<template>
<div class="app-shell">
<!-- Mobile sidebar backdrop -->
<div
v-if="sidebarOpen"
class="sidebar-backdrop"
@click="sidebarOpen = false"
/>
<!-- Sidebar (desktop: always visible; mobile: drawer) -->
<AppSidebar
:class="{ 'is-mobile-open': sidebarOpen }"
@close="sidebarOpen = false"
/>
<!-- Main content -->
<div class="app-main">
<Transition name="fade" mode="out-in">
<WelcomeScreen
v-if="showWelcome"
key="welcome"
/>
<ChatArea
v-else
key="chat"
@toggle-sidebar="sidebarOpen = !sidebarOpen"
/>
</Transition>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { useSessionsStore } from '@/stores/sessions'
import { useProfilesStore } from '@/stores/profiles'
import { useChatStore } from '@/stores/chat'
import AppSidebar from '@/components/sidebar/AppSidebar.vue'
import ChatArea from '@/components/chat/ChatArea.vue'
import WelcomeScreen from '@/components/ui/WelcomeScreen.vue'
const sessionsStore = useSessionsStore()
const profilesStore = useProfilesStore()
const chatStore = useChatStore()
const sidebarOpen = ref(false)
const showWelcome = computed(
() => sessionsStore.sessions.length === 0 && !sessionsStore.loading
)
onMounted(async () => {
await Promise.all([
profilesStore.fetchProfiles(),
sessionsStore.fetchSessions()
])
const hash = location.hash.slice(1)
const target = hash && sessionsStore.sessions.find(s => s.session_id === hash)
? hash
: sessionsStore.sessions[0]?.session_id
if (target) {
await chatStore.loadSession(target)
}
})
// Hash-based routing: browser back/forward
window.addEventListener('hashchange', () => {
const id = location.hash.slice(1)
if (id && id !== chatStore.currentId) {
chatStore.loadSession(id)
}
})
</script>
<style scoped>
.app-shell {
display: flex;
flex: 1 1 0;
min-height: 0;
min-width: 0;
overflow: hidden;
}
.sidebar-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.6);
z-index: 99;
@media (max-width: 768px) {
display: block;
}
}
</style>