Merge branch 'main' into feature/user-auth

Resolved merge conflicts integrating PR #13 (Home Page with MUI v2):

Backend changes:
- settings.py: Combined INSTALLED_APPS (accounts + jobs + corsheaders),
  kept HEAD's REST_FRAMEWORK (AllowAny + throttling) and SIMPLE_JWT,
  added origin/main's CORS config
- urls.py: Combined admin/, api/auth/, api/ routes
- pyproject.toml: Combined all dependencies (simplejwt + cors-headers)
- uv.lock: Regenerated with updated dependencies

Frontend changes:
- package.json: Combined all deps (axios + MUI + emotion)
- App.tsx: Integrated AuthProvider with MUI AppLayout, all routes
- HomePage.tsx: Show landing view when unauthenticated, MUI dashboard
  when authenticated
- main.tsx, tsconfig.json, vite-env.d.ts: Combined both versions
- yarn.lock: Kept origin/main's version (regenerated on install)
This commit is contained in:
Marko (Hermes Implementer)
2026-05-26 19:07:02 +00:00
30 changed files with 2095 additions and 58 deletions
+115
View File
@@ -0,0 +1,115 @@
# Spec: Home Page with MUI Components
## Ticket
Gitea: crisleo-hermes/job-tracker#2
Kanban: t_e6936299
## Overview
Build a home page at route `/` using Material-UI (MUI) components that displays the last three job updates and dashboard metrics, with a button to create a new job application.
## Pages
### HomePage (`/`)
- AppBar with title "Job Tracker"
- Dashboard metrics cards row (total applications, interviews, offers, rejection rate)
- Last 3 job updates displayed as cards
- "Create New Job Application" button (navigates to creation flow)
- Loading skeleton while data fetches
- Error snackbar on API failure
- Responsive Grid layout
## API Endpoints Consumed
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/updates/latest/` | 3 most recent JobUpdates with nested job info |
| GET | `/api/updates/metrics/` | Dashboard metrics (total, status breakdown, interviews, offers, rejection rate) |
### Response Shapes
**GET /api/updates/latest/**
```json
[
{
"id": 1,
"job_id": 1,
"company_name": "Acme Corp",
"position_title": "Software Engineer",
"from_status": "APPLIED",
"to_status": "INTERVIEW",
"notes": "Moving to next round",
"created_at": "2025-01-15T10:00:00Z",
"metrics": {"response_time_days": 5}
}
]
```
**GET /api/updates/metrics/**
```json
{
"total_applications": 12,
"status_breakdown": {"APPLIED": 5, "INTERVIEW": 4, "OFFER": 2, "REJECTED": 1},
"interviews_count": 6,
"offers_count": 2,
"rejection_rate": 8.3
}
```
## Components
### `AppLayout`
- MUI `AppBar` with `Toolbar`, `Typography` ("Job Tracker")
- Wraps child content via `Outlet` from React Router
### `UpdateCard`
- MUI `Card``CardContent`
- Displays: company name, position title, status change (`from_status``to_status`), created date, metrics summary
- Props: `JobUpdate`
### `MetricsPanel`
- MUI `Grid` container with metric `Card` items
- Each metric: total applications, interviews count, offers count, rejection rate
- Props: `DashboardMetrics`
### `LoadingSkeleton`
- MUI `Skeleton` components mimicking the home page layout
## Data Fetching
Custom hook `useDashboardData` using React's `useEffect` + `useState`:
- Fetches from `/api/updates/latest/` and `/api/updates/metrics/` concurrently (`Promise.all`)
- Vite proxy: `/api``http://localhost:8000/api`
- States: loading, error (with error message), data
## TypeScript Types
```typescript
interface JobUpdate {
id: number;
job_id: number;
company_name: string;
position_title: string;
from_status: string | null;
to_status: string;
notes: string;
created_at: string;
metrics: Record<string, unknown>;
}
interface DashboardMetrics {
total_applications: number;
status_breakdown: Record<string, number>;
interviews_count: number;
offers_count: number;
rejection_rate: number;
}
```
## Acceptance Criteria
- [x] Home page at route `/`
- [x] MUI components exclusively (AppBar, Typography, Card, Grid, Button, Skeleton, Snackbar)
- [x] Last 3 job updates: job ID, status, creation date, metrics
- [x] "Create New Job Application" button navigates to `/applications/new`
- [x] Loading indicators while fetching data (Skeleton components)
- [x] Graceful error handling (Snackbar with error message)
- [x] Responsive layout (Grid breakpoints)