diff --git a/packages/admin/src/components/repairs/ticket-notes.tsx b/packages/admin/src/components/repairs/ticket-notes.tsx index 3358e1f..b53f25b 100644 --- a/packages/admin/src/components/repairs/ticket-notes.tsx +++ b/packages/admin/src/components/repairs/ticket-notes.tsx @@ -116,11 +116,16 @@ export function TicketNotes({ ticketId }: TicketNotesProps) { formData.append('entityType', 'repair_note') formData.append('entityId', note.id) formData.append('category', 'attachment') - await fetch('/v1/files', { + const uploadRes = await fetch('/v1/files', { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: formData, }) + if (!uploadRes.ok) { + const err = await uploadRes.json().catch(() => ({})) + console.error('Photo upload failed:', err) + toast.error(`Photo upload failed: ${(err as any).error?.message ?? 'Unknown error'}`) + } } queryClient.invalidateQueries({ queryKey: repairNoteKeys.all(ticketId) }) diff --git a/packages/admin/src/components/repairs/ticket-photos.tsx b/packages/admin/src/components/repairs/ticket-photos.tsx index 91f78f4..53c5081 100644 --- a/packages/admin/src/components/repairs/ticket-photos.tsx +++ b/packages/admin/src/components/repairs/ticket-photos.tsx @@ -1,4 +1,4 @@ -import { useRef } from 'react' +import { useRef, useState, useEffect } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { queryOptions } from '@tanstack/react-query' import { api } from '@/lib/api-client' @@ -7,6 +7,30 @@ import { Button } from '@/components/ui/button' import { FileText, ImageIcon, Plus, Trash2 } from 'lucide-react' import { toast } from 'sonner' +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} +} + async function openSignedFile(fileId: string) { try { const res = await api.get<{ url: string }>(`/v1/files/signed-url/${fileId}`) @@ -164,8 +188,8 @@ function PhotoSection({ ) : (