ui phase 12
This commit is contained in:
+24
-2
@@ -244,6 +244,7 @@ client/
|
||||
│ │ ├── Pager/ # ui-phase-7 — the shared prev/next "page X of Y" control (common namespace i18n) replacing the near-identical inline pagers hand-rolled per list screen (nurse inbox tabs, payout history/earnings) (tested)
|
||||
│ │ ├── InitialsAvatar/ # ui-phase-9 — warm auto-colored initials for a person with no photo: deterministic name-hash → one of 6 `--bal-avatar-*` token pairs (tokens.css, both scheme blocks); `aria-hidden` (decorative next to a visible name); used by `PatientHeader` and (via `ProfileSummary`'s new `initialsFallback` prop) the customer account hub (tested)
|
||||
│ │ ├── FormDialogShell/ # ui-phase-9 — full-screen-below-`sm` form dialog (app-bar header + close) with a dirty-gated discard-confirm on close/backdrop/escape; the shared primitive behind the patient/address add-edit dialogs (the hosted form reports `dirty` via an `onDirtyChange` prop) (tested)
|
||||
│ │ ├── RouteFadeIn/ # ui-phase-12 — the one route-content fade/slide primitive (motion pass): wraps `{children}`, keyed on the locale-stripped pathname so it remounts (replays the CSS `bal-fade-in` keyframe, globals.css) on navigation but never on an in-place re-render; mounted inside the `ErrorBoundary` in all five shells (tested)
|
||||
│ │ └── index.tsx # barrel — keep next-intl-importing primitives (Money) below the presentational ones so the poisoning risk stays visible in review
|
||||
│ ├── admin/ # f15 backoffice + partner composites (import from `@/components/admin`): AdminDataTable (v2, ui-phase-11 — optional per-column server-param `sort`/`sortable` + `TableSortLabel`, `stickyHeader` scroll viewport, `minWidth`, a `footer` line), AdminPager (page/pageCount; the admin `page_indicator` i18n key regained its `{total}`), AdminPageHeader/AdminEmptyState/AdminErrorState, ConfirmDialog (thin alias), ConfigRow/AuditLogRow (ui-phase-11 — expand chevron rotates + `aria-expanded` + button semantics, new `actorLabel` prop resolved via a batch id→name lookup)/SupportAlertCard (ui-phase-11 — `assignSelfDisabled`/`assignSelfDisabledTitle` so "assign to me" never falls back to a guessed user)/PartnerSettlementRow, DocumentViewer, RefundPanel, AdminMessageBubble, and (ui-phase-11) `UserPicker`/`NursePicker` — async name/phone `Autocomplete` over the admin user directory (REQ-061, mock-backed), replacing every raw numeric-id `TextField` on an audited action; each option renders name+masked-phone+id, never a bare id
|
||||
│ ├── PlaceholderScreen/ # Empty-state scaffold for not-yet-built screens
|
||||
@@ -387,7 +388,7 @@ client/
|
||||
│ ├── tokens.css # CSS custom properties — [data-mui-color-scheme] selectors + the dark @media fallback (no-flash boot, no script — see "Theme System" below)
|
||||
│ ├── typography.ts # TYPOGRAPHY_LTR (Space Grotesk) / TYPOGRAPHY_RTL (Mikhak) — shared size scale, 500/700 weight system
|
||||
│ └── index.ts # Public re-exports (ThemeProvider, getDirection, APP_THEME_*)
|
||||
├── constants/ # App-wide constants (routes.ts w/ actor paths, roles.ts, headers.ts)
|
||||
├── constants/ # App-wide constants (routes.ts w/ actor paths, roles.ts, headers.ts, policy.ts — ui-phase-12's single-sourced trust-copy numbers pending REQ-065)
|
||||
├── hooks/ # incl. auth.ts → useIsAuthenticated / useActorRole (role-aware chrome); ui-phase-11 added `useAdminListState.ts` — URL-synced worklist state (`useSearchParams`-based; callers need a `<Suspense>` boundary) mirroring **applied** filters+page into the URL (draft-vs-applied; `apply`/`applyFilters`/`clear`/`goToPage`) + `useAdminBackToList` (a real `router.back()` with a list-route fallback), adopted by every admin/partner queue page
|
||||
├── utils/ # incl. money.ts (IRR/Toman, integer-safe) + date.ts (Shamsi display) + number.ts (localeTag/formatNumber/formatRelativeTime/formatClock — the one home for locale-ternary formatting) + toEnglishDigits + toCsv.ts (ui-phase-11 — dependency-free CSV serializer, CRLF + comma/quote escaping; backs the partner settlement CSV export, UTF-8-BOM-prefixed for Excel)
|
||||
└── config.ts
|
||||
@@ -511,6 +512,13 @@ namespaces and both files in sync.
|
||||
|
||||
**Never hard-code UI strings in English.** Any user-visible text must have a translation key in both locale files.
|
||||
|
||||
**Persian orthography is a checked-in style guide, not tribal knowledge.** `client/messages/STYLE.md`
|
||||
(ui-phase-12) is the binding decision record for brand spelling (ZWNJ: «بالینیار»), تأیید's hamza form,
|
||||
the one `جستجو` spelling, ZWNJ rules, the domain glossary, the shell-naming system, the
|
||||
verification-pipeline-vs-KYC-step naming split, and the digits/policy-number-interpolation rules.
|
||||
`npm run lint:copy` (`client/scripts/check-copy.mjs`, part of `npm run check`) greps `fa.json` for the
|
||||
banned variants on every run — a regression fails the gate immediately, it doesn't need re-discovering.
|
||||
|
||||
---
|
||||
|
||||
## Cookie Manager
|
||||
@@ -542,7 +550,7 @@ A value is "magic" if its meaning isn't obvious from the literal alone: cookie n
|
||||
Where to define:
|
||||
- **Cookie names / options**: `src/lib/cookies/constants.ts`
|
||||
- **Feature-scope constants**: co-locate in a `constants.ts` next to that feature's files
|
||||
- **App-wide constants** (used across multiple features): `src/constants/` — one file per concern (`routes.ts`, `events.ts`, etc.)
|
||||
- **App-wide constants** (used across multiple features): `src/constants/` — one file per concern (`routes.ts`, `events.ts`, etc.). `constants/policy.ts` (ui-phase-12) is this pattern applied to legally-sensitive numbers that trust-critical copy states in plain language (the payout dispute-window hours, the cancellation lead-time hours, the refund ETA day range) — real server config with no public/authenticated read yet (REQ-065), single-sourced here and fed into message keys as ICU params (`{hours}`, `{minDays}`/`{maxDays}`) instead of being baked into the string.
|
||||
|
||||
Rules:
|
||||
1. Import the constant; never copy-paste the string value.
|
||||
@@ -627,6 +635,20 @@ This includes feedback colors: `--bal-success`, `--bal-error`, `--bal-warning`,
|
||||
|
||||
`APP_THEME_LTR` and `APP_THEME_RTL` are created once at module load. Never call `createTheme()` inside a component or hook — pass the appropriate pre-built theme to `MuiThemeProvider`.
|
||||
|
||||
### Motion & the reduced-motion gate
|
||||
|
||||
Durations/easing live as tokens in `tokens.css` (`--bal-motion-fast/-base/-slow`, `--bal-easing-standard`);
|
||||
`theme.ts` points `MuiDialog`/`MuiDrawer`/`MuiPopover`/`MuiMenu`'s `defaultProps.transitionDuration` at the
|
||||
same numbers (in one place) instead of MUI's per-variant defaults. `RouteFadeIn`
|
||||
(`components/common/RouteFadeIn/`) is the one route-content fade/slide primitive, mounted inside the
|
||||
`ErrorBoundary` in all five shells — new pages get the motion for free, no per-page wiring.
|
||||
**`prefers-reduced-motion: reduce` has exactly one gate**, in `src/app/globals.css`: a universal
|
||||
`*, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; … }`
|
||||
media-query block. This is deliberately a global CSS reset, not a token-only zeroing (`tokens.css` also
|
||||
zeroes the duration tokens, but that alone wouldn't reach MUI's own JS-driven Dialog/Drawer/Menu/Collapse
|
||||
transitions, which don't read the CSS custom properties) — never add a second, component-local
|
||||
reduced-motion branch; extend this one rule if a new motion primitive needs the same treatment.
|
||||
|
||||
### Toggle components
|
||||
|
||||
`DarkModeToggleButton` and `DarkModeFormSwitch` in `src/layout/components/DarkModeButton.tsx` are the **only** components that subscribe to `useColorScheme()`. When the user toggles:
|
||||
|
||||
Reference in New Issue
Block a user