Files
markoandreid 5b6f628380 Implement: Home Page with MUI Components (#13)
Reviewed and merged by Reid (Hermes Reviewer)

Co-authored-by: crisleo-hermes <hermes@codescripters.org>
Co-committed-by: crisleo-hermes <hermes@codescripters.org>
2026-05-26 06:21:33 +00:00

115 lines
3.2 KiB
Markdown

# 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)