diff --git a/packages/admin/src/components/repairs/ticket-notes.tsx b/packages/admin/src/components/repairs/ticket-notes.tsx index c3314c0..3358e1f 100644 --- a/packages/admin/src/components/repairs/ticket-notes.tsx +++ b/packages/admin/src/components/repairs/ticket-notes.tsx @@ -9,6 +9,7 @@ import { Textarea } from '@/components/ui/textarea' import { Badge } from '@/components/ui/badge' import { Send, Trash2, Eye, Lock, ImageIcon, X } from 'lucide-react' import { toast } from 'sonner' +import { useEffect } from 'react' import type { RepairNote } from '@/types/repair' const STATUS_LABELS: Record = { @@ -48,6 +49,31 @@ async function openSignedFile(fileId: string) { } } +/** Image component that fetches via authenticated request and displays as blob */ +function AuthImage({ path, alt, className, onClick }: { path: string; alt: string; className?: string; onClick?: () => void }) { + const token = useAuthStore((s) => s.token) + const [src, setSrc] = useState(null) + + useEffect(() => { + let cancelled = false + async function load() { + try { + const res = await fetch(`/v1/files/serve/${path}`, { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }) + if (!res.ok || cancelled) return + const blob = await res.blob() + if (!cancelled) setSrc(URL.createObjectURL(blob)) + } catch { /* ignore */ } + } + load() + return () => { cancelled = true } + }, [path, token]) + + if (!src) return
+ return {alt} +} + interface TicketNotesProps { ticketId: string } @@ -263,8 +289,8 @@ function NoteEntry({ note, formatDate, canDelete, onDelete }: {
{photos.map((photo) => (