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

10 — Interaction Specification (Leave Module)

Interaction patterns per screen: gestures, transitions, feedback, offline behavior, optimistic updates, and edge handling. Motion tokens (m-fast, m-base), haptics, and offline policy per 00-shared/08; QA baseline in 00-shared/10.


1. Navigation & transitions

RouteTransition
Home → Leave workspaceplatform default push (per 00-shared/08)
My Requests → New Requestpush (m-base slide)
List → Detailbottom sheet (mobile) / right pane (tablet)
Approvals → Assign Substitutionbottom sheet with form
Balance ↔ Requestshorizontal tabs or back-stack; no bottom-nav duplication

2. List screens (My Requests, Approvals, Substitutions)

Gesture/eventBehavior
Pull-to-refreshRefreshIndicator; refetch active filter; m-fast fade-in on updated rows
Tap rowopen detail sheet (My Requests) / nothing extra (Approvals rows open action sheet)
Filter chip taprefetch ?status= server-side (leave.controller.ts:40); keep scroll position
Swipenone (no destructive actions exist)
Offline opencached snapshot + AppOfflineBanner; CTA disabled for mutating actions
LoadingAppSkeleton rows (never spinners for whole list)
EmptyAppEmptyState with contextual CTA ("Request leave", "No substitutions")

3. Request form

InteractionSpec
Type pickerdropdown; types cached in LeaveTypesCubit after first GET /leave/types
Date pickersDatePicker; select start → auto-suggest end ≥ start (clamp); days preview updates live
Live days previewrecompute on each date change (inclusive count, leave.service.ts:310-312) with weekend hint
SubmitAppButton loading state; no optimistic creation (id is server-assigned); on 200 → toast "Submitted — pending approval", pop to list where new row appears at top (createdAt desc, leave.service.ts:168)
404 typeinline + auto-refetch types
Double-tap submitguarded (in-flight flag)

4. Decision interaction (Approvals Queue)

InteractionSpec
Approve1 tap → PATCH with {action:"approve"} → row shows neutral "processing" → on 200 flips to approved & leaves pending list; on 409 reverts + toast
Rejecttap → sheet: optional note + confirm → PATCH {action:"reject", note}
Optimistic policyno optimistic status change — balance is affected (leave.service.ts:183-190); wait for 200, then animate chip swap (m-fast)
409 insufficient balancerow gets inline error chip "Insufficient balance"; approve disabled for that row until refetch; reject remains available
409 already decidedtoast + row removed on refetch
409 self-decisionrow never rendered for self (client filter)

5. Assign substitution sheet

InteractionSpec
Teacher pickersearch-as-you-type against teachers module (forward-looking); shows clash-free candidates only where known
Date pickerclamped hint to approved leave range (client only — gap)
Time pickersstart→end chained; end defaults start+1 h
Submiton 409 clash → inline error under time fields; on 404 → toast; on 200 → toast + switch to Substitutions list

6. Calendar

InteractionSpec
Month pagerswipe (mobile) + chevrons; fetch from/to per month (leave.controller.ts:85-91)
Day tapbottom sheet listing approved requests that day
Todayoutlined cell; selected month highlighted
Refreshpull-to-refresh refetches visible month

7. Feedback & haptics

  • Success toasts: AppSnackbar (short); decision approve = subtle haptic (HapticFeedback.selectionClick); errors = mediumImpact + inline error (00-shared/08).
  • No confetti; no destructive-confirm for approve (only reject).

8. Offline matrix

ScreenReadWrite
Balancecached snapshot (≤ 1 session)n/a
My Requestscached list; status may be stale → bannerblock new request (needs live type/balance truth)
Approvalscached listblock decisions (balance check server-side, leave.service.ts:184-190)
Substitutionscached listblock
Calendarcached monthn/a

9. Accessibility interactions

  • Focus order: filters → list → FAB/CTA; sheets trap focus; dismiss via swipe-down + Esc (desktop) + scrim tap.
  • All mutations require a visible confirmation state (no silent writes).
  • Reduced motion: m-fast becomes instant (per 00-shared/09).