diff --git a/src/components/reports/export-dashboard-pdf-button.tsx b/src/components/reports/export-dashboard-pdf-button.tsx index 6d1c87ef..fa913733 100644 --- a/src/components/reports/export-dashboard-pdf-button.tsx +++ b/src/components/reports/export-dashboard-pdf-button.tsx @@ -1,7 +1,7 @@ 'use client'; -import { useState } from 'react'; -import { FileDown, Loader2 } from 'lucide-react'; +import { useMemo, useState } from 'react'; +import { Eye, FileDown, Loader2 } from 'lucide-react'; import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; @@ -24,6 +24,7 @@ import { triggerBlobDownload } from '@/lib/utils/download'; import { usePermissions } from '@/hooks/use-permissions'; import { resolvePortIdFromSlug } from '@/lib/api/client'; import { SavedTemplatesPicker, type SavedTemplate } from './saved-templates-picker'; +import { PdfPreviewModal } from './pdf-preview-modal'; /** * Dashboard "Export as PDF" affordance. Per-export dialog lets reps @@ -44,6 +45,18 @@ export function ExportDashboardPdfButton() { PDF_DASHBOARD_WIDGETS.map((w) => w.id), ); const [loading, setLoading] = useState(false); + const [previewOpen, setPreviewOpen] = useState(false); + + // Build the payload the modal will POST. useMemo keeps the + // reference stable while the dialog's form is unchanged, so the + // preview effect doesn't re-fire on unrelated re-renders. + const previewPayload = useMemo( + () => ({ + title: title.trim() || 'Dashboard report', + config: { kind: 'dashboard' as const, widgetIds: selected }, + }), + [title, selected], + ); if (!can('reports', 'export')) return null; @@ -159,6 +172,14 @@ export function ExportDashboardPdfButton() { + +