diff --git a/docs/superpowers/specs/2026-04-28-report-builder-design.md b/docs/superpowers/specs/2026-04-28-report-builder-design.md new file mode 100644 index 0000000..c53e256 --- /dev/null +++ b/docs/superpowers/specs/2026-04-28-report-builder-design.md @@ -0,0 +1,148 @@ +# Report Builder — Design Spec +**Date:** 2026-04-28 +**Status:** Approved + +--- + +## Overview + +A dedicated `/report` page (admin-only) where users configure a client-facing PDF report from scratch. The report is a professional business document — no app interface visible — downloadable as a `.pdf` file via `@react-pdf/renderer`. + +--- + +## Page Structure + +Two-column layout on desktop, stacked on mobile: +- **Left panel (form):** all configuration fields, grouped into sections +- **Right panel:** a static document preview mockup (not a live render — too expensive). Shows real text fields (title, client name, period) updating in real time, but charts and metrics are represented as grey placeholder shapes. Gives the user a sense of page structure and section order. +- **Footer bar:** "Generate PDF" button (triggers download), estimated page count + +The route is `/report`, protected the same way `/settings` is (admin only, via `userRole === 'admin'` check in `App.tsx`). + +--- + +## Form Sections + +### 1. Client Info +| Field | Type | Notes | +|---|---|---| +| Report title | Text input | e.g. "Q1 2025 Visitor Performance" | +| Prepared for (company) | Text input | Shown in report header | +| Contact name | Text input | Optional — "Attention: …" line | +| Client logo | File upload (PNG/JPG/SVG, max 2MB) | Base64-encoded, embedded in PDF header | +| Accent color | Color picker | Defaults to HiHala blue `#2563eb`; used for section headers, borders | + +### 2. Data Selection +| Field | Type | Notes | +|---|---|---| +| Period start / end | Date inputs | Defaults to current month | +| Museums | Multi-select (same component as dashboard) | Empty = all | +| Channels | Multi-select | Empty = all | +| VAT | Toggle: Excl / Incl | Defaults to Incl | +| Include comparison | Checkbox | Adds previous-year column to metrics table | + +### 3. Content Sections (toggleable) +Each is a checkbox, all on by default: +- Executive summary (3–4 sentences auto-generated from numbers) +- Key metrics table (Revenue, Visitors, Tickets, Avg Rev/Visitor, optionally Pilgrim Capture Rate) +- Revenue & visitor trend chart +- Breakdown by museum +- Breakdown by channel +- Pilgrim capture rate section (only shown if toggle is on AND data exists) + +### 4. Presentation +| Field | Type | Notes | +|---|---|---| +| Language | Toggle: EN / AR | Controls all PDF text and direction | +| Confidentiality footer | Select: Confidential / Internal / Public | Shown in page footer | +| Page orientation | Toggle: Portrait / Landscape | Portrait default | + +--- + +## PDF Document Design + +Built with `@react-pdf/renderer`. All layout is code — no DOM capture, no html2canvas. + +**Page 1 — Cover** +- HiHala logo (top-left) + client logo (top-right) +- Large report title +- "Prepared for: [Company]" / "Attention: [Contact]" +- Period label (e.g. "January – March 2025") +- Generation date +- Accent color bar at bottom + +**Page 2+ — Content pages** +- Shared header: small HiHala wordmark + report title + page number +- Sections in the order the user toggled them on +- Each section starts with a colored heading bar (accent color) +- Confidentiality level in page footer + +**Chart rendering:** +Charts do not use the live Chart.js instances. Instead, `@react-pdf/renderer` draws simplified chart equivalents natively using SVG primitives (``, ``, ``, ``) — no canvas capture needed. This produces crisp vector output at any print resolution. + +Simplified charts to implement: +- **Trend line chart:** SVG polyline over a grid +- **Bar chart (museum/channel breakdown):** horizontal SVG bars with labels + +**Executive summary generation:** +Computed from the metrics — a template string filled with actual numbers. Example (EN): +> "During [period], [selected museums] recorded [X] visitors and [Y SAR] in revenue, representing a [Z%] change versus the same period last year. The top-performing channel was [channel] with [N%] of total tickets." + +The same template exists in Arabic (stored in the locale file alongside EN/AR strings already in the codebase). Falls back gracefully if comparison data is absent (omits the change sentence). + +--- + +## Data Flow + +``` +/report page + → user fills form + → clicks "Generate PDF" + → reads filtered data from already-loaded app state (passed as prop from App.tsx) + OR re-fetches if needed (dataService.fetchData()) + → applies period + museum + channel filters client-side + → computes metrics (reuses existing calculateMetrics()) + → passes computed values to (react-pdf component) + → pdf.download('hihala-report.pdf') +``` + +No new API endpoints required. All computation is client-side using existing `dataService` functions. + +--- + +## File Structure + +``` +src/ + components/ + Report/ + index.tsx — the /report page (form + preview layout) + ReportForm.tsx — the left-panel form + ReportPreview.tsx — the right-panel static mockup + ReportDocument.tsx — the @react-pdf/renderer document + reportCharts.tsx — SVG chart primitives for PDF + reportHelpers.ts — executive summary generator, data filters +``` + +--- + +## Navigation + +- Desktop nav: gear icon already links to `/settings`; add a "Report" link (document icon) next to it, admin-only +- Mobile bottom nav: add Report icon between Comparison and Settings + +--- + +## Dependencies + +- `@react-pdf/renderer` — PDF generation +- No other new dependencies (reuses existing AltMultiSelect, form inputs, data service) + +--- + +## Out of Scope + +- Scheduled / emailed reports +- Saving report configurations +- Non-admin users generating reports +- Live chart preview in the right panel (static mockup only)