Skip to main content

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

ComponentPurpose
ClientSelectorDropdown for selecting an application
PeriodPickerDate range picker with month presets
PrefillPreviewDisplay prefill results before generating
LineItemEditorTable for editing line items
FinancialSummaryTotal, overtime, base amount display

Invoice Components

ComponentPurpose
InvoiceTableRegistry list with sortable columns, shows company name alongside CDM key
InvoiceStatusBadgeColor-coded status indicator
HTMLPreviewRenders server-side HTML in a sandboxed iframe for fast draft preview (accepts className for height override)
PDFViewerEmbedded PDF viewer for finalized invoices (accepts className for height override)
DeclineModalDialog with required reason textarea for declining invoices
RejectModalDialog with required reason textarea for rejecting invoices
InvoiceActionsContextual action buttons (finalize, download, etc.)
EditHistoryTimelineChronological list of edits

Common Components

ComponentPurpose
StatusBadgeColor-coded status badge for all 8 invoice statuses
CurrencyDisplayFormatted currency display with correct symbol
JiraLinkClickable Jira issue key that links to the Jira instance
CalculationBreakdownShows overtime/base amount calculation details
PageTitleConsistent page title styling

Layout

ComponentPurpose
AppLayoutMain layout with sidebar and header
SidebarResizable navigation menu (200-480px, width persisted in localStorage)
HeaderTop 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:

ComponentUsage
ButtonAction buttons, variants: default, outline, ghost, destructive
InputText inputs with validation states
SelectDropdown selectors
TableData tables with headers and rows
BadgeStatus indicators and labels
CardContent containers
DialogModal dialogs for confirmations
Toast (sonner)Notification toasts
SwitchToggle switches (used for display settings)
LabelForm field labels
TextareaMulti-line text input (used for legal text editing)
SkeletonLoading 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.