diff --git a/frontend/.env.example b/frontend/.env.example index 22273ec..63121ca 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -2,7 +2,8 @@ # Copy this file to .env and fill in your values # API Configuration -VITE_API_URL=http://localhost:8000 +# IMPORTANT: Must include /api/v1 path to properly connect to backend +VITE_API_URL=http://localhost:8000/api/v1 # App Version (for Sentry releases) VITE_APP_VERSION=1.0.0 diff --git a/frontend/CASES_PAGE_FIX.md b/frontend/CASES_PAGE_FIX.md new file mode 100644 index 0000000..4a92180 --- /dev/null +++ b/frontend/CASES_PAGE_FIX.md @@ -0,0 +1,58 @@ +# Cases Page Launch Issue Fix + +## Problem +The cases page was failing to launch because API calls were not reaching the backend server. + +## Root Cause +The `apiRequest` function in `src/lib/api.ts` was not prepending the base API URL to relative URLs. This caused requests like `/cases?page=1` to be sent to the frontend server (http://localhost:5173) instead of the backend API server (http://localhost:8000/api/v1). + +## Solution +1. **Updated `apiRequest` function** to prepend `VITE_API_URL` for relative URLs +2. **Updated `.env.example`** to show correct API URL including `/api/v1` path + +## Setup Instructions + +### 1. Create .env file +```bash +cp .env.example .env +``` + +### 2. Verify API URL in .env +```env +VITE_API_URL=http://localhost:8000/api/v1 +``` + +**Important:** The `/api/v1` path is required. Do not use just `http://localhost:8000`. + +### 3. Start servers +```bash +# Terminal 1 - Backend +cd backend +# ... start backend server on port 8000 + +# Terminal 2 - Frontend +cd frontend +npm install +npm run dev +``` + +### 4. Test +Navigate to http://localhost:5173/cases - the page should now load successfully and fetch case data from the backend. + +## Files Changed +- `src/lib/api.ts` - Fixed `apiRequest` to prepend BASE_URL +- `.env.example` - Updated with correct API URL + +## Affected Components +This fix resolves API issues for ALL components using `apiRequest`: +- CaseList, CaseDetail +- Forensics, FinalSummary, Ingestion, AdjudicationQueue +- All adjudication components +- Evidence API +- And more... + +## Production Deployment +For production, update `VITE_API_URL` to point to your production API server: +```env +VITE_API_URL=https://api.your-domain.com/api/v1 +``` diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 642aa2f..3d7b7ab 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -25,6 +25,10 @@ export async function apiRequest( ): Promise { const method = options?.method?.toUpperCase() || 'GET'; + // Prepend base URL if URL is relative + const BASE_URL = import.meta.env.VITE_API_URL || '/api/v1'; + const fullUrl = url.startsWith('http') ? url : `${BASE_URL}${url}`; + // Prepare headers const headers = new Headers(options?.headers); if (!headers.has('Content-Type')) { @@ -66,7 +70,7 @@ export async function apiRequest( requestOptions.body = options.body; } - const response = await fetch(url, requestOptions); + const response = await fetch(fullUrl, requestOptions); if (!response.ok) { await response.text().catch(() => 'Unknown error'); diff --git a/frontend/src/pages/CaseDetail.tsx b/frontend/src/pages/CaseDetail.tsx index f2fd376..90b73ac 100644 --- a/frontend/src/pages/CaseDetail.tsx +++ b/frontend/src/pages/CaseDetail.tsx @@ -40,7 +40,7 @@ interface PredictiveResponse { const { data: aiRiskPrediction, isLoading: predictionLoading } = useQuery({ queryKey: ['case', id, 'ai-risk-prediction'], - queryFn: () => apiRequest(`/cases/${id}/ai-risk-prediction`), + queryFn: () => apiRequest(`/cases/${id}/ai-risk-prediction`, { method: 'POST' }), retry: false, enabled: !!id, }); diff --git a/frontend/src/pages/CaseList.tsx b/frontend/src/pages/CaseList.tsx index fb63c64..b772760 100644 --- a/frontend/src/pages/CaseList.tsx +++ b/frontend/src/pages/CaseList.tsx @@ -80,7 +80,7 @@ export function CaseList() { else if (riskFilter === 'low') params.append('max_risk', '39'); } - return apiRequest('/cases/?' + params.toString()); + return apiRequest(`/cases?${params.toString()}`); }; const { data, isLoading, error, refetch } = useQuery({