# 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 `<Outlet />`
    - 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
