- Create ApiError class with status helpers (isNotFound, etc.) - Create typed fetch wrapper with get/post/put/patch/delete methods - Auto-inject Authorization header from auth store - Handle 401 with automatic token refresh and retry - Add query parameter support and proper URL building - Add comprehensive tests (11 tests) Phase F0 progress: 6/8 tasks complete Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
195 lines
7.0 KiB
JSON
195 lines
7.0 KiB
JSON
{
|
|
"meta": {
|
|
"phaseId": "PHASE_F0",
|
|
"name": "Project Foundation",
|
|
"version": "1.0.0",
|
|
"created": "2026-01-30",
|
|
"lastUpdated": "2026-01-30",
|
|
"totalTasks": 8,
|
|
"completedTasks": 6,
|
|
"status": "in_progress"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "F0-001",
|
|
"name": "Initialize Vite project",
|
|
"description": "Create Vue 3 + TypeScript project with Vite",
|
|
"category": "setup",
|
|
"priority": 1,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": [],
|
|
"files": [
|
|
{"path": "package.json", "status": "create"},
|
|
{"path": "vite.config.ts", "status": "create"},
|
|
{"path": "tsconfig.json", "status": "create"}
|
|
],
|
|
"details": [
|
|
"npm create vite@latest . -- --template vue-ts",
|
|
"Configure path aliases (@/ for src/)",
|
|
"Set up TypeScript strict mode"
|
|
],
|
|
"notes": "Completed in initial scaffold commit b9b803d"
|
|
},
|
|
{
|
|
"id": "F0-002",
|
|
"name": "Install and configure Tailwind",
|
|
"description": "Set up Tailwind CSS with custom theme",
|
|
"category": "styling",
|
|
"priority": 2,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["F0-001"],
|
|
"files": [
|
|
{"path": "tailwind.config.js", "status": "create"},
|
|
{"path": "src/assets/main.css", "status": "create"}
|
|
],
|
|
"details": [
|
|
"Install tailwindcss, postcss, autoprefixer",
|
|
"Configure content paths",
|
|
"Add Mantimon color palette (Pokemon-inspired)"
|
|
],
|
|
"notes": "Completed in initial scaffold - using Tailwind v4 with @tailwindcss/postcss"
|
|
},
|
|
{
|
|
"id": "F0-003",
|
|
"name": "Set up Vue Router",
|
|
"description": "Configure routing with guards and lazy loading",
|
|
"category": "setup",
|
|
"priority": 3,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["F0-001"],
|
|
"files": [
|
|
{"path": "src/router/index.ts", "status": "modify"},
|
|
{"path": "src/router/guards.ts", "status": "create"}
|
|
],
|
|
"details": [
|
|
"Define route structure per sitePlan",
|
|
"Create auth guard (requireAuth, requireGuest)",
|
|
"Create starter guard (redirect if no starter deck)",
|
|
"Configure lazy loading for heavy routes",
|
|
"Extract guards to separate file"
|
|
],
|
|
"notes": "Partial - router/index.ts exists with basic routes and inline guard. Needs guards.ts extraction and starter deck guard."
|
|
},
|
|
{
|
|
"id": "F0-004",
|
|
"name": "Set up Pinia stores",
|
|
"description": "Create store structure with persistence",
|
|
"category": "stores",
|
|
"priority": 4,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["F0-001"],
|
|
"files": [
|
|
{"path": "src/stores/auth.ts", "status": "modify"},
|
|
{"path": "src/stores/user.ts", "status": "create"},
|
|
{"path": "src/stores/ui.ts", "status": "create"}
|
|
],
|
|
"details": [
|
|
"Install pinia and pinia-plugin-persistedstate (done)",
|
|
"Update auth store for OAuth flow (not username/password)",
|
|
"Create user store skeleton (display_name, avatar, linked accounts)",
|
|
"Create UI store (loading states, toasts, modals)"
|
|
],
|
|
"notes": "Partial - auth.ts exists but uses username/password pattern instead of OAuth. Needs user.ts and ui.ts."
|
|
},
|
|
{
|
|
"id": "F0-005",
|
|
"name": "Create API client",
|
|
"description": "HTTP client with auth token injection and refresh",
|
|
"category": "api",
|
|
"priority": 5,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["F0-001", "F0-004"],
|
|
"files": [
|
|
{"path": "src/api/client.ts", "status": "create"},
|
|
{"path": "src/api/types.ts", "status": "create"}
|
|
],
|
|
"details": [
|
|
"Create fetch wrapper with base URL from config",
|
|
"Inject Authorization header from auth store",
|
|
"Handle 401 responses with automatic token refresh",
|
|
"Type API responses (ApiError, ApiResponse<T>)",
|
|
"Add request/response interceptor pattern"
|
|
],
|
|
"notes": "Not started. Critical for all backend communication."
|
|
},
|
|
{
|
|
"id": "F0-006",
|
|
"name": "Create Socket.IO client",
|
|
"description": "WebSocket connection manager",
|
|
"category": "api",
|
|
"priority": 6,
|
|
"completed": false,
|
|
"tested": false,
|
|
"dependencies": ["F0-001", "F0-004"],
|
|
"files": [
|
|
{"path": "src/socket/client.ts", "status": "create"},
|
|
{"path": "src/socket/types.ts", "status": "create"}
|
|
],
|
|
"details": [
|
|
"Install socket.io-client (done)",
|
|
"Create connection manager singleton",
|
|
"Configure auth token in handshake",
|
|
"Set up reconnection with exponential backoff",
|
|
"Create typed event emitters for game namespace"
|
|
],
|
|
"notes": "Not started. socket.io-client is installed."
|
|
},
|
|
{
|
|
"id": "F0-007",
|
|
"name": "Create app shell",
|
|
"description": "Basic layout with navigation",
|
|
"category": "components",
|
|
"priority": 7,
|
|
"completed": false,
|
|
"tested": false,
|
|
"dependencies": ["F0-001", "F0-002", "F0-003"],
|
|
"files": [
|
|
{"path": "src/App.vue", "status": "modify"},
|
|
{"path": "src/layouts/DefaultLayout.vue", "status": "create"},
|
|
{"path": "src/layouts/MinimalLayout.vue", "status": "create"},
|
|
{"path": "src/layouts/GameLayout.vue", "status": "create"},
|
|
{"path": "src/components/NavSidebar.vue", "status": "create"},
|
|
{"path": "src/components/NavBottomTabs.vue", "status": "create"},
|
|
{"path": "src/components/ui/LoadingOverlay.vue", "status": "create"},
|
|
{"path": "src/components/ui/ToastContainer.vue", "status": "create"}
|
|
],
|
|
"details": [
|
|
"Create DefaultLayout with sidebar (desktop) / bottom tabs (mobile)",
|
|
"Create MinimalLayout for login/auth pages (centered, no nav)",
|
|
"Create GameLayout for match page (full viewport, no nav)",
|
|
"Responsive nav: NavSidebar for md+, NavBottomTabs for mobile",
|
|
"Loading overlay component tied to UI store",
|
|
"Toast notification container tied to UI store"
|
|
],
|
|
"notes": "Partial - App.vue and AppHeader.vue exist but don't match sitePlan layout system."
|
|
},
|
|
{
|
|
"id": "F0-008",
|
|
"name": "Environment configuration",
|
|
"description": "Configure environment variables",
|
|
"category": "setup",
|
|
"priority": 8,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["F0-001"],
|
|
"files": [
|
|
{"path": ".env.development", "status": "create"},
|
|
{"path": ".env.production", "status": "create"},
|
|
{"path": "src/config.ts", "status": "create"}
|
|
],
|
|
"details": [
|
|
"Create .env.development with local API URLs",
|
|
"Create .env.production with production API URLs",
|
|
"Create type-safe config.ts that reads VITE_* vars",
|
|
"Define: VITE_API_BASE_URL, VITE_WS_URL, VITE_OAUTH_REDIRECT_URI"
|
|
],
|
|
"notes": "Not started. Needed before API client can work properly."
|
|
}
|
|
]
|
|
}
|