{{ theme.skipToContentLabel || 'Skip to content' }}

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:

  1. PDF Layout (Portrait/Landscape) selector
  2. GPT-5.2 AI model option
  3. localStorage auto-save + "Load All Saved" descriptions
  4. Per-chart "Load Saved" + "Copy Raw Data" buttons
  5. 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 textarea

useExportPage Hook

Accepts feature-specific options:

  • storageKey — localStorage key for description persistence
  • chartOptions — feature-specific chart list
  • hasData — whether valid data exists
  • edgeFunctionName — AI edge function name
  • buildAIRequestBody(chartKey) — builds feature-specific AI request body
  • onExport(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.

  • modelOptions prop allows customizing available models per feature
  • extraControls slot for feature-specific controls (Ranger Type, Data Type)

Export Service Changes

DustLevelExportService gains landscape support:

  • Accept orientation from ExportConfig
  • 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.ts
  • src/features/exports/utils.ts
  • src/features/exports/hooks/useExportPage.ts
  • src/features/exports/components/ExportPageHeader.tsx
  • src/features/exports/components/ReportNameEditor.tsx
  • src/features/exports/components/AIControlsPanel.tsx
  • src/features/exports/components/ExportSummarySection.tsx

Modified Files (4)

  • src/features/dust-levels/components/ExportModal.tsx — Add PdfOrientation + orientation to ExportConfig
  • src/features/dust-levels/services/exportService.ts — Add landscape support
  • src/app/(admin)/(pages)/dust-levels/export.tsx — Refactor to shared hook + components
  • src/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)
  • ChartWithDescription component (already shared)