# Implementation Plan: Signal Dashboard ## Overview Incremental build of the Signal Dashboard SPA in `frontend/`. Each phase wires up end-to-end before moving on, so there's always a runnable app. Backend API is already live — we consume it as-is. ## Tasks - [x] 1. Scaffold Vite + React + TypeScript project - [x] 1.1 Initialize `frontend/` with Vite React-TS template, install dependencies (react, react-dom, react-router-dom, @tanstack/react-query, zustand, axios, recharts, tailwindcss, postcss, autoprefixer) - Create `package.json`, `tsconfig.json`, `vite.config.ts`, `tailwind.config.ts`, `postcss.config.js` - Configure Vite proxy for `/api/v1/` to backend during dev - Configure Tailwind with dark mode class strategy - Create `src/main.tsx`, `src/App.tsx`, `src/styles/globals.css` with Tailwind directives - _Requirements: 14.1, 14.4, 13.2_ - [x] 1.2 Create shared TypeScript interfaces and formatting utilities - Create `src/lib/types.ts` with all data model interfaces (APIEnvelope, TokenResponse, WatchlistEntry, OHLCVBar, ScoreResponse, TradeSetup, SRLevel, SentimentResponse, FundamentalResponse, IndicatorResult, EMACrossResult, Ticker, AdminUser, SystemSetting, etc.) - Create `src/lib/format.ts` with `formatPrice`, `formatPercent`, `formatLargeNumber`, `formatDate`, `formatDateTime` - _Requirements: 13.4_ - [ ]* 1.3 Write property tests for formatting utilities - **Property 16: Number formatting** - **Validates: Requirements 13.4** - Install vitest, @testing-library/react, fast-check as dev dependencies - Create `frontend/vitest.config.ts` with jsdom environment - Create `frontend/tests/property/format.test.ts` - Test `formatPrice` always produces 2 decimal places, `formatPercent` ends with `%`, `formatLargeNumber` uses correct suffix - [x] 2. API client and auth store - [x] 2.1 Create Axios API client with interceptors - Create `src/api/client.ts` with base URL `/api/v1/`, 30s timeout, JSON content type - Add request interceptor to attach Bearer token from auth store - Add response interceptor to unwrap `{ status, data, error }` envelope - Add 401 handler that clears auth store and redirects to login - Create `ApiError` class for typed error handling - _Requirements: 12.1, 12.2, 12.3, 12.4, 12.5_ - [x] 2.2 Create Zustand auth store - Create `src/stores/authStore.ts` with token, username, role state - `login(token)` decodes JWT payload, extracts `sub` and `role`, persists to localStorage - `logout()` clears state and localStorage - Initialize from localStorage on store creation for session persistence - _Requirements: 1.1, 1.6_ - [x] 2.3 Create API module files for each domain - Create `src/api/auth.ts` (login, register) - Create `src/api/watchlist.ts` (list, add, remove) - Create `src/api/tickers.ts` (list, create, delete) - Create `src/api/scores.ts` (getScores, getRankings, updateWeights) - Create `src/api/trades.ts` (list) - Create `src/api/ohlcv.ts` (getOHLCV) - Create `src/api/indicators.ts` (getIndicator, getEMACross) - Create `src/api/sr-levels.ts` (getLevels) - Create `src/api/sentiment.ts` (getSentiment) - Create `src/api/fundamentals.ts` (getFundamentals) - Create `src/api/ingestion.ts` (fetchData) - Create `src/api/admin.ts` (users CRUD, settings, jobs, cleanup) - Create `src/api/health.ts` (check) - _Requirements: 12.1, 12.2_ - [ ]* 2.4 Write property tests for API client and auth store - **Property 1: Token storage round-trip** - **Property 2: Bearer token attachment** - **Property 5: API envelope unwrapping** - **Validates: Requirements 1.1, 1.3, 1.6, 12.2, 12.3** - [x] 3. Checkpoint — Verify foundation - Ensure all tests pass, ask the user if questions arise. - [x] 4. Routing, layout, and auth pages - [x] 4.1 Create ProtectedRoute component and router setup - Create `src/components/auth/ProtectedRoute.tsx` — redirects to `/login` if no token, redirects non-admin away from admin routes - Set up React Router in `src/App.tsx` with route structure from design (login, register, protected shell with watchlist, ticker detail, scanner, rankings, admin) - _Requirements: 2.1, 2.2, 2.3, 2.4_ - [x] 4.2 Create AppShell layout with sidebar navigation - Create `src/components/layout/AppShell.tsx` — sidebar + main content area with `` - Create `src/components/layout/Sidebar.tsx` — nav links to watchlist, scanner, rankings, admin (admin link only if role is admin) - Create `src/components/layout/MobileNav.tsx` — hamburger menu for screens < 1024px - Apply dark color scheme with Tailwind dark mode classes - Add smooth transitions (150-300ms) for navigation and interactive elements - _Requirements: 2.5, 13.1, 13.2, 13.3_ - [x] 4.3 Create Login and Register pages - Create `src/pages/LoginPage.tsx` with username/password form, calls `useAuth().login` mutation - Create `src/pages/RegisterPage.tsx` with username (min 1 char) / password (min 6 chars) validation, calls `useAuth().register` mutation - Create `src/hooks/useAuth.ts` with login/register/logout mutations using TanStack Query - Display API errors via toast on failure, redirect to watchlist on login success - _Requirements: 1.1, 1.2, 1.4, 1.5_ - [x] 4.4 Create shared UI components - Create `src/components/ui/Toast.tsx` — toast context + portal, auto-dismiss 4s, max 3 visible, color-coded (red/green/blue) - Create `src/components/ui/Skeleton.tsx` — Tailwind `animate-pulse` placeholder blocks - Create `src/components/ui/Badge.tsx` — small label component for entry types - Create `src/components/ui/ConfirmDialog.tsx` — modal confirmation dialog - Create `src/components/ui/ScoreCard.tsx` — composite score display with colored ring (green > 70, yellow 40-70, red < 40) and dimension breakdown - _Requirements: 13.3, 13.5, 1.5_ - [ ]* 4.5 Write property tests for routing and registration validation - **Property 3: Registration form validation** - **Property 4: Route protection based on auth state** - **Validates: Requirements 1.2, 2.1, 2.2** - [x] 5. Checkpoint — Verify auth flow and navigation - Ensure all tests pass, ask the user if questions arise. - [x] 6. Watchlist view - [x] 6.1 Create TanStack Query hooks for watchlist - Create `src/hooks/useWatchlist.ts` with `useWatchlist()` query, `useAddToWatchlist()` mutation, `useRemoveFromWatchlist()` mutation - Invalidate watchlist query on add/remove success - Surface errors to toast system - _Requirements: 3.1, 3.3, 3.4, 3.5_ - [x] 6.2 Create WatchlistPage and sub-components - Create `src/pages/WatchlistPage.tsx` — fetches watchlist, renders table/cards, loading skeletons, error state - Create `src/components/watchlist/WatchlistTable.tsx` — displays symbol (clickable → `/ticker/{symbol}`), entry type badge (auto/manual), composite score, dimension scores, R:R ratio, R:R direction, nearest S/R levels, remove button - Create `src/components/watchlist/AddTickerForm.tsx` — input + submit to add symbol to watchlist - _Requirements: 3.1, 3.2, 3.3, 3.4, 3.6, 3.7_ - [ ]* 6.3 Write property tests for watchlist rendering - **Property 6: Watchlist entry rendering completeness** - **Property 7: Symbol click navigation** (watchlist portion) - **Validates: Requirements 3.2, 3.6, 3.7** - [x] 7. Ticker detail view - [x] 7.1 Create TanStack Query hooks for ticker detail - Create `src/hooks/useTickerDetail.ts` with parallel queries for OHLCV, scores, S/R levels, sentiment, fundamentals - Each query is independent — partial failure renders available sections - _Requirements: 4.1, 4.9_ - [x] 7.2 Create TickerDetailPage with chart and data panels - Create `src/pages/TickerDetailPage.tsx` — orchestrates parallel data fetching, renders sections with independent loading/error states - Create `src/components/charts/CandlestickChart.tsx` — Recharts ComposedChart with custom Bar shapes for OHLCV candles, date x-axis, price y-axis - Create `src/components/ticker/SROverlay.tsx` — renders S/R levels as ReferenceLine components on chart (green = support, red = resistance) - Render ScoreCard for composite + dimension scores - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.9_ - [x] 7.3 Create sentiment, fundamentals, and indicator panels - Create `src/components/ticker/SentimentPanel.tsx` — displays classification, confidence, dimension score - Create `src/components/ticker/FundamentalsPanel.tsx` — displays P/E, revenue growth, earnings surprise, market cap (placeholder for nulls) - Create `src/components/ticker/IndicatorSelector.tsx` — dropdown to select indicator type (ADX, EMA, RSI, ATR, volume_profile, pivot_points), fetches from `/api/v1/indicators/{symbol}/{type}`, displays result with normalized score. Includes EMA cross signal display. - _Requirements: 4.5, 4.6, 4.7, 4.8_ - [x] 7.4 Add data ingestion trigger to ticker detail - Add fetch-data button to TickerDetailPage - POST to `/api/v1/ingestion/fetch/{symbol}`, show loading indicator on button, toast on success/failure, refresh OHLCV data on success - _Requirements: 10.1, 10.2, 10.3, 10.4_ - [ ]* 7.5 Write property tests for ticker detail components - **Property 8: Score card rendering** - **Property 9: Sentiment panel rendering** - **Property 10: Fundamentals panel rendering** - **Validates: Requirements 4.4, 4.5, 4.6** - [x] 8. Checkpoint — Verify watchlist and ticker detail - Ensure all tests pass, ask the user if questions arise. - [x] 9. Scanner view - [x] 9.1 Create TanStack Query hooks and scanner page - Create `src/hooks/useTrades.ts` with `useTrades()` query - Create `src/pages/ScannerPage.tsx` — fetches trade setups, renders filter controls and table, loading skeletons - Create `src/components/scanner/TradeTable.tsx` — sortable table displaying symbol (clickable → `/ticker/{symbol}`), direction, entry price, stop loss, target, R:R ratio, composite score, detection timestamp - Add filter controls: minimum R:R numeric input, direction dropdown (long/short/both) - Add column sorting (R:R ratio, composite score, symbol, detection time) with ascending/descending toggle - _Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 5.6_ - [ ]* 9.2 Write property tests for scanner filtering and sorting - **Property 11: Trade setup rendering** - **Property 12: Scanner filtering** - **Property 13: Scanner sorting** - **Validates: Requirements 5.2, 5.3, 5.4, 5.5** - [x] 10. Rankings view - [x] 10.1 Create TanStack Query hooks and rankings page - Create `src/hooks/useScores.ts` with `useRankings()` query, `useUpdateWeights()` mutation - Create `src/pages/RankingsPage.tsx` — fetches rankings, renders table sorted by composite score descending, displays current weights - Create `src/components/rankings/RankingsTable.tsx` — displays rank position, symbol (clickable → `/ticker/{symbol}`), composite score, all dimension scores - Create `src/components/rankings/WeightsForm.tsx` — editable numeric inputs per dimension, submit updates weights via PUT, refreshes rankings on success - _Requirements: 6.1, 6.2, 6.3, 6.4, 11.1, 11.2, 11.3, 11.4_ - [ ]* 10.2 Write property tests for rankings and weights - **Property 14: Rankings display order** - **Property 17: Weights form rendering** - **Validates: Requirements 6.1, 6.2, 11.1** - [x] 11. Checkpoint — Verify scanner and rankings - Ensure all tests pass, ask the user if questions arise. - [x] 12. Ticker management - [x] 12.1 Create TanStack Query hooks and ticker management UI - Create `src/hooks/useTickers.ts` with `useTickers()` query, `useAddTicker()` mutation, `useDeleteTicker()` mutation - Add ticker list display to an appropriate location (e.g., admin page or dedicated section) - Add ticker form for adding new symbols - Delete button triggers ConfirmDialog before sending DELETE request - Remove ticker from display on successful delete without full page reload - _Requirements: 9.1, 9.2, 9.3, 9.4, 9.5_ - [x] 13. Admin panel - [x] 13.1 Create admin hooks and user management section - Create `src/hooks/useAdmin.ts` with queries and mutations for users, settings, jobs, cleanup - Create `src/pages/AdminPage.tsx` — tabbed layout with user management, settings, jobs, data cleanup sections - Create `src/components/admin/UserTable.tsx` — displays username, role, access status; toggle access, reset password controls - Add create-user form (username, password, role, access flag) - _Requirements: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6_ - [x] 13.2 Create settings, jobs, and data cleanup sections - Create `src/components/admin/SettingsForm.tsx` — editable fields for each setting, registration toggle - Create `src/components/admin/JobControls.tsx` — toggle on/off per job, manual trigger button, toast confirmation - Create `src/components/admin/DataCleanup.tsx` — older-than-days input, submit cleanup, display result via toast - _Requirements: 8.1, 8.2, 8.3, 8.4, 8.5, 8.6_ - [ ]* 13.3 Write property test for admin user table rendering - **Property 15: Admin user table rendering** - **Validates: Requirements 7.2** - [x] 14. Final wiring and polish - [x] 14.1 Add health check and loading states - Create health check query using `GET /api/v1/health` — display backend status indicator in sidebar - Ensure all pages show Skeleton placeholders during loading - Ensure all mutation errors surface through Toast system consistently - _Requirements: 14.5, 13.5, 12.4_ - [x] 14.2 Configure production build - Verify `vite build` outputs to `frontend/dist/` with hashed filenames - Add Nginx config snippet in comments or README for `try_files $uri $uri/ /index.html` and `/api/v1/` proxy - _Requirements: 14.1, 14.2, 14.3, 14.4_ - [x] 15. Final checkpoint — Ensure all tests pass - Ensure all tests pass, ask the user if questions arise. ## Notes - Tasks marked with `*` are optional property test tasks and can be skipped for faster MVP - Each task references specific requirements for traceability - Backend API is already running — no backend changes needed - All 17 correctness properties are covered across optional test tasks - Checkpoints are placed after each major phase for incremental validation