AppSidebar.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <script lang="ts" setup>
  2. import {MessageSquareOff, MoreHorizontal, Plus, Trash} from "lucide-vue-next"
  3. import {
  4. Sidebar,
  5. SidebarContent,
  6. SidebarGroup,
  7. SidebarGroupAction,
  8. SidebarGroupContent,
  9. SidebarGroupLabel,
  10. SidebarMenu,
  11. SidebarMenuAction,
  12. SidebarMenuButton,
  13. SidebarMenuItem
  14. } from '@/Packages/Shadcn/Components/ui/sidebar'
  15. import {
  16. DropdownMenu,
  17. DropdownMenuContent,
  18. DropdownMenuItem,
  19. DropdownMenuTrigger
  20. } from "@/Packages/Shadcn/Components/ui/dropdown-menu";
  21. import {Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from '@/Packages/Shadcn/Components/ui/empty'
  22. import {Skeleton} from "@/Packages/Shadcn/Components/ui/skeleton"
  23. import {router, usePage} from "@inertiajs/vue3";
  24. import {useEcho} from "@laravel/echo-vue";
  25. import {computed} from "vue";
  26. const page = usePage()
  27. const {user} = defineProps({
  28. user: {
  29. type: Object,
  30. default: () => null,
  31. },
  32. chats: {
  33. type: Array,
  34. default: () => [],
  35. },
  36. })
  37. const chat = computed(() => page.props.chat ?? null)
  38. useEcho(`App.Models.User.${user.id}`, '.ChatUpdated', (e) => router.reload())
  39. </script>
  40. <template>
  41. <Sidebar variant="floating">
  42. <SidebarContent>
  43. <SidebarGroup>
  44. <SidebarGroupLabel>Application</SidebarGroupLabel>
  45. <SidebarGroupAction class="rounded-full cursor-pointer" title="New Chat"
  46. @click="() => router.visit(route('chats.index'))">
  47. <Plus/>
  48. <span class="sr-only">New Chat</span>
  49. </SidebarGroupAction>
  50. <SidebarGroupContent>
  51. <template v-if="chats.length === 0">
  52. <Empty class="border border-dashed">
  53. <EmptyHeader>
  54. <EmptyMedia variant="icon">
  55. <MessageSquareOff/>
  56. </EmptyMedia>
  57. <EmptyTitle>Нет чатов</EmptyTitle>
  58. <EmptyDescription>Список чатов пока пуст</EmptyDescription>
  59. </EmptyHeader>
  60. </Empty>
  61. </template>
  62. <template v-else>
  63. <SidebarMenu>
  64. <SidebarMenuItem v-for="item in chats" :key="item.id">
  65. <SidebarMenuButton :variant="item.id == chat?.id ? 'outline' : 'default'"
  66. class="cursor-pointer"
  67. @click="() => router.visit(route('chats.show', item.id))">
  68. <Skeleton class="h-4 w-full rounded-full" v-if="!item.title"/>
  69. <div v-else class="text-nowrap overflow-hidden text-ellipsis" :title="item.title">{{ item.title }}</div>
  70. </SidebarMenuButton>
  71. <DropdownMenu>
  72. <DropdownMenuTrigger asChild>
  73. <SidebarMenuAction class="rounded-full cursor-pointer">
  74. <MoreHorizontal/>
  75. </SidebarMenuAction>
  76. </DropdownMenuTrigger>
  77. <DropdownMenuContent align="center" side="right">
  78. <DropdownMenuItem class="text-primary cursor-pointer"
  79. @click="() => router.delete(route('chats.destroy', item.id), { preserveScroll: false, preserveState: false })">
  80. <Trash/>
  81. <span>Удалить чат</span>
  82. </DropdownMenuItem>
  83. </DropdownMenuContent>
  84. </DropdownMenu>
  85. </SidebarMenuItem>
  86. </SidebarMenu>
  87. </template>
  88. </SidebarGroupContent>
  89. </SidebarGroup>
  90. </SidebarContent>
  91. </Sidebar>
  92. </template>