# Requirements Document

## Introduction

Signal Dashboard is a single-page application (SPA) frontend for the Stock Data Backend API. The Dashboard provides authenticated users with a visual interface to monitor watchlists, analyze individual tickers across multiple dimensions (technical, S/R, sentiment, fundamentals, momentum), scan for asymmetric risk:reward trade setups, view composite-score rankings, and manage system administration. The Dashboard consumes the existing REST API at `/api/v1/` and is served as static files by Nginx on the same domain (`signal.thiessen.io`).

Technology choice: React 18 + TypeScript + Vite, with TanStack Query for data fetching, Zustand for auth state, Tailwind CSS for styling, Recharts for charting, and React Router for navigation. This stack prioritizes maintainability, small bundle size, and a modern developer experience without framework bloat.

## Glossary

- **Dashboard**: The Signal Dashboard SPA frontend application
- **API_Client**: The HTTP client module that communicates with the backend REST API
- **Auth_Module**: The authentication subsystem handling login, registration, token storage, and token refresh
- **Watchlist_View**: The main overview page displaying the user's watchlist entries with enriched score data
- **Ticker_Detail_View**: The per-ticker analysis page showing price chart, indicators, S/R levels, sentiment, and fundamentals
- **Scanner_View**: The trade setup scanner page displaying R:R filtered setups
- **Rankings_View**: The page displaying all tickers sorted by composite score
- **Admin_Panel**: The administration interface for user management, job control, system settings, and data cleanup
- **Router**: The client-side routing module controlling navigation and access guards
- **Token_Store**: The client-side storage mechanism for JWT access tokens
- **Chart_Component**: The interactive price chart component rendering OHLCV candlestick data with overlays
- **Score_Card**: A UI component displaying a composite score and its dimension breakdown
- **Toast_System**: The notification subsystem displaying transient success/error messages to the user

## Requirements

### Requirement 1: JWT Authentication Flow

**User Story:** As a user, I want to log in and register so that I can access the dashboard securely.

#### Acceptance Criteria

1. WHEN a user submits valid credentials on the login form, THE Auth_Module SHALL send a POST request to `/api/v1/auth/login` and store the returned JWT token in the Token_Store
2. WHEN a user submits a registration form with a username (minimum 1 character) and password (minimum 6 characters), THE Auth_Module SHALL send a POST request to `/api/v1/auth/register` and display a success message via the Toast_System
3. WHILE a valid JWT token exists in the Token_Store, THE API_Client SHALL include the token as a Bearer authorization header on all subsequent API requests
4. WHEN the API returns a 401 Unauthorized response, THE Auth_Module SHALL clear the Token_Store and redirect the user to the login page
5. IF the login or registration request fails, THEN THE Auth_Module SHALL display the error message from the API response via the Toast_System
6. THE Token_Store SHALL persist the JWT token in browser localStorage so that sessions survive page reloads

### Requirement 2: Protected Routing and Role-Based Access

**User Story:** As a user, I want the app to enforce access control so that unauthenticated users cannot access protected pages and only admins can access admin features.

#### Acceptance Criteria

1. WHILE no valid JWT token exists in the Token_Store, THE Router SHALL redirect navigation to any protected route to the login page
2. WHILE a valid JWT token exists in the Token_Store, THE Router SHALL allow navigation to protected routes (Watchlist_View, Ticker_Detail_View, Scanner_View, Rankings_View)
3. WHILE the authenticated user has an admin role, THE Router SHALL allow navigation to the Admin_Panel
4. WHILE the authenticated user has a non-admin role, THE Router SHALL redirect navigation to the Admin_Panel to the Watchlist_View
5. THE Router SHALL provide a navigation sidebar or top bar with links to all accessible views for the authenticated user

### Requirement 3: Watchlist Overview

**User Story:** As a user, I want to see my watchlist with composite scores, dimension breakdowns, and R:R ratios so that I can quickly assess my tracked tickers.

#### Acceptance Criteria

1. WHEN the Watchlist_View loads, THE Dashboard SHALL fetch data from `GET /api/v1/watchlist` and display each entry as a card or row
2. THE Watchlist_View SHALL display for each entry: symbol, entry type (auto/manual), composite score, dimension scores, R:R ratio, R:R direction, and nearest S/R levels
3. WHEN a user clicks the add-to-watchlist control and enters a valid ticker symbol, THE Dashboard SHALL send a POST request to `/api/v1/watchlist/{symbol}` and refresh the watchlist
4. WHEN a user clicks the remove button on a watchlist entry, THE Dashboard SHALL send a DELETE request to `/api/v1/watchlist/{symbol}` and remove the entry from the display
5. IF the watchlist API request fails, THEN THE Dashboard SHALL display the error message via the Toast_System
6. WHEN a user clicks on a watchlist entry symbol, THE Router SHALL navigate to the Ticker_Detail_View for that symbol
7. THE Watchlist_View SHALL visually distinguish auto-populated entries from manual entries using a badge or label

### Requirement 4: Ticker Detail View

**User Story:** As a user, I want to see a comprehensive analysis of a single ticker including price chart, indicators, S/R levels, sentiment, and fundamentals so that I can make informed decisions.

#### Acceptance Criteria

1. WHEN the Ticker_Detail_View loads for a given symbol, THE Dashboard SHALL fetch data in parallel from: `GET /api/v1/ohlcv/{symbol}`, `GET /api/v1/scores/{symbol}`, `GET /api/v1/sr-levels/{symbol}`, `GET /api/v1/sentiment/{symbol}`, and `GET /api/v1/fundamentals/{symbol}`
2. THE Chart_Component SHALL render OHLCV data as a candlestick chart with date on the x-axis and price on the y-axis
3. THE Chart_Component SHALL overlay S/R levels as horizontal lines on the price chart, color-coded by type (support in green, resistance in red)
4. THE Ticker_Detail_View SHALL display the composite score and all dimension scores using Score_Card components
5. THE Ticker_Detail_View SHALL display sentiment data including classification (bullish/bearish/neutral), confidence, and the time-decay weighted dimension score
6. THE Ticker_Detail_View SHALL display fundamental data including P/E ratio, revenue growth, earnings surprise, and market cap
7. WHEN a user selects an indicator type (ADX, EMA, RSI, ATR, volume_profile, pivot_points), THE Dashboard SHALL fetch data from `GET /api/v1/indicators/{symbol}/{indicator_type}` and display the result with its normalized score
8. WHEN a user requests the EMA cross signal, THE Dashboard SHALL fetch data from `GET /api/v1/indicators/{symbol}/ema-cross` and display the signal (bullish/bearish/neutral) with short and long EMA values
9. IF any data fetch fails for the Ticker_Detail_View, THEN THE Dashboard SHALL display an inline error message for the failed section while rendering the remaining sections normally

### Requirement 5: Trade Setup Scanner

**User Story:** As a user, I want to scan for trade setups with favorable risk:reward ratios so that I can find asymmetric opportunities.

#### Acceptance Criteria

1. WHEN the Scanner_View loads, THE Dashboard SHALL fetch data from `GET /api/v1/trades` and display all trade setups in a sortable table
2. THE Scanner_View SHALL display for each trade setup: symbol, direction (long/short), entry price, stop loss, target, R:R ratio, composite score, and detection timestamp
3. THE Scanner_View SHALL allow the user to filter trade setups by minimum R:R ratio using a numeric input
4. THE Scanner_View SHALL allow the user to filter trade setups by direction (long, short, or both)
5. THE Scanner_View SHALL allow the user to sort the table by any column (R:R ratio, composite score, symbol, detection time)
6. WHEN a user clicks on a trade setup symbol, THE Router SHALL navigate to the Ticker_Detail_View for that symbol

### Requirement 6: Rankings View

**User Story:** As a user, I want to see all tickers ranked by composite score so that I can identify the strongest opportunities.

#### Acceptance Criteria

1. WHEN the Rankings_View loads, THE Dashboard SHALL fetch data from `GET /api/v1/rankings` and display tickers sorted by composite score descending
2. THE Rankings_View SHALL display for each ticker: rank position, symbol, composite score, and all dimension scores
3. THE Rankings_View SHALL display the current scoring weights used for composite calculation
4. WHEN a user clicks on a ranked ticker symbol, THE Router SHALL navigate to the Ticker_Detail_View for that symbol

### Requirement 7: Admin Panel — User Management

**User Story:** As an admin, I want to manage user accounts so that I can control access to the platform.

#### Acceptance Criteria

1. WHEN the Admin_Panel user management section loads, THE Dashboard SHALL fetch data from `GET /api/v1/admin/users` and display all users in a table
2. THE Admin_Panel SHALL display for each user: username, role, and access status
3. WHEN an admin clicks the create-user control and submits a username, password, role, and access flag, THE Dashboard SHALL send a POST request to `/api/v1/admin/users` and refresh the user list
4. WHEN an admin toggles a user's access status, THE Dashboard SHALL send a PUT request to `/api/v1/admin/users/{user_id}/access` with the new access flag
5. WHEN an admin resets a user's password, THE Dashboard SHALL send a PUT request to `/api/v1/admin/users/{user_id}/password` with the new password
6. IF any admin user management request fails, THEN THE Dashboard SHALL display the error message via the Toast_System

### Requirement 8: Admin Panel — System Settings and Jobs

**User Story:** As an admin, I want to manage system settings, scheduled jobs, and data cleanup so that I can maintain the platform.

#### Acceptance Criteria

1. WHEN the Admin_Panel settings section loads, THE Dashboard SHALL fetch data from `GET /api/v1/admin/settings` and display all settings as editable fields
2. WHEN an admin updates a system setting value, THE Dashboard SHALL send a PUT request to `/api/v1/admin/settings/{key}` with the new value
3. WHEN an admin toggles the registration setting, THE Dashboard SHALL send a PUT request to `/api/v1/admin/settings/registration` with the enabled flag
4. WHEN an admin toggles a scheduled job on or off, THE Dashboard SHALL send a PUT request to `/api/v1/admin/jobs/{job_name}/toggle` with the enabled flag
5. WHEN an admin triggers a scheduled job manually, THE Dashboard SHALL send a POST request to `/api/v1/admin/jobs/{job_name}/trigger` and display a confirmation via the Toast_System
6. WHEN an admin submits a data cleanup request with an older-than-days value, THE Dashboard SHALL send a POST request to `/api/v1/admin/data/cleanup` with the specified value and display the result via the Toast_System

### Requirement 9: Ticker Management

**User Story:** As a user, I want to add and remove tickers from the system so that I can track the stocks I care about.

#### Acceptance Criteria

1. WHEN a user submits a new ticker symbol via the add-ticker form, THE Dashboard SHALL send a POST request to `/api/v1/tickers` with the symbol and refresh the ticker list
2. WHEN a user views the ticker list, THE Dashboard SHALL fetch data from `GET /api/v1/tickers` and display all registered tickers
3. WHEN a user clicks the delete button on a ticker, THE Dashboard SHALL display a confirmation dialog before sending a DELETE request to `/api/v1/tickers/{symbol}`
4. IF a ticker deletion or creation request fails, THEN THE Dashboard SHALL display the error message via the Toast_System
5. WHEN a ticker is successfully deleted, THE Dashboard SHALL remove the ticker from the displayed list without requiring a full page reload

### Requirement 10: Data Ingestion Trigger

**User Story:** As a user, I want to manually trigger data ingestion for a specific ticker so that I can get fresh data on demand.

#### Acceptance Criteria

1. WHEN a user clicks the fetch-data button on the Ticker_Detail_View, THE Dashboard SHALL send a POST request to `/api/v1/ingestion/fetch/{symbol}`
2. WHILE the ingestion request is in progress, THE Dashboard SHALL display a loading indicator on the fetch-data button
3. WHEN the ingestion request completes successfully, THE Dashboard SHALL display a success message via the Toast_System and refresh the OHLCV data on the Ticker_Detail_View
4. IF the ingestion request fails, THEN THE Dashboard SHALL display the error message via the Toast_System

### Requirement 11: Score Weight Configuration

**User Story:** As a user, I want to adjust the scoring dimension weights so that I can customize the composite score calculation to my strategy.

#### Acceptance Criteria

1. THE Dashboard SHALL display the current scoring weights on the Rankings_View with editable numeric inputs for each dimension
2. WHEN a user modifies one or more weight values and submits the form, THE Dashboard SHALL send a PUT request to `/api/v1/scores/weights` with the updated weights map
3. WHEN the weight update succeeds, THE Dashboard SHALL refresh the rankings data to reflect the new composite scores
4. IF the weight update request fails, THEN THE Dashboard SHALL display the error message via the Toast_System

### Requirement 12: API Client and Error Handling

**User Story:** As a developer, I want a centralized API client with consistent error handling so that all API interactions follow the same patterns.

#### Acceptance Criteria

1. THE API_Client SHALL send all requests to the base URL `/api/v1/` using the JSON content type
2. THE API_Client SHALL unwrap the API envelope (`{ status, data, error }`) and return the `data` field on success or throw an error with the `error` field on failure
3. THE API_Client SHALL attach the JWT Bearer token from the Token_Store to every authenticated request
4. WHEN the API_Client receives a network error or timeout, THE API_Client SHALL throw a descriptive error that the calling component can display via the Toast_System
5. THE API_Client SHALL set a request timeout of 30 seconds for all API calls

### Requirement 13: Responsive Layout and Visual Design

**User Story:** As a user, I want the dashboard to have a clean, modern interface that works on desktop and tablet screens so that I can use it comfortably.

#### Acceptance Criteria

1. THE Dashboard SHALL use a sidebar navigation layout on screens wider than 1024 pixels and a collapsible hamburger menu on narrower screens
2. THE Dashboard SHALL use a dark color scheme with accent colors for positive (green) and negative (red) values consistent with financial data conventions
3. THE Dashboard SHALL apply smooth transitions (duration 150ms to 300ms) for page navigation, modal openings, and interactive element state changes
4. THE Dashboard SHALL display numeric financial values with appropriate formatting: prices to 2 decimal places, percentages with a percent sign, large numbers with abbreviations (K, M, B)
5. THE Dashboard SHALL display loading skeleton placeholders while data is being fetched from the API

### Requirement 14: Static SPA Build and Deployment

**User Story:** As a developer, I want the frontend to build as static files that Nginx can serve alongside the backend API so that deployment is simple.

#### Acceptance Criteria

1. THE Dashboard SHALL produce a static build output (HTML, CSS, JS) in a `dist/` directory via a single build command
2. THE Dashboard SHALL use hash-based filenames for JS and CSS assets to enable long-term browser caching
3. THE Dashboard SHALL support client-side routing with a fallback to `index.html` for all non-API routes (Nginx `try_files` configuration)
4. THE Dashboard SHALL proxy API requests to `/api/v1/` on the same origin, requiring no CORS configuration in production
5. WHEN the `GET /api/v1/health` endpoint returns a success response, THE Dashboard SHALL consider the backend available
