From 553928a3a905e9066ddbca10f48b057a076f59a7 Mon Sep 17 00:00:00 2001 From: fahed Date: Tue, 28 Apr 2026 14:41:44 +0300 Subject: [PATCH] feat(report): form component with all config fields --- src/components/Report/ReportForm.tsx | 170 +++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 src/components/Report/ReportForm.tsx diff --git a/src/components/Report/ReportForm.tsx b/src/components/Report/ReportForm.tsx new file mode 100644 index 0000000..a8af9fb --- /dev/null +++ b/src/components/Report/ReportForm.tsx @@ -0,0 +1,170 @@ +import React, { useRef } from 'react'; +import AltMultiSelect from '../shared/AltMultiSelect'; +import type { ReportConfig } from './reportHelpers'; + +interface Props { + config: ReportConfig; + onChange: (patch: Partial) => void; + allMuseums: string[]; + allChannels: string[]; +} + +function SectionTitle({ children }: { children: React.ReactNode }) { + return
{children}
; +} + +function Field({ label, children }: { label: string; children: React.ReactNode }) { + return ( + + ); +} + +function Toggle({ left, right, value, onChange }: { + left: string; right: string; value: boolean; onChange: (v: boolean) => void; +}) { + return ( +
+ + +
+ ); +} + +function CheckRow({ label, checked, onChange }: { label: string; checked: boolean; onChange: (v: boolean) => void }) { + return ( + + ); +} + +export default function ReportForm({ config: cfg, onChange, allMuseums, allChannels }: Props) { + const logoInputRef = useRef(null); + + const handleLogoUpload = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + if (file.size > 2 * 1024 * 1024) { alert('Logo must be under 2 MB'); return; } + const reader = new FileReader(); + reader.onload = () => onChange({ clientLogoBase64: reader.result as string }); + reader.readAsDataURL(file); + }; + + return ( +
+ + Client Info + + + onChange({ title: e.target.value })} + placeholder="Q1 2025 Visitor Performance" /> + + + + onChange({ clientName: e.target.value })} + placeholder="Acme Group" /> + + + + onChange({ contactName: e.target.value })} + placeholder="Mohammed Al-..." /> + + + +
+ + {cfg.clientLogoBase64 && ( + <> + preview + + + )} + +
+
+ + +
+ onChange({ accentColor: e.target.value })} + className="rf-color-input" /> + {cfg.accentColor} +
+
+ + Data Selection + +
+ + onChange({ startDate: e.target.value })} /> + + + onChange({ endDate: e.target.value })} /> + +
+ + + onChange({ selectedMuseums: v })} + allLabel="All museums" countLabel={n => `${n} museums`} clearLabel="Clear" /> + + + + onChange({ selectedChannels: v })} + allLabel="All channels" countLabel={n => `${n} channels`} clearLabel="Clear" /> + + + + onChange({ includeVAT: v })} /> + + + onChange({ includeComparison: v })} /> + + Content Sections + + onChange({ showExecutiveSummary: v })} /> + onChange({ showMetricsTable: v })} /> + onChange({ showTrendChart: v })} /> + onChange({ showMuseumBreakdown: v })} /> + onChange({ showChannelBreakdown: v })} /> + onChange({ showPilgrimCapture: v })} /> + + Presentation + + + onChange({ language: v ? 'ar' : 'en' })} /> + + + + onChange({ orientation: v ? 'landscape' : 'portrait' })} /> + + + + + + +
+ ); +}