2025-12-18 13:50:39 +08:00
|
|
|
# Pinia Stores Documentation
|
|
|
|
|
|
|
|
|
|
This directory contains all Pinia stores for the Sub2API frontend application.
|
|
|
|
|
|
|
|
|
|
## Stores Overview
|
|
|
|
|
|
|
|
|
|
### 1. Auth Store (`auth.ts`)
|
|
|
|
|
|
|
|
|
|
Manages user authentication state, login/logout, and token persistence.
|
|
|
|
|
|
|
|
|
|
**State:**
|
2025-12-25 08:41:43 -08:00
|
|
|
|
2025-12-18 13:50:39 +08:00
|
|
|
- `user: User | null` - Current authenticated user
|
|
|
|
|
- `token: string | null` - JWT authentication token
|
|
|
|
|
|
|
|
|
|
**Computed:**
|
2025-12-25 08:41:43 -08:00
|
|
|
|
2025-12-18 13:50:39 +08:00
|
|
|
- `isAuthenticated: boolean` - Whether user is currently authenticated
|
|
|
|
|
|
|
|
|
|
**Actions:**
|
2025-12-25 08:41:43 -08:00
|
|
|
|
2025-12-18 13:50:39 +08:00
|
|
|
- `login(credentials)` - Authenticate user with username/password
|
|
|
|
|
- `register(userData)` - Register new user account
|
|
|
|
|
- `logout()` - Clear authentication and logout
|
|
|
|
|
- `checkAuth()` - Restore session from localStorage
|
|
|
|
|
- `refreshUser()` - Fetch latest user data from server
|
|
|
|
|
|
|
|
|
|
### 2. App Store (`app.ts`)
|
|
|
|
|
|
|
|
|
|
Manages global UI state including sidebar, loading indicators, and toast notifications.
|
|
|
|
|
|
|
|
|
|
**State:**
|
2025-12-25 08:41:43 -08:00
|
|
|
|
2025-12-18 13:50:39 +08:00
|
|
|
- `sidebarCollapsed: boolean` - Sidebar collapsed state
|
|
|
|
|
- `loading: boolean` - Global loading state
|
|
|
|
|
- `toasts: Toast[]` - Active toast notifications
|
|
|
|
|
|
|
|
|
|
**Computed:**
|
2025-12-25 08:41:43 -08:00
|
|
|
|
2025-12-18 13:50:39 +08:00
|
|
|
- `hasActiveToasts: boolean` - Whether any toasts are active
|
|
|
|
|
|
|
|
|
|
**Actions:**
|
2025-12-25 08:41:43 -08:00
|
|
|
|
2025-12-18 13:50:39 +08:00
|
|
|
- `toggleSidebar()` - Toggle sidebar state
|
|
|
|
|
- `setSidebarCollapsed(collapsed)` - Set sidebar state explicitly
|
|
|
|
|
- `setLoading(isLoading)` - Set loading state
|
|
|
|
|
- `showToast(type, message, duration?)` - Show toast notification
|
|
|
|
|
- `showSuccess(message, duration?)` - Show success toast
|
|
|
|
|
- `showError(message, duration?)` - Show error toast
|
|
|
|
|
- `showInfo(message, duration?)` - Show info toast
|
|
|
|
|
- `showWarning(message, duration?)` - Show warning toast
|
|
|
|
|
- `hideToast(id)` - Hide specific toast
|
|
|
|
|
- `clearAllToasts()` - Clear all toasts
|
|
|
|
|
- `withLoading(operation)` - Execute async operation with loading state
|
|
|
|
|
- `withLoadingAndError(operation, errorMessage?)` - Execute with loading and error handling
|
|
|
|
|
- `reset()` - Reset store to defaults
|
|
|
|
|
|
|
|
|
|
## Usage Examples
|
|
|
|
|
|
|
|
|
|
### Auth Store
|
|
|
|
|
|
|
|
|
|
```typescript
|
2025-12-25 08:41:43 -08:00
|
|
|
import { useAuthStore } from '@/stores'
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// In component setup
|
2025-12-25 08:41:43 -08:00
|
|
|
const authStore = useAuthStore()
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// Initialize on app startup
|
2025-12-25 08:41:43 -08:00
|
|
|
authStore.checkAuth()
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// Login
|
|
|
|
|
try {
|
2025-12-25 08:41:43 -08:00
|
|
|
await authStore.login({ username: 'user', password: 'pass' })
|
|
|
|
|
console.log('Logged in:', authStore.user)
|
2025-12-18 13:50:39 +08:00
|
|
|
} catch (error) {
|
2025-12-25 08:41:43 -08:00
|
|
|
console.error('Login failed:', error)
|
2025-12-18 13:50:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check authentication
|
|
|
|
|
if (authStore.isAuthenticated) {
|
2025-12-25 08:41:43 -08:00
|
|
|
console.log('User is logged in:', authStore.user?.username)
|
2025-12-18 13:50:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Logout
|
2025-12-25 08:41:43 -08:00
|
|
|
authStore.logout()
|
2025-12-18 13:50:39 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### App Store
|
|
|
|
|
|
|
|
|
|
```typescript
|
2025-12-25 08:41:43 -08:00
|
|
|
import { useAppStore } from '@/stores'
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// In component setup
|
2025-12-25 08:41:43 -08:00
|
|
|
const appStore = useAppStore()
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// Sidebar control
|
2025-12-25 08:41:43 -08:00
|
|
|
appStore.toggleSidebar()
|
|
|
|
|
appStore.setSidebarCollapsed(true)
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// Loading state
|
2025-12-25 08:41:43 -08:00
|
|
|
appStore.setLoading(true)
|
2025-12-18 13:50:39 +08:00
|
|
|
// ... do work
|
2025-12-25 08:41:43 -08:00
|
|
|
appStore.setLoading(false)
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// Or use helper
|
|
|
|
|
await appStore.withLoading(async () => {
|
2025-12-25 08:41:43 -08:00
|
|
|
const data = await fetchData()
|
|
|
|
|
return data
|
|
|
|
|
})
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// Toast notifications
|
2025-12-25 08:41:43 -08:00
|
|
|
appStore.showSuccess('Operation completed!')
|
|
|
|
|
appStore.showError('Something went wrong!', 5000)
|
|
|
|
|
appStore.showInfo('FYI: This is informational')
|
|
|
|
|
appStore.showWarning('Be careful!')
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// Custom toast
|
2025-12-25 08:41:43 -08:00
|
|
|
const toastId = appStore.showToast('info', 'Custom message', undefined) // No auto-dismiss
|
2025-12-18 13:50:39 +08:00
|
|
|
// Later...
|
2025-12-25 08:41:43 -08:00
|
|
|
appStore.hideToast(toastId)
|
2025-12-18 13:50:39 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Combined Usage in Vue Component
|
|
|
|
|
|
|
|
|
|
```vue
|
|
|
|
|
<script setup lang="ts">
|
2025-12-25 08:41:43 -08:00
|
|
|
import { useAuthStore, useAppStore } from '@/stores'
|
|
|
|
|
import { onMounted } from 'vue'
|
2025-12-18 13:50:39 +08:00
|
|
|
|
2025-12-25 08:41:43 -08:00
|
|
|
const authStore = useAuthStore()
|
|
|
|
|
const appStore = useAppStore()
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
// Check for existing session
|
2025-12-25 08:41:43 -08:00
|
|
|
authStore.checkAuth()
|
|
|
|
|
})
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
async function handleLogin(username: string, password: string) {
|
|
|
|
|
try {
|
|
|
|
|
await appStore.withLoading(async () => {
|
2025-12-25 08:41:43 -08:00
|
|
|
await authStore.login({ username, password })
|
|
|
|
|
})
|
|
|
|
|
appStore.showSuccess('Welcome back!')
|
2025-12-18 13:50:39 +08:00
|
|
|
} catch (error) {
|
2025-12-25 08:41:43 -08:00
|
|
|
appStore.showError('Login failed. Please check your credentials.')
|
2025-12-18 13:50:39 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleLogout() {
|
2025-12-25 08:41:43 -08:00
|
|
|
authStore.logout()
|
|
|
|
|
appStore.showInfo('You have been logged out.')
|
2025-12-18 13:50:39 +08:00
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div>
|
2025-12-25 08:41:43 -08:00
|
|
|
<button @click="appStore.toggleSidebar">Toggle Sidebar</button>
|
|
|
|
|
|
2025-12-18 13:50:39 +08:00
|
|
|
<div v-if="appStore.loading">Loading...</div>
|
2025-12-25 08:41:43 -08:00
|
|
|
|
2025-12-18 13:50:39 +08:00
|
|
|
<div v-if="authStore.isAuthenticated">
|
|
|
|
|
Welcome, {{ authStore.user?.username }}!
|
|
|
|
|
<button @click="handleLogout">Logout</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else>
|
|
|
|
|
<button @click="handleLogin('user', 'pass')">Login</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Persistence
|
|
|
|
|
|
|
|
|
|
- **Auth Store**: Token and user data are automatically persisted to `localStorage`
|
|
|
|
|
- Keys: `auth_token`, `auth_user`
|
|
|
|
|
- Restored on `checkAuth()` call
|
|
|
|
|
- **App Store**: No persistence (UI state resets on page reload)
|
|
|
|
|
|
|
|
|
|
## TypeScript Support
|
|
|
|
|
|
|
|
|
|
All stores are fully typed with TypeScript. Import types from `@/types`:
|
|
|
|
|
|
|
|
|
|
```typescript
|
2025-12-25 08:41:43 -08:00
|
|
|
import type { User, Toast, ToastType } from '@/types'
|
2025-12-18 13:50:39 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Testing
|
|
|
|
|
|
|
|
|
|
Stores can be reset to initial state:
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
// Auth store
|
2025-12-25 08:41:43 -08:00
|
|
|
authStore.logout() // Clears all auth state
|
2025-12-18 13:50:39 +08:00
|
|
|
|
|
|
|
|
// App store
|
2025-12-25 08:41:43 -08:00
|
|
|
appStore.reset() // Resets to defaults
|
2025-12-18 13:50:39 +08:00
|
|
|
```
|