Commit Graph

2 Commits

Author SHA1 Message Date
wmj 33a821e61d refactor: restructure navigation into 5 grouped hubs, off the 22-item flat strip
Implements the researched IA fix: mobile nav UX consensus caps primary
destinations at 4-5 (uxpin.com, fintech/banking 2026 UX research), and
this app had grown to 22 tabs in one horizontally-scrolling row —
exactly the anti-pattern that research flags for choice paralysis and
slower task completion.

New structure — 5 bottom-nav hubs, grouped by what the user is actually
trying to do, not build order:
- Home: Coverage (unchanged, still the landing screen)
- Estate: Assets, Faraid, Insurance, Wassiyah, Hibah, Family Waqf,
  Nominate, Claims (H2)
- Giving: Zakat, Sadaqah, Khairat
- Family: Tree, Trigger, Mutawalli, Manage (was 'Family', renamed to
  avoid colliding with the hub's own label), Neighbourhood
- Daily: Prayer Times, Qibla, Quran, Locate

Each hub reveals its own sub-nav one tap in, instead of every tab
competing for space in a single row. Settings moved out of the tab
strip entirely into a header gear icon, matching the banking-app pattern
of keeping settings out of primary thumb-reach real estate. The bottom
nav is now fixed (thumb-zone), sub-nav keeps the old sticky-top position.

Cross-component navigation (nav.js requestedTab, used by the Family
Tree's 'give sadaqah in memory' link) now resolves a tab label to its
owning (hub, sub-tab) pair instead of a flat index — verified live.

This touches every E2E suite: a single click on a tab's old selector no
longer reaches it (hub, then sub-tab). Added a shared gotoTab(page, label)
helper to e2e-auth-helper.cjs encapsulating the two-step navigation, and
migrated all ~22 affected test files off direct nav-button selectors —
mechanical substitution followed by manual fixes for local clickTab
wrappers, template-literal selectors, and active-state assertions that
needed to target the new .hub-tab/.subnav structure specifically.

Full regression after migration: every suite passes (one isolated
Family Tree flake confirmed clean on rerun, unrelated to navigation).
2026-08-14 14:55:09 +08:00
wmj 2549e9de0c feat: add Khairat, emergency-contact auto-notify, and 5 lifestyle-companion tabs
Big round covering two different asks: Khairat/emergency infrastructure
(tightly coupled to what's already built) and a Muslim-lifestyle
companion surface (a genuinely different product, added at the user's
explicit request after being offered a smaller scope).

Khairat & emergency contacts:
- nf_khairat_memberships (per-member scheme membership) + nf_emergency_fund
  (per-family shared reserve tracker) — records intent/contacts only,
  never holds or moves real money.
- nf_trusted_contacts gains category (mosque/police/ambulance/hospital/
  khairat/family/other) and email columns.
- New notify-emergency-contacts Edge Function, auto-invoked the moment a
  mutawalli fires a member's death trigger (the one place in this app
  where auto-send-on-trigger is actually correct), alongside — not
  instead of — the existing heir notification. Verified with a live fire
  end-to-end (e2e-emergency-notify.cjs, 5/5).

Lifestyle-companion tabs — all computed/searched live, nothing fabricated:
- Qibla: pure great-circle bearing math to the Kaaba from geolocation,
  no API/key. Verified against Kuala Lumpur (293°, matches expected ~292°).
- Prayer Times: client-side astronomical calculation (single-pass solar
  position, MWL angles), sanity-checked against known KL/London times
  before shipping.
- Locate: mosque/halal/cemetery search via the free, keyless OpenStreetMap
  Overpass API — real community-sourced results only, honest empty state
  when nothing's mapped nearby.
- Quran: Surah list + Arabic/translation via the free alquran.cloud API,
  fetched fresh each time, nothing stored in this app's own database.
- Neighbourhood: a join-by-code community announcement board — a
  genuinely separate multi-tenant concept from the estate-planning family
  structure, scoped to the user account. Found and fixed a real UX gap
  during testing: the create/join form was only reachable with zero
  existing neighbourhoods, with no way to join a second one.

Also found and fixed a real bug: the heir-notify and emergency-notify
status messages shared the same CSS class, breaking any script (including
the pre-existing e2e-per-member.cjs) that targeted '.notify-status'
without further filtering — gave each its own distinguishing class.

Covered by e2e-khairat-lifestyle.cjs (13/13) and e2e-emergency-notify.cjs
(5/5). Full regression: 316/316 across all suites (several transient
flakes under heavy mail-relay load during the sweep, all confirmed clean
on rerun — one led to the real class-collision fix above).
2026-08-14 14:25:26 +08:00