Export Page Refactor & Daily Dust Levels Parity
Date: 2026-02-13 Scope: Refactor both PDF export pages to share common code; bring Daily Dust Levels export to full feature parity with Raw Dust Levels Data export.
Problem
The two export pages (dust-levels/export.tsx ~975 lines, dust-ranger-data/export.tsx ~1508 lines) share ~80% identical logic:
- Chart selection state, description management, AI generation orchestration
- UI sections: header badges, report name editor, AI controls panel, summary textarea
- Callback patterns: toggle, update, generate single/all, export
Daily Dust Levels is also missing features that Raw Dust Levels has:
- PDF Layout (Portrait/Landscape) selector
- GPT-5.2 AI model option
- localStorage auto-save + "Load All Saved" descriptions
- Per-chart "Load Saved" + "Copy Raw Data" buttons
- Landscape PDF generation in the export service
Solution
New Shared Feature: src/features/exports/
src/features/exports/
├── types.ts # BaseExportConfig, ChartOption, TimezoneOption, PdfOrientation, AI response types
├── utils.ts # formatRange, formatDate
├── hooks/
│ └── useExportPage.ts # Shared state + callbacks
└── components/
├── ExportPageHeader.tsx # Top bar with badges + back button
├── ReportNameEditor.tsx # Name input + reset + back/export buttons
├── AIControlsPanel.tsx # Model, style, timezone, orientation, generate all, load all saved
└── ExportSummarySection.tsx # Summary textareauseExportPage Hook
Accepts feature-specific options:
storageKey— localStorage key for description persistencechartOptions— feature-specific chart listhasData— whether valid data existsedgeFunctionName— AI edge function namebuildAIRequestBody(chartKey)— builds feature-specific AI request bodyonExport(config)— executes feature-specific PDF export
Returns all shared state + actions (selectedCharts, chartDescriptions, selectedModel, selectedStyle, selectedTimezone, selectedOrientation, generatingAll, generatingCharts, savedDescriptions, etc.)
AIControlsPanel Component
Renders model, style, orientation, timezone selectors + Generate All + Load All Saved buttons.
modelOptionsprop allows customizing available models per featureextraControlsslot for feature-specific controls (Ranger Type, Data Type)
Export Service Changes
DustLevelExportService gains landscape support:
- Accept
orientationfromExportConfig - Dynamic
pageWidth/pageHeight(210×297 vs 297×210) - Dynamic margins (25mm portrait, 20mm landscape)
- Cover page reflows for landscape (1×4 summary cards instead of 2×2)
- Content pages scale charts to fit wider/shorter area
Files Changed
New Files (7)
src/features/exports/types.tssrc/features/exports/utils.tssrc/features/exports/hooks/useExportPage.tssrc/features/exports/components/ExportPageHeader.tsxsrc/features/exports/components/ReportNameEditor.tsxsrc/features/exports/components/AIControlsPanel.tsxsrc/features/exports/components/ExportSummarySection.tsx
Modified Files (4)
src/features/dust-levels/components/ExportModal.tsx— AddPdfOrientation+orientationtoExportConfigsrc/features/dust-levels/services/exportService.ts— Add landscape supportsrc/app/(admin)/(pages)/dust-levels/export.tsx— Refactor to shared hook + componentssrc/app/(admin)/(pages)/dust-ranger-data/export.tsx— Refactor to shared hook + components
What Daily Dust Levels Gains
- PDF Layout (Portrait/Landscape) selector
- GPT-5.2 AI model option
- localStorage auto-save + Load All Saved button
- Per-chart Load Saved + Copy Raw Data buttons
- Landscape PDF generation
What Doesn't Change
- Chart types and rendering per feature
- Export service visual design (cover page, branding)
- Feature-specific controls (Ranger Type, Data Type stay in dust-ranger only)
ChartWithDescriptioncomponent (already shared)