'use client'; import { isSupportAttachmentImage } from '@edr/types'; import { Download, ExternalLink, FileText } from 'lucide-react'; import { useCallback, useState } from 'react'; import Modal from '@/components/ui/Modal'; /** The minimal file shape the preview needs. */ export interface PreviewableFile { name: string; /** * A blob object URL, not the attachment's API path — the API guard reads the * bearer token from the `Authorization` header, which `` and `` can't * send. Callers fetch the bytes first (see `useAttachmentObjectUrl`). */ url: string; mimeType: string; } /** * Drives a single shared preview modal for the page: call `view(file)` from any * attachment, render `viewer` once near the page root. * * Mirrors the shape of `useFileViewer` from `@edr/ui-common`, which the freight * backoffice uses. That hook can't be used here: it renders `@mantine/core` * components, and this app is Tailwind-only with no `MantineProvider` mounted — * its Modal would throw at runtime. Kept deliberately narrow (images inline, * everything else handed to the browser) rather than reimplementing the shared * viewer's pdf/office/video handling; swap this for the shared hook if this app * ever adopts Mantine. */ export function useFilePreview() { const [file, setFile] = useState(null); const view = useCallback((f: PreviewableFile) => setFile(f), []); const close = useCallback(() => setFile(null), []); const viewer = ( {file && (
{isSupportAttachmentImage(file.mimeType) ? ( // eslint-disable-next-line @next/next/no-img-element {file.name} ) : (

No inline preview for this file type.

)}
Open in new tab Download
)} ); return { view, close, viewer }; }