scaffold: Vue 3 frontend — router, stores, views, composables, layouts
Complete frontend skeleton: Vite + Vue 3 + TypeScript + Tailwind CSS, Pinia stores (auth, server, wipe, plugins), authenticated API composable, full route tree with auth guards, DashboardLayout with sidebar nav, 23 view stubs across auth/admin/public, all TypeScript interfaces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
163
frontend/src/router/index.ts
Normal file
163
frontend/src/router/index.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
// Auth routes (no layout)
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('@/views/auth/LoginView.vue'),
|
||||
meta: { guest: true },
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
name: 'register',
|
||||
component: () => import('@/views/auth/RegisterView.vue'),
|
||||
meta: { guest: true },
|
||||
},
|
||||
{
|
||||
path: '/setup',
|
||||
name: 'setup-wizard',
|
||||
component: () => import('@/views/auth/SetupWizardView.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
|
||||
// Admin dashboard routes (with sidebar layout)
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('@/components/layout/DashboardLayout.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'dashboard',
|
||||
component: () => import('@/views/admin/DashboardView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'server',
|
||||
name: 'server',
|
||||
component: () => import('@/views/admin/ServerView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'console',
|
||||
name: 'console',
|
||||
component: () => import('@/views/admin/ConsoleView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'players',
|
||||
name: 'players',
|
||||
component: () => import('@/views/admin/PlayersView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'plugins',
|
||||
name: 'plugins',
|
||||
component: () => import('@/views/admin/PluginsView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'wipes',
|
||||
name: 'wipes',
|
||||
component: () => import('@/views/admin/WipesView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'wipes/profiles',
|
||||
name: 'wipe-profiles',
|
||||
component: () => import('@/views/admin/WipeProfilesView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'wipes/calendar',
|
||||
name: 'wipe-calendar',
|
||||
component: () => import('@/views/admin/WipeCalendarView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'wipes/history',
|
||||
name: 'wipe-history',
|
||||
component: () => import('@/views/admin/WipeHistoryView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'maps',
|
||||
name: 'maps',
|
||||
component: () => import('@/views/admin/MapsView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'chat',
|
||||
name: 'chat',
|
||||
component: () => import('@/views/admin/ChatLogView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'analytics',
|
||||
name: 'analytics',
|
||||
component: () => import('@/views/admin/AnalyticsView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'notifications',
|
||||
name: 'notifications',
|
||||
component: () => import('@/views/admin/NotificationsView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'team',
|
||||
name: 'team',
|
||||
component: () => import('@/views/admin/TeamView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'store/manage',
|
||||
name: 'store-manage',
|
||||
component: () => import('@/views/admin/StoreManageView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'modules',
|
||||
name: 'modules',
|
||||
component: () => import('@/views/admin/ModuleStoreView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
name: 'settings',
|
||||
component: () => import('@/views/admin/SettingsView.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Public server site routes (different layout)
|
||||
{
|
||||
path: '/s/:subdomain',
|
||||
component: () => import('@/components/layout/PublicLayout.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'public-server',
|
||||
component: () => import('@/views/public/ServerInfoView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'store',
|
||||
name: 'public-store',
|
||||
component: () => import('@/views/public/StoreView.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Status page
|
||||
{
|
||||
path: '/status',
|
||||
name: 'status',
|
||||
component: () => import('@/views/public/StatusPageView.vue'),
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
})
|
||||
|
||||
// Auth guard
|
||||
router.beforeEach((to, _from, next) => {
|
||||
const auth = useAuthStore()
|
||||
|
||||
if (to.meta.requiresAuth && !auth.isAuthenticated) {
|
||||
next({ name: 'login', query: { redirect: to.fullPath } })
|
||||
} else if (to.meta.guest && auth.isAuthenticated) {
|
||||
next({ name: 'dashboard' })
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
Reference in New Issue
Block a user