Initial project scaffold

Full-stack homeschool web app with FastAPI backend, Vue 3 frontend,
MySQL database, and Docker Compose orchestration. Includes JWT auth,
WebSocket real-time TV dashboard, schedule builder, activity logging,
and multi-child support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 22:56:31 -08:00
parent 93e0494864
commit 417b3adfe8
68 changed files with 3919 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import api from '@/composables/useApi'
export const useAuthStore = defineStore('auth', () => {
const accessToken = ref(localStorage.getItem('access_token') || null)
const user = ref(null)
const isAuthenticated = computed(() => !!accessToken.value)
function setToken(token) {
accessToken.value = token
localStorage.setItem('access_token', token)
}
function clearToken() {
accessToken.value = null
user.value = null
localStorage.removeItem('access_token')
}
async function login(email, password) {
const res = await api.post('/api/auth/login', { email, password })
setToken(res.data.access_token)
await fetchMe()
}
async function register(email, password, fullName) {
const res = await api.post('/api/auth/register', {
email,
password,
full_name: fullName,
})
setToken(res.data.access_token)
await fetchMe()
}
async function logout() {
try {
await api.post('/api/auth/logout')
} catch (_) {
// ignore errors on logout
}
clearToken()
}
async function tryRefresh() {
try {
const res = await api.post('/api/auth/refresh')
setToken(res.data.access_token)
await fetchMe()
} catch (_) {
clearToken()
}
}
async function fetchMe() {
try {
const res = await api.get('/api/users/me')
user.value = res.data
} catch (_) {
clearToken()
}
}
return {
accessToken,
user,
isAuthenticated,
login,
register,
logout,
tryRefresh,
fetchMe,
}
})