10 — Interaction Specification (Fees Module)
- 1. Phone / touch
- 2. Keyboard / desktop / mouse
- 3. Haptics (mobile)
- 4. Motion language (module extension of 00-shared/08 §4)
- 5. Micro-interactions catalogue
- 6. Frustration controls (shared 00-shared/08 §6 + module)
- 7. Special: deep-link & clipboard
- 8. Validation of interaction to server semantics
Platform interaction detail for the Fees screens; extends 00-shared/08. Motion tokens
Mo.*= 00-shared/02 §6;F= focus/touch baseline.
1. Phone / touch
- Dues list: tap row → invoice detail; tap inline "Collect" icon-button
(44 dp, tooltip) → record-payment sheet;
RefreshIndicator; infinite scroll with bottomAppProgress. - Invoices list (student): tap card → detail; pull-to-refresh.
- Record payment: full-height
AppBottomSheet(r-xl, drag handle) with keyboard avoidance (resizeToAvoidBottomInset: true); CTA pinned above keyboard. - Generate invoice:
AppDialog(format): student dropdown + discounts editor; button "Generate invoice". - Receipt view: render +
Shareaction(proposed); long-press number to copy.
2. Keyboard / desktop / mouse
- Amounts: decimal numeric pad;
.nextfield order;Ctrl/Cmd+Entersubmit on forms. - Desktop
N= new structure (list screen);E= edit (detail) — app-level. - Hover states on cards/rows (00-shared/02 §9); hover scale on badges
(proposed). - Right-click row menu for structure rows (Edit / Delete; Duplicate
(planned)).
3. Haptics (mobile)
- Success payment post: light success tap; error/409: warning buzz (short).
- Pull-to-refresh: default haptic; new invoice issued: subtle confirmation.
4. Motion language (module extension of 00-shared/08 §4)
- List transitions
Mo.m-entrancestagger 40 ms; card fade for deletionMo.m-base. - Amount changes animate by counting (
AnimatedSwitcher/IntrinsicCounter) overMo.m-base, only when server-confirmed — never optimistic. - Status chip swaps:
AnimatedSwitcherMo.fast, cross-fade only. - Sheet: standard spring up
Mo.m-base; dialogMo.m-basescale+fade. - Reduced-motion: all
Mo.m-instantstatic; no counting animation, no parallax.
5. Micro-interactions catalogue
| Interaction | Trigger | Feedback |
|---|---|---|
| Record payment submit | tap FilledButton | spinner (icon→spinner), disabled inputs, live-region announce |
| Generate invoice | dialog submit | spinner; then snackbar "Invoice issued" |
| Refresh dues | pull | RefreshIndicator; success silent |
| Overpay attempt (amount > due) | edge | inline tertiary banner "Exceeds remaining balance" + preview resulting paidAmount |
| Amount focus | MoneyField | select-all, hide grouping suffix until blur |
| Copy reference | long-press on transactionReference rows | snackbar "Copied {ref}" |
| Back from dirty sheet | system-back | (proposed) "Discard payment?" dialog |
| 409 duplicate-invoice | submit response | inline AppBanner(info), dialog stays |
| 409 paid/cancelled | submit response | close + snackbar(info) |
6. Frustration controls (shared 00-shared/08 §6 + module)
- Retry always on
AppErrorState; 429 → countdown text, no auto-retry (00-shared/07 §4 api 100/min). - Snackbar error persists ≥ 4 s (00-shared/03 §A); success < 3 s.
- Status changes (e.g. invoice → paid) announce via
Semantics(liveRegion).
7. Special: deep-link & clipboard
(proposed)deeplinks:studylyon://fees/dues,studylyon://fees/structures/:id,studylyon://fees/invoices/:id,studylyon://payments/receipts/:id.- Notification tap → invoice detail (when
invoice.updated/receipt notification lands;(planned)). - Amounts copying: long-press
MoneyAmount→ copy raw number + currency.
8. Validation of interaction to server semantics
| Client interaction | Server semantics (must not diverge) |
|---|---|
| Sheet "Record payment" success | server 201 + recompute paidAmount/status (fees.service.ts:168-176) |
| Sheet retry with same key | replay original doc (fees.service.ts:148-152) |
| Generate invoice success | server 201, _id returned; issuedAt set server-side (fees.service.ts:122-130) |
| Duplicate generation 409 | treated as already-exists navigation (fees.service.ts:107-115) |
Refund amount reduction | server caps refunds ≤ payment (payments.service.ts:81-86) |
| Online payment | transactionReference from server (payments.service.ts:215-217); local refs never sent |
| Any amount displayed | source of truth = server field; formatting client-side only (06 §0; OQ-1) |