mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
140 lines
3.7 KiB
Vue
140 lines
3.7 KiB
Vue
<template>
|
|
<aside>
|
|
<Sidebar collapsible="icon">
|
|
<SidebarHeader class="p-0 border-0">
|
|
<button
|
|
class="h-[53px] flex items-center gap-2.5 px-3.5 w-full border-b border-border text-foreground hover:bg-accent/50 transition-colors group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:px-0"
|
|
@click="router.push(backToChatRoute)"
|
|
>
|
|
<ChevronLeft
|
|
class="size-3 shrink-0"
|
|
/>
|
|
<span class="text-xs font-semibold group-data-[collapsible=icon]:hidden">
|
|
{{ t('sidebar.settings') }}
|
|
</span>
|
|
</button>
|
|
</SidebarHeader>
|
|
|
|
<SidebarContent>
|
|
<SidebarGroup class="px-2 py-2.5">
|
|
<SidebarGroupContent>
|
|
<SidebarMenu class="gap-0.5">
|
|
<SidebarMenuItem
|
|
v-for="item in navItems"
|
|
:key="item.name"
|
|
>
|
|
<SidebarMenuButton
|
|
:tooltip="item.title"
|
|
:is-active="isItemActive(item.name)"
|
|
:aria-current="isItemActive(item.name) ? 'page' : undefined"
|
|
class="h-9 gap-2 relative before:absolute before:w-0.5 before:top-1.5 before:bottom-1.5 before:left-0 before:rounded-full data-[active=true]:before:bg-[#8B56E3]"
|
|
@click="router.push({ name: item.name })"
|
|
>
|
|
<component
|
|
:is="item.icon"
|
|
class="size-3.5 ml-1.5"
|
|
/>
|
|
<span class="text-xs font-medium">{{ item.title }}</span>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
</SidebarMenu>
|
|
</SidebarGroupContent>
|
|
</SidebarGroup>
|
|
</SidebarContent>
|
|
</Sidebar>
|
|
</aside>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, type Component } from 'vue'
|
|
import { storeToRefs } from 'pinia'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { ChevronLeft, Bot, Boxes, Globe, Brain, Volume2, Mail, AppWindow, ChartLine, User } from 'lucide-vue-next'
|
|
import { useChatSelectionStore } from '@/store/chat-selection'
|
|
import {
|
|
Sidebar,
|
|
SidebarContent,
|
|
SidebarGroup,
|
|
SidebarGroupContent,
|
|
SidebarHeader,
|
|
SidebarMenu,
|
|
SidebarMenuButton,
|
|
SidebarMenuItem,
|
|
} from '@memohai/ui'
|
|
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const { t } = useI18n()
|
|
const selectionStore = useChatSelectionStore()
|
|
const { currentBotId, sessionId } = storeToRefs(selectionStore)
|
|
|
|
const backToChatRoute = computed(() => {
|
|
const botId = (currentBotId.value ?? '').trim()
|
|
const targetSessionId = (sessionId.value ?? '').trim()
|
|
if (!botId) return { name: 'home' as const }
|
|
return {
|
|
name: 'chat' as const,
|
|
params: {
|
|
botId,
|
|
sessionId: targetSessionId || undefined,
|
|
},
|
|
}
|
|
})
|
|
|
|
function isItemActive(name: string): boolean {
|
|
if (name === 'bots') {
|
|
return route.path.startsWith('/settings/bots')
|
|
}
|
|
return route.name === name
|
|
}
|
|
|
|
const navItems = computed<{ title: string; name: string; icon: Component }[]>(() => [
|
|
{
|
|
title: t('sidebar.bots'),
|
|
name: 'bots',
|
|
icon: Bot,
|
|
},
|
|
{
|
|
title: t('sidebar.providers'),
|
|
name: 'providers',
|
|
icon: Boxes,
|
|
},
|
|
{
|
|
title: t('sidebar.webSearch'),
|
|
name: 'web-search',
|
|
icon: Globe,
|
|
},
|
|
{
|
|
title: t('sidebar.memory'),
|
|
name: 'memory',
|
|
icon: Brain,
|
|
},
|
|
{
|
|
title: t('sidebar.speech'),
|
|
name: 'speech',
|
|
icon: Volume2,
|
|
},
|
|
{
|
|
title: t('sidebar.email'),
|
|
name: 'email',
|
|
icon: Mail,
|
|
},
|
|
{
|
|
title: t('sidebar.browser'),
|
|
name: 'browser',
|
|
icon: AppWindow,
|
|
},
|
|
{
|
|
title: t('sidebar.usage'),
|
|
name: 'usage',
|
|
icon: ChartLine,
|
|
},
|
|
{
|
|
title: t('sidebar.profile'),
|
|
name: 'profile',
|
|
icon: User,
|
|
},
|
|
])
|
|
</script>
|