Files
dyolink/frontend/src/components/ui/treatment/CaseLatestAttachmentPreview.tsx

73 lines
2.1 KiB
TypeScript
Raw Normal View History

'use client';
import { useEffect, useState } from 'react';
import { FileText } from 'lucide-react';
import { treatmentsApi } from '@/lib/api/treatments';
import type { TreatmentAttachmentMeta } from '@/types/treatment';
interface CaseLatestAttachmentPreviewProps {
attachment: TreatmentAttachmentMeta;
className?: string;
}
export function CaseLatestAttachmentPreview({
attachment,
className = 'aspect-square w-full max-w-[11rem]',
}: CaseLatestAttachmentPreviewProps) {
const [url, setUrl] = useState<string | null>(null);
const [failed, setFailed] = useState(false);
useEffect(() => {
let cancelled = false;
let objectUrl: string | null = null;
void (async () => {
try {
const blob = await treatmentsApi.getAttachmentFileBlob(attachment.id);
if (cancelled) return;
objectUrl = URL.createObjectURL(blob);
setUrl(objectUrl);
setFailed(false);
} catch {
if (!cancelled) setFailed(true);
}
})();
return () => {
cancelled = true;
if (objectUrl) URL.revokeObjectURL(objectUrl);
};
}, [attachment.id]);
const isImage = attachment.mimeType.startsWith('image/');
const isPdf = attachment.mimeType === 'application/pdf';
return (
<div
className={`${className} rounded-[var(--radius-md)] border border-border/60 bg-background-secondary overflow-hidden`}
title={attachment.fileName}
>
{url && isImage ? (
<img
src={url}
alt={attachment.fileName}
className="h-full w-full object-fill"
/>
) : url && isPdf ? (
<iframe
src={url}
title={attachment.fileName}
className="h-full w-full border-0"
/>
) : (
<div className="flex h-full w-full flex-col items-center justify-center gap-1.5 p-2 text-text-muted">
<FileText className="h-8 w-8 shrink-0 icon-flat" aria-hidden />
<span className="line-clamp-2 text-center text-[10px] leading-tight">
{failed ? 'Preview unavailable' : attachment.fileName}
</span>
</div>
)}
</div>
);
}