Files
TapTrack-Hub/frontend/src/stores/auth.ts
kevin-asprec 73a17aaf9a feat(phase-1): TapTrack Hub initial scaffold
Full project scaffold for TapTrack Hub — cloud SaaS control plane
for managing on-prem TapTrack school deployments.

## Infrastructure
- Docker Compose: backend (gunicorn+uvicorn), Celery worker + beat,
  frontend (Vite build + nginx), PostgreSQL 15, Redis 7, nginx proxy
- Dockerfile for backend and frontend, nginx reverse proxy config

## Backend (FastAPI + SQLAlchemy async + Celery)
Database schema (10 tables):
  hub_users, schools, licenses, sms_jobs, sms_credit_ledger,
  invoices, invoice_line_items, school_subscriptions,
  support_tickets, ticket_replies, audit_logs, announcements

Auth: JWT (python-jose) + bcrypt + role-based FastAPI dependencies
  (get_current_user, require_super_admin, require_school_admin)

Routers (11): auth, schools, licenses, sms, billing, tickets,
  users, dashboard, school_portal, announcements, sync

Celery tasks (6):
  sms.process_queue, billing.generate_monthly_invoices,
  billing.send_invoice_email, billing.check_overdue,
  license.check_expiry, reports.send_monthly_reports

Services: SMTP email helper (smtplib + Jinja2)
Seed script: creates super admin admin@taptrack.io

## Frontend (Vue 3 + Vite + Pinia + Tailwind CSS)
Router: 14 routes across super admin + school portal layouts
Stores: Pinia auth store with localStorage persistence
API client: full axios client for all backend endpoints
Layouts: AppLayout (super admin), PortalLayout (school), AuthLayout
Components: AppSidebar, PortalSidebar, SidebarItem, KpiCard,
  StatusBadge, ToastStack
Pages: Login, Dashboard, Schools, SchoolDetail, Licenses, SMS,
  Billing, Tickets, TicketDetail, Users, Announcements, 404
Portal pages: Overview, Billing, SMS Reports, Tickets, Profile

## PAUL Planning Files
- .paul/ROADMAP.md: full 15-phase roadmap with detailed scope
- .paul/STATE.md: current position, tech stack, architecture notes
- .paul/phases/01-setup/01-PLAN.md: complete Phase 1 plan (done)
- .paul/phases/02 through 15: README stubs for all future phases
2026-03-16 07:26:06 +08:00

51 lines
1.9 KiB
TypeScript

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useAuthStore = defineStore('auth', () => {
const token = ref<string | null>(null)
const role = ref<string | null>(null)
const userId = ref<string | null>(null)
const fullName = ref<string | null>(null)
const schoolId = ref<string | null>(null)
const isAuthenticated = computed(() => !!token.value)
const isSuperAdmin = computed(() => role.value === 'super_admin')
const isSchoolAdmin = computed(() => role.value === 'school_admin')
function loadFromStorage() {
token.value = localStorage.getItem('hub_token')
role.value = localStorage.getItem('hub_role')
userId.value = localStorage.getItem('hub_user_id')
fullName.value = localStorage.getItem('hub_full_name')
schoolId.value = localStorage.getItem('hub_school_id')
}
function setAuth(data: { access_token: string; role: string; user_id: string; full_name: string; school_id: string | null }) {
token.value = data.access_token
role.value = data.role
userId.value = data.user_id
fullName.value = data.full_name
schoolId.value = data.school_id
localStorage.setItem('hub_token', data.access_token)
localStorage.setItem('hub_role', data.role)
localStorage.setItem('hub_user_id', data.user_id)
localStorage.setItem('hub_full_name', data.full_name)
if (data.school_id) localStorage.setItem('hub_school_id', data.school_id)
}
function logout() {
token.value = null
role.value = null
userId.value = null
fullName.value = null
schoolId.value = null
localStorage.removeItem('hub_token')
localStorage.removeItem('hub_role')
localStorage.removeItem('hub_user_id')
localStorage.removeItem('hub_full_name')
localStorage.removeItem('hub_school_id')
}
return { token, role, userId, fullName, schoolId, isAuthenticated, isSuperAdmin, isSchoolAdmin, loadFromStorage, setAuth, logout }
})