Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

07 — Component Library (Fees Module)

Module-specific components used across the Fees screens. Everything else comes from 00-shared/03_Component_Library.md (referenced by name). All amounts render via the shared AppMoney helper (15_Flutter_Implementation_Guide.md §4).


A. Fees representation

MoneyAmount

  • Purpose: canonical amount rendering (mono, tabularFigures).
  • Props: amount (num), currency (default from context: structure currency default XAF fee-structure.schema.ts:27-28; v2 USD payments/schemas/payment.schema.ts:42-43), style (display|title|label), zeroState ("Settled"/"Free").
  • Rules: intl.NumberFormat.currency; XAF 0 decimals, USD 2; never "-0"; always FontFeature.tabularFigures().
  • Flutter: Text + TextStyle.monospace wrapper AmountText.

StatusChip (AppBadge variant)

  • Purpose: invoice / payment / structure status, text + icon + color (never color-only — 09 §9).
  • Palette per status (full table in 06 §5); icons check_circle, schedule, hourglass, mail, cancel, description.
  • Props: invoiceStatus? (draft|issued|partial|paid|overdue|cancelledinvoice.schema.ts:7-14), paymentStatus? (PaymentStatus payments/schemas/payment.schema.ts:18-26), boolStatus? (structure isActive).
  • Flutter: custom StatusChipContainer + Icon + Text.

DueRow

  • Purpose: dues table row: student ref, structure, due (server-provided, fees.service.ts:213-216), status chip, inline Collect action.
  • Props: invoice, due, onTap, onCollect.
  • Flutter: ListTile-based DueRow (height 56+).

InvoiceCard

  • Purpose: invoice summary for student-invoices + detail header.
  • Props: invoice (invoice.schema.ts:16-51), due (derived display), onTap.
  • Renders total/paid/due burst (displaySmall/titleLarge mono).

StructureCard

  • Purpose: structure list row: name, class/year, totalAmount, currency, dueDate, isActive, items.length, lateFee.
  • Props: structure, onTap, onEdit, onDelete, onDuplicate? (planned).

LineItemsTable

  • Purpose: structure line items (items[{name,amount}] fee-structure.schema.ts:18-22) + sum-vs-total warning AppBanner.
  • Props: items, totalAmount, currency.
  • Behaviour: if Σ items ≠ totalAmount show warning banner (server never validates the sum).

PaymentHistoryRow

  • Purpose: v2 payment row in invoice detail: transactionReference, amount, gateway, status chip.
  • Props: payment (payments/schemas/payment.schema.ts:28-77), onTap.

ReceiptDocument

  • Purpose: printable receipt view (receipt.schema.ts:7-41).
  • Props: receipt, actions (Print / Share), qr? (forward-looking).
  • Wrapped in RepaintBoundary for render-to-image.

DiscountsList

  • Purpose: invoice.discounts[] (invoice.schema.ts:46-50): rows name/−amount, caption "Reduces total at issue time".
  • Props: discounts, currency.

B. Money input

MoneyField (AppTextField variant)

  • Props: label, value (num?), currency, min (0), max?, validator (≥ 0 numeric), suffix currency code.
  • Behaviour: numeric keyboard (decimal), groups while typing, clears on focus; server @Min(0) per record-payment.dto.ts:19 — client matches.
  • A11y: label + Semantics(value: amount + currency).

DiscountEditor

  • Purpose: add/remove discounts[] in Generate-invoice dialog (generate-invoice.dto.ts:13-22).
  • Props: items [{name, amount}], onAdd, onRemove, maxTotal (deducts from structure total).
  • Validation clientside: amount ≥ 0 (@Min(0)), name required @IsString (generate-invoice.dto.ts:16-20).

PaymentMethodSelector

  • Purpose: 5-option selector, exact enum values (record-payment.dto.ts:21-25): cash, bank_transfer, mobile_money, cheque, other.
  • Presented as: AppBottomSheet picker or four chips (cash + mobile_money are the till defaults) + "other".
  • Locale labels i18n keys; raw string sent to server.

D. Dues aggregation

DuesSummaryTiles

  • Purpose: fees home stat tiles (total due, overdue count, partial count) computed from the dues page (client grouping by invoice.status).
  • Props: rows (DuesRow[]).
  • Note: numbers are derived display; authoritative per-invoice due is server (fees.service.ts:213-216).

E. Only elements the API supports

The module renders only fields the schemas/DTOs expose:

  • Structure: name, classId, academicYearId, items[{name,amount}], totalAmount, currency, dueDate, lateFee, isActive.
  • Invoice: studentId, feeStructureId, academicYearId, totalAmount, paidAmount, status, dueDate, issuedAt?, discounts[{name,amount}].
  • Payment (fees): invoiceId, amount, paymentMethod, reference?, idempotencyKey, paidAt, notes?, status.
  • Payment (v2): transactionReference, amount, fee, refundedAmount, currency, gateway, gatewayTransactionId?, gatewayResponse?, status, invoiceId?, invoiceType?, payerId?, payerEmail?, payerName?, description?, metadata?.
  • Receipt: receiptNumber, paymentId, invoiceId?, amount, fee, currency, paymentMethod, payerName, payerEmail, description, issuedAt. No waive, balance-string, or per-invoice endpoint fields — those are (planned) (IMPLEMENTATION_PLAN.md:206-211).

F. Flutter widget map (module)

features/fees/presentation/widgets/
├── amount_text.dart          # MoneyAmount
├── status_chip.dart          # StatusChip (invoice/payment/active)
├── due_row.dart
├── invoice_card.dart
├── structure_card.dart
├── line_items_table.dart
├── discounts_list.dart
├── payment_history_row.dart
├── receipt_document.dart
├── dues_summary_tiles.dart
├── payment_method_selector.dart
├── money_field.dart
└── discount_editor.dart

G. Golden tests

AmountText, StatusChip, InvoiceCard, DueRow, ReceiptDocument, LineItemsTable — light/dark × 3 sizes (00-shared/03 G). Money locale (0-major-unit currency) snapshot tests included.