Newer
Older
navi-1 / webclient / src / App.vue
<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>