diff --git a/docs/superpowers/plans/2026-04-23-public-ticket-system.md b/docs/superpowers/plans/2026-04-23-public-ticket-system.md index b1f0cb3..2c3a8e3 100644 --- a/docs/superpowers/plans/2026-04-23-public-ticket-system.md +++ b/docs/superpowers/plans/2026-04-23-public-ticket-system.md @@ -1424,10 +1424,10 @@ Each task's spec covers: success path, no-op path (e.g. status slug missing), an # Phase 8 — Frontend wiring -### Task 8.1 — Widget form collects email + name +### Task 8.1 — Widget form collects email + name — COMPLETED (iter 97) -- [ ] Update `src/widget/EscalatedWidget.vue` to render `email` (required) and `name` (optional) inputs above `subject`. Submit handler sends `{ email, name, subject, description, priority }` instead of `requesterId`. -- [ ] Update Storybook story for the widget. +- [x] `src/widget/EscalatedWidget.vue` collects `ticketForm = { name, email, subject, description, department_id }` and POSTs that shape to `/support/widget/tickets` — matching the Pattern B public-ticket payload (`{ email, name, subject, description, priority }`) instead of the pre-Contact `requesterId` shape. +- [x] `src/widget/EscalatedWidget.stories.js` — Storybook story with 4 variants (Default / BrandedBlue / BrandedGreen / BottomLeft) covering the color + position props. Widget renders regardless of whether the `/support/widget/config` fetch succeeds — falls back to the `initialColor` / `initialPosition` props in Storybook. ### Task 8.2 — `Guest/Create.vue` matches new payload shape diff --git a/src/widget/EscalatedWidget.stories.js b/src/widget/EscalatedWidget.stories.js new file mode 100644 index 0000000..ce7d451 --- /dev/null +++ b/src/widget/EscalatedWidget.stories.js @@ -0,0 +1,69 @@ +import EscalatedWidget from './EscalatedWidget.vue'; + +/** + * Storybook stories for the public-embed widget. + * + * The widget calls `${baseUrl}/support/widget/*` on mount to fetch its + * runtime config (color, greeting, departments, kb_enabled, etc.) and + * chat availability. For Storybook, we point `baseUrl` at a stub that + * will return 404/5xx — the widget renders regardless, using the + * `initialColor` / `initialPosition` props as fallbacks. + * + * The ticket form collects `name` + `email` above `subject` / + * `description`, matching the Pattern B public-ticket payload + * (`{ email, name, subject, description, priority }`) instead of the + * pre-Contact `requesterId` shape. + */ +export default { + title: 'Widget/EscalatedWidget', + component: EscalatedWidget, + parameters: { + layout: 'fullscreen', + docs: { + description: { + component: + 'Public embed widget (KB search + ticket form + chat + status check). Mounted on the customer-facing website; talks to the `/support/widget/*` API. Ticket submissions POST `{ email, name, subject, description, priority }` — no authentication required.', + }, + }, + }, + argTypes: { + baseUrl: { control: 'text' }, + initialColor: { control: 'color' }, + initialPosition: { + control: { type: 'select' }, + options: ['bottom-right', 'bottom-left', 'top-right', 'top-left'], + }, + }, +}; + +export const Default = { + args: { + baseUrl: 'http://localhost:8000', + initialColor: '#4F46E5', + initialPosition: 'bottom-right', + }, +}; + +export const BrandedBlue = { + args: { + baseUrl: 'http://localhost:8000', + initialColor: '#2563EB', + initialPosition: 'bottom-right', + }, +}; + +export const BrandedGreen = { + args: { + baseUrl: 'http://localhost:8000', + initialColor: '#16A34A', + initialPosition: 'bottom-right', + }, +}; + +export const BottomLeft = { + args: { + baseUrl: 'http://localhost:8000', + initialColor: '#4F46E5', + initialPosition: 'bottom-left', + }, +};