07 — Component Library (Fees Module)
- A. Fees representation
- B. Money input
- D. Dues aggregation
- E. Only elements the API supports
- F. Flutter widget map (module)
- G. Golden tests
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
AppMoneyhelper (15_Flutter_Implementation_Guide.md §4).
A. Fees representation
MoneyAmount
- Purpose: canonical amount rendering (mono,
tabularFigures). - Props:
amount(num),currency(default from context: structurecurrencydefaultXAFfee-structure.schema.ts:27-28; v2USDpayments/schemas/payment.schema.ts:42-43),style(display|title|label),zeroState("Settled"/"Free"). - Rules:
intl.NumberFormat.currency;XAF0 decimals,USD2; never "-0"; alwaysFontFeature.tabularFigures(). - Flutter:
Text+TextStyle.monospacewrapperAmountText.
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|cancelled—invoice.schema.ts:7-14),paymentStatus?(PaymentStatuspayments/schemas/payment.schema.ts:18-26),boolStatus?(structureisActive). - Flutter: custom
StatusChip→Container+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-basedDueRow(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/titleLargemono).
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 warningAppBanner. - Props:
items,totalAmount,currency. - Behaviour: if
Σ items ≠ totalAmountshow 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
RepaintBoundaryfor 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)perrecord-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:
AppBottomSheetpicker 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
dueis 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. Nowaive,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.