profileShare

rasmusjy / splitapp-frontend-vue

Read-only snapshot

No repository description.

main default branch 96 files Expires Sep 13, 2026, 9:06 AM
App.vue 3,052 bytes
1 <script setup lang="ts">
2 import { useAuthStore } from '@/stores/auth'
3 import { useRouter } from 'vue-router'
4 import { useI18n } from 'vue-i18n'
5 import AccountService from '@/services/AccountService'
6 import ToastContainer from '@/components/ToastContainer.vue'
7 import LangSwitcher from '@/components/LangSwitcher.vue'
8
9 const authStore = useAuthStore()
10 const router = useRouter()
11 const { t } = useI18n()
12
13 function userInitials() {
14 const name = authStore.userName || ''
15 const parts = name.split(' ')
16 if (parts.length >= 2) return (parts[0]![0]! + parts[1]![0]!).toUpperCase()
17 return name.substring(0, 2).toUpperCase()
18 }
19
20 async function handleLogout() {
21 if (authStore.refreshToken) {
22 await AccountService.logoutAsync(authStore.refreshToken)
23 }
24 authStore.logout()
25 router.push({ name: 'Home' })
26 }
27 </script>
28
29 <template>
30 <nav class="navbar navbar-expand-lg sa-navbar">
31 <div class="container">
32 <RouterLink class="navbar-brand sa-navbar-brand" :to="{ name: 'Home' }">
33 <span class="sa-navbar-logo-icon">
34 <i class="bi bi-airplane-fill"></i>
35 </span>
36 SplitApp
37 </RouterLink>
38
39 <button
40 class="navbar-toggler border-0"
41 type="button"
42 data-bs-toggle="collapse"
43 data-bs-target="#navbarNav"
44 >
45 <span class="navbar-toggler-icon"></span>
46 </button>
47
48 <div class="collapse navbar-collapse" id="navbarNav">
49 <ul class="navbar-nav me-auto" v-if="authStore.isAuthenticated">
50 <li class="nav-item">
51 <RouterLink class="nav-link" :to="{ name: 'TripsIndex' }">
52 <i class="bi bi-suitcase-lg me-1"></i>{{ t('nav.trips') }}
53 </RouterLink>
54 </li>
55 </ul>
56
57 <div class="navbar-nav ms-auto align-items-center">
58 <LangSwitcher />
59 <template v-if="authStore.isAuthenticated">
60 <button class="sa-nav-avatar-btn" @click="handleLogout" :title="t('nav.logout')">
61 <span class="sa-avatar sa-avatar-sm sa-avatar-1">{{ userInitials() }}</span>
62 <span>{{ authStore.userName }}</span>
63 <i class="bi bi-box-arrow-right ms-1"></i>
64 </button>
65 </template>
66 <div v-else class="sa-navbar-auth-btns">
67 <RouterLink class="nav-link" :to="{ name: 'Login' }">{{ t('nav.signIn') }}</RouterLink>
68 <RouterLink class="sa-btn sa-btn-primary sa-btn-sm sa-btn-pill" :to="{ name: 'Register' }">
69 {{ t('nav.getStarted') }}
70 </RouterLink>
71 </div>
72 </div>
73 </div>
74 </div>
75 </nav>
76
77 <main class="container" style="padding-top: var(--sa-space-6); padding-bottom: var(--sa-space-8);">
78 <RouterView />
79 </main>
80
81 <ToastContainer />
82 </template>
83
84 <style scoped>
85 .sa-navbar-logo-icon {
86 display: inline-flex;
87 align-items: center;
88 justify-content: center;
89 width: 32px;
90 height: 32px;
91 border-radius: 10px;
92 background: linear-gradient(135deg, #e8604c 0%, #d4456a 100%);
93 color: #fff;
94 font-size: 0.875rem;
95 margin-right: 8px;
96 }
97 </style>
98