Components
Components are organized by feature area in frontend/src/components/.
Directory Structure
components/
├── common/ # Shared across features
├── invoice/ # Invoice display and editing
├── generate/ # Generate wizard steps
├── calculator/ # Pricing calculator (Phase 5)
├── layout/ # Page layout (header, sidebar, nav)
└── ui/ # shadcn/ui primitives (do not modify)
Key Components
Generate Wizard
| Component | Purpose |
|---|---|
ClientSelector | Dropdown for selecting an application |
PeriodPicker | Date range picker with month presets |
PrefillPreview | Display prefill results before generating |
LineItemEditor | Table for editing line items |
FinancialSummary | Total, overtime, base amount display |
Invoice Components
| Component | Purpose |
|---|---|
InvoiceTable | Registry list with sortable columns, shows company name alongside CDM key |
InvoiceStatusBadge | Color-coded status indicator |
HTMLPreview | Renders server-side HTML in a sandboxed iframe for fast draft preview (accepts className for height override) |
PDFViewer | Embedded PDF viewer for finalized invoices (accepts className for height override) |
DeclineModal | Dialog with required reason textarea for declining invoices |
RejectModal | Dialog with required reason textarea for rejecting invoices |
InvoiceActions | Contextual action buttons (finalize, download, etc.) |
EditHistoryTimeline | Chronological list of edits |
Common Components
| Component | Purpose |
|---|---|
StatusBadge | Color-coded status badge for all 8 invoice statuses |
CurrencyDisplay | Formatted currency display with correct symbol |
JiraLink | Clickable Jira issue key that links to the Jira instance |
CalculationBreakdown | Shows overtime/base amount calculation details |
PageTitle | Consistent page title styling |
Layout
| Component | Purpose |
|---|---|
AppLayout | Main layout with sidebar and header |
Sidebar | Resizable navigation menu (200-480px, width persisted in localStorage) |
Header | Top bar with user info |
shadcn/ui Primitives
The components/ui/ directory contains shadcn/ui components. These are generated by the shadcn CLI and should not be modified directly.
Commonly used primitives:
| Component | Usage |
|---|---|
Button | Action buttons, variants: default, outline, ghost, destructive |
Input | Text inputs with validation states |
Select | Dropdown selectors |
Table | Data tables with headers and rows |
Badge | Status indicators and labels |
Card | Content containers |
Dialog | Modal dialogs for confirmations |
Toast (sonner) | Notification toasts |
Switch | Toggle switches (used for display settings) |
Label | Form field labels |
Textarea | Multi-line text input (used for legal text editing) |
Skeleton | Loading placeholders |
Patterns
Data Fetching
Components use custom hooks that wrap React Query:
// hooks/use-invoices.ts
export function useInvoices(filters: InvoiceFilters) {
return useQuery({
queryKey: queryKeys.invoices.list(filters),
queryFn: () => fetchInvoices(filters),
});
}
Mutations
Mutations use React Query's useMutation with optimistic updates:
export function useGenerateInvoice() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: generateInvoice,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: queryKeys.invoices.all });
toast.success('Invoice generated');
},
onError: (error) => {
toast.error(`Generation failed: ${error.message}`);
},
});
}
Error Handling
API errors are displayed via sonner toasts with contextual messages. Form validation errors are shown inline with aria-invalid attributes.