feat(frontend): Vue 3 + wa-sqlite + sync engine + auth + layouts
- package.json with Vue 3, Pinia, vue-router, wa-sqlite, Tailwind CSS 4, Vite - wa-sqlite database layer with IDBBatchAtomicVFS (offline-first) - Full schema mirroring backend tables (vehicles, orders, invoices, etc.) - SyncEngine: fullSync, incrementalSync, pushQueue for offline queue - Auth store with JWT parsing, login/register, plan tier detection - Router with all routes and auth navigation guards - AppLayout (sidebar desktop / bottom nav mobile) + AuthLayout - Login/Register views connected to API contract - SyncIndicator component (online/offline status) - Reactive SQL query composable (useSqlQuery) - Placeholder views for dashboard, orders, vehicles, appointments, catalog, settings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
27
frontend/src/router/index.js
Normal file
27
frontend/src/router/index.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { useAuthStore } from '../stores/auth.js'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{ path: '/login', component: () => import('../views/auth/LoginView.vue'), meta: { layout: 'auth' } },
|
||||
{ path: '/register', component: () => import('../views/auth/RegisterView.vue'), meta: { layout: 'auth' } },
|
||||
{ path: '/dashboard', component: () => import('../views/dashboard/DashboardView.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/orders', component: () => import('../views/orders/OrdersListView.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/orders/new', component: () => import('../views/orders/OrderCreateView.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/orders/:id', component: () => import('../views/orders/OrderDetailView.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/vehicles', component: () => import('../views/vehicles/VehiclesListView.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/appointments', component: () => import('../views/appointments/AppointmentsView.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/catalog', component: () => import('../views/catalog/CatalogView.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/settings', component: () => import('../views/settings/SettingsView.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/p/:token', component: () => import('../views/client/DevizPublicView.vue') },
|
||||
{ path: '/', redirect: '/dashboard' },
|
||||
],
|
||||
scrollBehavior: () => ({ top: 0 })
|
||||
})
|
||||
|
||||
router.beforeEach((to) => {
|
||||
if (to.meta.requiresAuth && !useAuthStore().isAuthenticated) return '/login'
|
||||
})
|
||||
|
||||
export default router
|
||||
Reference in New Issue
Block a user