Job Board
OpportunityBoard
File: apps/landing/src/app/components/job-board.tsx
The main job listing page at /opportunities.
Data Flow
- On mount, fetches active jobs from Supabase via
getActiveJobs() - Stores results in local state (
useState) - Filters client-side by search query, location, and employment type
Shared UI Used
| Component | Import Source |
|---|---|
LoadingState | @prosper/shared/components/ui/loading-spinner |
ErrorState | @prosper/shared/components/ui/loading-spinner |
SearchInput | @prosper/shared/components/ui/search-input |
FilterDropdown | ./filter-dropdown (local) |
PageHeader | ./page-header (local) |
Layout
PageHeaderat the top (shader gradient + nav)- Search bar + two
FilterDropdowns (Location, Employment Type) below - Grid of
OpportunityCardcomponents - “No matching opportunities” empty state
OpportunityCard
File: apps/landing/src/app/components/job-card.tsx
A compact card (100px height) that links to the job detail page.
Content
- Job title
- Hourly rate (computed from salary range)
- Location
- Employment type
Styling
Uses hardcoded shadow-[...] custom box-shadow CSS with color token vars:
shadow-[0px_0px_0px_1px_var(--color-gray-200),0px_1px_3px_0px_rgba(0,0,0,0.1),0px_1px_2px_-1px_rgba(0,0,0,0.1)]On hover, transitions to a blue-tinted shadow.
JobDetailV2
File: apps/landing/src/app/components/job-detail-v2.tsx
The full job detail page at /opportunities/:id.
Content
- Job title, description (rendered as HTML via
dangerouslySetInnerHTML) - Responsibilities list
- Requirements list
- Salary range, employment type, location
- “Apply Now” CTA linking to the application form
Shared UI Used
| Component | Source |
|---|---|
PageHeader | Local |
Button | @prosper/shared (via “Apply Now” CTA) |
| Lucide icons | MapPin, Briefcase, DollarSign, etc. |