'use client';
import { useState } from 'react';
import dynamic from 'next/dynamic';
import { ExternalLink, ZoomIn } from 'lucide-react';
import { useQuery } from '@tanstack/react-query';
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { apiFetch } from '@/lib/api/client';
// yet-another-react-lightbox is ~50kb, lazy-load it.
const Lightbox = dynamic(() => import('yet-another-react-lightbox'), { ssr: false });
import 'yet-another-react-lightbox/styles.css';
// pdfjs-dist is ~150kb gzip — lazy-load so routes that never preview
// PDFs don't ship it. ssr:false because the worker setup needs window.
const PdfViewer = dynamic(() => import('./pdf-viewer').then((m) => ({ default: m.PdfViewer })), {
ssr: false,
loading: () => (
Loading PDF viewer…
),
});
interface FilePreviewDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
fileId?: string;
fileName?: string;
mimeType?: string;
}
export function FilePreviewDialog({
open,
onOpenChange,
fileId,
fileName,
mimeType,
}: FilePreviewDialogProps) {
const [lightboxOpen, setLightboxOpen] = useState(false);
// useQuery replaces the prior useEffect(fetch+setState) pattern. The
// request is gated on the dialog being open and a fileId being set.
const previewQuery = useQuery<{ data: { url: string } }>({
queryKey: ['file-preview', fileId],
queryFn: () => apiFetch(`/api/v1/files/${fileId}/preview`),
enabled: open && !!fileId,
});
const previewUrl = previewQuery.data?.data.url ?? null;
const loading = previewQuery.isLoading;
const error = previewQuery.error ? 'Failed to load preview' : null;
const isImage = mimeType?.startsWith('image/');
const isPdf = mimeType === 'application/pdf';
return (
);
}