feat(portal): strip Vuexy demo content and create clean portal shell

Remove all demo pages, dialogs, sidebar navigation, and layout components.
Create minimal top-bar portal layout with auth-aware navigation, placeholder
pages for volunteer registration, dashboard, shifts, profile, artist advance,
and login. Add Pinia auth store, axios with Sanctum support, and router guards.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 17:38:55 +02:00
parent 853271f0c2
commit 87f0bcce6e
54 changed files with 558 additions and 4185 deletions

View File

@@ -0,0 +1,73 @@
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { apiClient } from '@/lib/axios'
interface PortalUser {
id: string
name: string
email: string
}
const TOKEN_KEY = 'crewli_portal_token'
export const useAuthStore = defineStore('auth', () => {
const token = ref<string | null>(localStorage.getItem(TOKEN_KEY))
const user = ref<PortalUser | null>(null)
const isInitialized = ref(false)
const isAuthenticated = computed(() => !!token.value && !!user.value)
function setToken(newToken: string) {
token.value = newToken
localStorage.setItem(TOKEN_KEY, newToken)
}
function setUser(data: PortalUser) {
user.value = data
}
function logout() {
token.value = null
user.value = null
localStorage.removeItem(TOKEN_KEY)
}
let initializePromise: Promise<void> | null = null
function initialize(): Promise<void> {
if (isInitialized.value) return Promise.resolve()
if (!initializePromise) {
initializePromise = doInitialize()
}
return initializePromise
}
async function doInitialize(): Promise<void> {
if (!token.value) {
isInitialized.value = true
return
}
try {
const { data } = await apiClient.get<{ success: boolean; data: PortalUser }>('/auth/me')
setUser(data.data)
}
catch {
logout()
}
finally {
isInitialized.value = true
}
}
return {
token,
user,
isAuthenticated,
isInitialized,
setToken,
setUser,
logout,
initialize,
}
})