diff --git a/.planning/phases/18-payment-gateway/18-UI-SPEC.md b/.planning/phases/18-payment-gateway/18-UI-SPEC.md new file mode 100644 index 0000000..0dd0b83 --- /dev/null +++ b/.planning/phases/18-payment-gateway/18-UI-SPEC.md @@ -0,0 +1,1003 @@ +--- +phase: "18" +slug: "payment-gateway" +status: draft +shadcn_initialized: false +preset: none +created: "2026-10-12" +--- + +# Phase 18 — UI Design Contract + +> Visual and interaction contract for frontend phases. Generated by msd-ui-researcher, verified by msd-ui-checker. + +This phase has three visual surfaces: + +1. **Admin SPA (`admin/`, framework, plan 1).** Generic cabana work that the payment screens need, built before any plugin screen: + - **F1.** The `money` form field and `money` list column (D-07). + - **F2.** A write-only secret on settings forms: `type: password` backed by `lagoon.Encrypted`, with a stored/env/empty status line (D-13, RESEARCH F-5). + - **F3.** `richeditor` allowed on settings forms (RESEARCH F-5). It has no new visuals and reuses the Phase 17 RichEditorField unchanged. + - **F4.** Tabs on settings forms, the FormView tab strip reused. + - **F5.** A `Danger` flag on record actions, which turns their confirm dialog into the danger variant. + - **F6.** The preview screen's Edit button only renders when the form has an editable field. + - **F7.** Two new partial style kit classes, `.summer-table` and `.summer-stat__note`. +2. **Plugin admin screens** in `sm-paymentgateway-plugin` and `sm-pgstripe-plugin`. They are YAML (`columns.yaml`, `fields.yaml`, `config_*.yaml`, settings fields) plus server partial templates (`AdminPartialData` view models), record actions, and **one** plugin custom element: the quote cart editor. They render through the existing list, preview, form and settings views. +3. **`vue-paymentgateway-layer` (D-06, D-17).** A new Nuxt layer in the `vue-journal-layer` / `vue-faq-layer` style: neutral, token-driven checkout, order status and order list components over `/_paymentgateway/api/v1`. The site app overrides tokens or same-name components. + +The admin SPA already has a complete design system: Direction C v2 (`.planning/phases/10-admin-vue-spa/design/README.md`), implemented as Tailwind 4 `@theme` tokens in `admin/src/styles/main.css` on Reka UI primitives. **This contract adds no new admin tokens, colours, fonts, radii or shadows.** It adds three plain CSS classes to the partial style kit (F7), and they read only the public `--c-*` variables, as the 12.1 `.summer-callout*` addition did. Every other admin value reuses an existing token or copies a class string from `FormView.vue`, `PreviewView.vue`, `SettingsFormView.vue`, `ListView.vue`, `DataTable.vue`, `CellValue.vue`, `FormField.vue`, `NumberField.vue`, `PasswordField.vue`, `RecordActions.vue`, `Button.vue`, `control.ts`, or the 10.1, 12.1, 12.2, 16.3 and 17 UI-SPECs. + +Sources: +- `18-CONTEXT.md`: D-02, D-05 to D-08, D-13, D-16, D-17 (locked). +- `18-RESEARCH.md`: findings F-5 to F-7; Patterns 8, 11 and 12; Pitfall 11; Open Questions 2 and 3; Assumptions A10 and A11. +- The 10.1, 12.1, 12.2, 16.3 and 17 UI-SPECs (approved house conventions). +- The codebase scan listed above, plus `modules/cabana/settings.go:86` (the settings type refusal), `modules/pact/capabilities.go` (`AdminRecordAction`, `AdminPartialData`, `NavigationItem`) and `admin/src/app/icons.ts`. +- The frozen PHP sources (D-02) under `/media/nvme/dev/golem15/horoskopia.eu/plugins/golem15/`: + - `paymentgateway/`: `controllers/{orders,payments,quotes}/*.htm` and `config_*.yaml`; `models/*/{columns,fields}.yaml`; `models/settings/{fields,mailer_fields}.yaml`; `formwidgets/MoneyWidget.php`; `support/StateFormatter.php`; `components/orders/*.htm`; `lang/{en,pl}/lang.php`. + - `pgstripe/`: `Plugin.php` (the injected Stripe fields), `partials/_stripe_info.htm`, `lang/{en,pl}`. + +**Out of this contract:** +- **Mail templates.** They render through postcard's existing Markdown layout, with no new mail design (D-08). Their copy keeps the PHP template codes and variables. +- **The notification route** `_paymentgateway/...`. It has no UI; the Stripe browser return is a redirect to `return_url`. +- **Subscriptions** (Phase 18.1, D-01). +- **The consuming application's own pages.** The layer components are what an app mounts. + +**Framework additions this contract depends on.** F4 to F7 are small and generic, and none is named in RESEARCH's plan 1 list. The planner places them in plan 1 next to F1 to F3, or raises them with the user at the plan-count checkpoint. Without them: +- the Mailer page's 25 switches render ungrouped (F4); +- refund and reject confirms render as ordinary confirms (F5); +- order and payment previews show an Edit button that opens an empty form (F6); +- the cart partial has no native table style (F7). + +--- + +## Design System + +| Property | Value | +|----------|-------| +| Tool | none. There is no shadcn: this is a Vue 3 SPA with its own Direction C system. The shadcn gate does not apply to a Vue codebase with an established system, the same ruling as Phases 10.1, 12.1, 12.2, 16.3 and 17. The Nuxt layer uses plain scoped CSS on its own tokens, like `vue-journal-layer`. | +| Preset | not applicable | +| Component library | Admin: Reka UI 2.9.10 (headless primitives) plus the local components in `admin/src/components/`. Layer: none. It uses Vue SFCs with native `