feat: redesign routed ZarinPal merchant dashboard

This commit is contained in:
2026-08-20 21:41:18 +03:30
parent d8eeff57cd
commit 9ce2e6ec83
183 changed files with 7991 additions and 1569 deletions

View File

@@ -15,17 +15,17 @@ Implementation is authorized through the approved Phase 3 task list. Each work p
## 2. Approved inputs
| Input | Status | Planning use |
|---|---|---|
| `docs/DASHBOARD-SPEC.md` | Approved for planning | Product scope and acceptance criteria |
| `docs/DASHBOARD-UX-SPEC.md` | Approved for planning | Screen, state, content, responsive, export, and accessibility behavior |
| `DESIGN.md` `0.3.2` | Approved baseline | Tokens, themes, FaNum font, RTL, component contracts, and motion |
| Backend `IDENTITY-SPEC.md` | Approved | Session, login, logout, CSRF, throttle, and tenant boundary |
| Backend `ANALYTICS-SPEC.md` | Approved | Metric lifecycle, partial delivery, retries, thresholds, and privacy |
| Backend `METRIC-CATALOGUE.md` `0.4.0` | Approved definitions | Metric semantics and formatting evidence |
| Backend `API-SPEC.md` | Approved | REST/SSE/CSV behavior and provider boundary |
| Backend `docs/openapi.yaml` `1.0.0` | Approved | Generated types and operation contracts |
| Nginx/static routing contract | Approved | Production/static-host verification contract |
| Input | Status | Planning use |
| ------------------------------------- | --------------------- | ---------------------------------------------------------------------- |
| `docs/DASHBOARD-SPEC.md` | Approved for planning | Product scope and acceptance criteria |
| `docs/DASHBOARD-UX-SPEC.md` | Approved for planning | Screen, state, content, responsive, export, and accessibility behavior |
| `DESIGN.md` `0.3.2` | Approved baseline | Tokens, themes, FaNum font, RTL, component contracts, and motion |
| Backend `IDENTITY-SPEC.md` | Approved | Session, login, logout, CSRF, throttle, and tenant boundary |
| Backend `ANALYTICS-SPEC.md` | Approved | Metric lifecycle, partial delivery, retries, thresholds, and privacy |
| Backend `METRIC-CATALOGUE.md` `0.4.0` | Approved definitions | Metric semantics and formatting evidence |
| Backend `API-SPEC.md` | Approved | REST/SSE/CSV behavior and provider boundary |
| Backend `docs/openapi.yaml` `1.0.0` | Approved | Generated types and operation contracts |
| Nginx/static routing contract | Approved | Production/static-host verification contract |
## 3. Planning assumptions
@@ -137,16 +137,16 @@ Route groups share authentication/layout requirements without changing public UR
### 5.3 State ownership
| State | Owner | Persistence |
|---|---|---|
| Server session and merchant scope | Backend | Secure server session; cookie unreadable to frontend |
| Session summary and CSRF value | Auth feature/context | Memory only; cleared on logout/401 |
| Theme choice | Theme service | Local presentation-only preference |
| Period type/id and detail filters/cursor | URL | Query parameters using server-allowlisted values |
| Analytics run and section states | Analytics-run feature | Memory; recover from run snapshot/SSE replay |
| Last SSE event id/liveness | Stream adapter | Memory for the current authorized run only |
| Form/dialog/drawer state | Owning component | Local Svelte rune state |
| Generated transport types | Build output/source | Regenerated from approved OpenAPI; never hand-edited |
| State | Owner | Persistence |
| ---------------------------------------- | --------------------- | ---------------------------------------------------- |
| Server session and merchant scope | Backend | Secure server session; cookie unreadable to frontend |
| Session summary and CSRF value | Auth feature/context | Memory only; cleared on logout/401 |
| Theme choice | Theme service | Local presentation-only preference |
| Period type/id and detail filters/cursor | URL | Query parameters using server-allowlisted values |
| Analytics run and section states | Analytics-run feature | Memory; recover from run snapshot/SSE replay |
| Last SSE event id/liveness | Stream adapter | Memory for the current authorized run only |
| Form/dialog/drawer state | Owning component | Local Svelte rune state |
| Generated transport types | Build output/source | Regenerated from approved OpenAPI; never hand-edited |
Ready section content remains immutable for a run dataset snapshot. Event reconciliation is idempotent by event and section identity. A sibling event cannot erase a valid ready section.
@@ -234,58 +234,58 @@ These are Phase 2 packages, not yet implementable Phase 3 tasks.
### Phase I — contracts and foundation
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P01 | Freeze API/OpenAPI and product limits | Gate A decisions | Approved versioned transport contract |
| P02 | Verify static-SPA/Nginx topology | P01, deployment decision | Deep links, `/api/v1`, assets, cache rules proven |
| P03 | Scaffold pinned SvelteKit/Svelte/Tailwind project | P02 | Minimal strict project and lockfile |
| P04 | Establish quality/test commands | P03 | Format, lint, check, unit, E2E, build scripts |
| P05 | Generate and drift-check API types | P01, P03 | Reproducible generated contract types |
| P06 | Implement design/theme/font foundation | P03 | RTL root, semantic themes, no-flash choice, tracked font |
| P07 | Establish contract-safe fixtures | P05 | Sensitive-free builders for all states/errors/events |
| ID | Work package | Depends on | Result |
| --- | ------------------------------------------------- | ------------------------ | -------------------------------------------------------- |
| P01 | Freeze API/OpenAPI and product limits | Gate A decisions | Approved versioned transport contract |
| P02 | Verify static-SPA/Nginx topology | P01, deployment decision | Deep links, `/api/v1`, assets, cache rules proven |
| P03 | Scaffold pinned SvelteKit/Svelte/Tailwind project | P02 | Minimal strict project and lockfile |
| P04 | Establish quality/test commands | P03 | Format, lint, check, unit, E2E, build scripts |
| P05 | Generate and drift-check API types | P01, P03 | Reproducible generated contract types |
| P06 | Implement design/theme/font foundation | P03 | RTL root, semantic themes, no-flash choice, tracked font |
| P07 | Establish contract-safe fixtures | P05 | Sensitive-free builders for all states/errors/events |
### Phase II — identity and reporting context
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P08 | Deliver login/session/logout slice | P04–P07 | Generic/throttled login and revocable session flow |
| P09 | Deliver authenticated shell | P08 | RTL sidebar/drawer, merchant identity, theme, route protection |
| P10 | Deliver Persian formatters | P04, P06 | Digits, Rial, Jalali/Tehran, percent, bidi isolation |
| ID | Work package | Depends on | Result |
| --- | ------------------------------------ | ------------- | --------------------------------------------------------------- |
| P08 | Deliver login/session/logout slice | P04–P07 | Generic/throttled login and revocable session flow |
| P09 | Deliver authenticated shell | P08 | RTL sidebar/drawer, merchant identity, theme, route protection |
| P10 | Deliver Persian formatters | P04, P06 | Digits, Rial, Jalali/Tehran, percent, bidi isolation |
| P11 | Deliver periods and URL filter slice | P05, P08, P10 | Server-allowlisted default/selection and navigation restoration |
### Phase III — partial analytics
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P12 | Resolve SSE transport spike | P01, P05, P08 | Documented tested transport choice |
| ID | Work package | Depends on | Result |
| --- | ---------------------------------------- | ------------- | ------------------------------------------------------------ |
| P12 | Resolve SSE transport spike | P01, P05, P08 | Documented tested transport choice |
| P13 | Deliver run/snapshot/section state model | P07, P11, P12 | Idempotent start, independent sections, typed errors/retries |
| P14 | Deliver overview slice | P10, P13 | KPI priority, comparisons, eligible insights, definitions |
| P15 | Deliver payment-performance slice | P10, P13 | Outcomes, retry, timing, stage semantics |
| P16 | Deliver fees slice | P10, P13 | Session-grain real Rial fees and rate |
| P17 | Deliver peer-comparison slice | P10, P13 | Median/percentile or privacy-safe suppression |
| P18 | Integrate recovery and rate-limit flows | P13–P17 | Heartbeat, replay/reset, sibling isolation, manual retry |
| P14 | Deliver overview slice | P10, P13 | KPI priority, comparisons, eligible insights, definitions |
| P15 | Deliver payment-performance slice | P10, P13 | Outcomes, retry, timing, stage semantics |
| P16 | Deliver fees slice | P10, P13 | Session-grain real Rial fees and rate |
| P17 | Deliver peer-comparison slice | P10, P13 | Median/percentile or privacy-safe suppression |
| P18 | Integrate recovery and rate-limit flows | P13–P17 | Heartbeat, replay/reset, sibling isolation, manual retry |
### Phase IV — merchant-owned evidence and export
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P19 | Deliver shared cursor-detail foundation | P05, P09–P11 | Semantic responsive table, URL filters, cursor rules |
| P20 | Deliver unverified-paid detail slice | P15, P19 | Authorized read-only `Paid` evidence |
| P21 | Deliver failed detail slice | P15, P19 | Safe observed-stage filters without invented causes |
| P22 | Deliver retried detail slice | P15, P19 | Ordered attempt summaries and recovery evidence |
| P23 | Resolve CSV delivery spike | P01, P08, P19 | Approved browser download/error strategy |
| P24 | Deliver CSV export slice | P20–P23 | Current-filter authorized export and handoff UX |
| ID | Work package | Depends on | Result |
| --- | --------------------------------------- | ------------- | ---------------------------------------------------- |
| P19 | Deliver shared cursor-detail foundation | P05, P09–P11 | Semantic responsive table, URL filters, cursor rules |
| P20 | Deliver unverified-paid detail slice | P15, P19 | Authorized read-only `Paid` evidence |
| P21 | Deliver failed detail slice | P15, P19 | Safe observed-stage filters without invented causes |
| P22 | Deliver retried detail slice | P15, P19 | Ordered attempt summaries and recovery evidence |
| P23 | Resolve CSV delivery spike | P01, P08, P19 | Approved browser download/error strategy |
| P24 | Deliver CSV export slice | P20–P23 | Current-filter authorized export and handoff UX |
### Phase V — completion and hardening
| ID | Work package | Depends on | Result |
|---|---|---|---|
| P25 | Deliver methodology and account screens | P09–P18 | Metric/privacy explanations and demo switching/logout guidance |
| P26 | Complete responsive RTL and theme matrix | P14–P25 | 360/768/1024/1440 and both themes |
| P27 | Complete accessibility/reduced-motion verification | P14–P26 | WCAG 2.2 AA critical flows and chart/table equivalence |
| P28 | Complete security/privacy negative tests | P08–P24 | No cross-tenant/payer/peer/token exposure |
| P29 | Complete static production acceptance | P02–P28 | Build artifact passes target Nginx critical flows |
| P30 | Final documentation and human review | P29 | Current docs, evidence, approval for release handoff |
| ID | Work package | Depends on | Result |
| --- | -------------------------------------------------- | ---------- | -------------------------------------------------------------- |
| P25 | Deliver methodology and account screens | P09–P18 | Metric/privacy explanations and demo switching/logout guidance |
| P26 | Complete responsive RTL and theme matrix | P14–P25 | 360/768/1024/1440 and both themes |
| P27 | Complete accessibility/reduced-motion verification | P14–P26 | WCAG 2.2 AA critical flows and chart/table equivalence |
| P28 | Complete security/privacy negative tests | P08–P24 | No cross-tenant/payer/peer/token exposure |
| P29 | Complete static production acceptance | P02–P28 | Build artifact passes target Nginx critical flows |
| P30 | Final documentation and human review | P29 | Current docs, evidence, approval for release handoff |
## 8. Vertical acceptance slices
@@ -319,18 +319,18 @@ User confirms view/period/filter scope and downloads the synchronous server-owne
Exact command names are established in P04 and recorded in `package.json`; the required categories are:
| Level | Purpose | Required evidence |
|---|---|---|
| OpenAPI validation/generation | Prevent interface drift | Approved contract validates; generated output is reproducible |
| Unit | Formatters, reducers, error mapping, insight eligibility | Boundary tables for zero/null/decimal/RTL/event duplication |
| Component | Semantic states and interactions | Roles/names/focus/live-region behavior in both themes |
| Integration with contract fixtures | API client, auth, run/SSE, details/export | Every success/problem/event state maps correctly |
| Playwright | Critical user journeys | Login, default period, partial order, reconnect, detail, export, logout |
| Accessibility automation | Detect common WCAG failures | Axe-equivalent checks plus no serious/critical violations |
| Manual accessibility | Cover automation gaps | Keyboard, screen reader status, zoom/reflow, focus restoration |
| Visual/responsive | RTL/theme/layout stability | 360/768/1024/1440, light/dark, known long Persian content |
| Static production | Prove target topology | Built files behind Nginx, deep-link refresh, API/SSE/CSV proxy |
| Security/privacy | Negative authorization/data tests | Manipulated ids/cursors/filters and sensitive-field absence |
| Level | Purpose | Required evidence |
| ---------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------- |
| OpenAPI validation/generation | Prevent interface drift | Approved contract validates; generated output is reproducible |
| Unit | Formatters, reducers, error mapping, insight eligibility | Boundary tables for zero/null/decimal/RTL/event duplication |
| Component | Semantic states and interactions | Roles/names/focus/live-region behavior in both themes |
| Integration with contract fixtures | API client, auth, run/SSE, details/export | Every success/problem/event state maps correctly |
| Playwright | Critical user journeys | Login, default period, partial order, reconnect, detail, export, logout |
| Accessibility automation | Detect common WCAG failures | Axe-equivalent checks plus no serious/critical violations |
| Manual accessibility | Cover automation gaps | Keyboard, screen reader status, zoom/reflow, focus restoration |
| Visual/responsive | RTL/theme/layout stability | 360/768/1024/1440, light/dark, known long Persian content |
| Static production | Prove target topology | Built files behind Nginx, deep-link refresh, API/SSE/CSV proxy |
| Security/privacy | Negative authorization/data tests | Manipulated ids/cursors/filters and sensitive-field absence |
No task is complete with only typecheck/build evidence; runtime behavior and relevant error paths must be exercised.
@@ -373,21 +373,21 @@ No task is complete with only typecheck/build evidence; runtime behavior and rel
## 11. Risks and mitigations
| Risk | Impact | Mitigation |
|---|---|---|
| Implementing against draft OpenAPI | High rework/contract drift | Hard Gate A; generated types only from approved version |
| Native `EventSource` hides HTTP error detail | High recovery/accessibility gap | P12 spike; select fetch stream only if evidence requires it |
| Two reconnect owners create duplicate streams | High rate-limit/data duplication | One transport owner, explicit cleanup, concurrency tests |
| Synchronous CSV cannot support promised ready/error UX | High misleading behavior | P23 spike and UX amendment before export implementation |
| 50 MiB Blob download harms mobile memory | Medium/High | Measure at cap; prefer server streaming/direct download or revise policy |
| Static fallback mishandles deep links/API paths | High production failure | P02 Nginx proof before feature work |
| Chart library adds inaccessible/RTL-heavy dependency | Medium | Start semantic SVG/HTML; add dependency only after focused evaluation |
| Decimal strings are coerced to floating point | High financial display error | Exact parsing/format tests; format transport decimals deliberately |
| Persian/Jalali/bidi formatting corrupts technical ids | High trust/usability issue | Central formatters, long/mixed fixtures, screen-reader and visual review |
| Theme initialization flashes or leaks state across tests | Medium | Pre-paint presentation-only bootstrap and deterministic theme tests |
| Completion-order rendering shifts layout/focus | High accessibility issue | Stable frames, reducer tests, focus-preservation E2E |
| Handwritten DTOs drift from OpenAPI | High integration failure | Generated types plus CI drift check; view models remain separate |
| Fixtures accidentally contain source-sensitive data | High privacy issue | Synthetic builders, forbidden-field scans, review gate |
| Risk | Impact | Mitigation |
| -------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------ |
| Implementing against draft OpenAPI | High rework/contract drift | Hard Gate A; generated types only from approved version |
| Native `EventSource` hides HTTP error detail | High recovery/accessibility gap | P12 spike; select fetch stream only if evidence requires it |
| Two reconnect owners create duplicate streams | High rate-limit/data duplication | One transport owner, explicit cleanup, concurrency tests |
| Synchronous CSV cannot support promised ready/error UX | High misleading behavior | P23 spike and UX amendment before export implementation |
| 50 MiB Blob download harms mobile memory | Medium/High | Measure at cap; prefer server streaming/direct download or revise policy |
| Static fallback mishandles deep links/API paths | High production failure | P02 Nginx proof before feature work |
| Chart library adds inaccessible/RTL-heavy dependency | Medium | Start semantic SVG/HTML; add dependency only after focused evaluation |
| Decimal strings are coerced to floating point | High financial display error | Exact parsing/format tests; format transport decimals deliberately |
| Persian/Jalali/bidi formatting corrupts technical ids | High trust/usability issue | Central formatters, long/mixed fixtures, screen-reader and visual review |
| Theme initialization flashes or leaks state across tests | Medium | Pre-paint presentation-only bootstrap and deterministic theme tests |
| Completion-order rendering shifts layout/focus | High accessibility issue | Stable frames, reducer tests, focus-preservation E2E |
| Handwritten DTOs drift from OpenAPI | High integration failure | Generated types plus CI drift check; view models remain separate |
| Fixtures accidentally contain source-sensitive data | High privacy issue | Synthetic builders, forbidden-field scans, review gate |
## 12. Parallelization after foundation