Files
hihala-dashboard/docs/superpowers/specs/2026-04-28-report-builder-design.md
T
fahed 64955f0f51 docs: report builder design spec
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 14:20:07 +03:00

149 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 (34 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 (`<Svg>`, `<Rect>`, `<Path>`, `<Line>`) — 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 <ReportDocument /> (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)