import { useEffect, useState } from 'react' import { Loader2, AlertTriangle } from 'lucide-react' import { Dialog } from '@/components/ui/Dialog' import { Button } from '@/components/ui/Button' import { api } from '@/lib/api' /** Extensions hỗ trợ preview inline (PDF native + images native). Word/Excel * KHÔNG support — user phải download mở local Office. */ const PREVIEWABLE_EXT = ['pdf', 'png', 'jpg', 'jpeg', 'webp', 'gif'] export function isPreviewable(fileName: string): boolean { const ext = fileName.toLowerCase().split('.').pop() ?? '' return PREVIEWABLE_EXT.includes(ext) } type Props = { open: boolean evaluationId: string attachmentId: string fileName: string onClose: () => void } /** Preview file inline qua BE endpoint `/view` (Content-Disposition: inline). * Fetch as blob → object URL → iframe (PDF) hoặc img (image). * Bearer auth qua axios api client (KHÔNG thể set iframe src trực tiếp vì * iframe không inherit Authorization header). */ export function AttachmentPreviewDialog({ open, evaluationId, attachmentId, fileName, onClose, }: Props) { const [blobUrl, setBlobUrl] = useState(null) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const ext = fileName.toLowerCase().split('.').pop() ?? '' const isImage = ['png', 'jpg', 'jpeg', 'webp', 'gif'].includes(ext) useEffect(() => { if (!open) return let cancelled = false let currentUrl: string | null = null setLoading(true) setError(null) api.get(`/purchase-evaluations/${evaluationId}/attachments/${attachmentId}/view`, { responseType: 'blob', }) .then(res => { if (cancelled) return currentUrl = window.URL.createObjectURL(res.data as Blob) setBlobUrl(currentUrl) setLoading(false) }) .catch(err => { if (cancelled) return setError(err?.message ?? 'Lỗi tải file') setLoading(false) }) return () => { cancelled = true if (currentUrl) window.URL.revokeObjectURL(currentUrl) setBlobUrl(null) } }, [open, evaluationId, attachmentId]) return ( Đóng} >
{loading && (
Đang tải file…
)} {error && !loading && (
Không tải được file
{error}
)} {blobUrl && !loading && !error && ( isImage ? {fileName} :