Fix note photos not displaying by using authenticated image fetching
Note photo thumbnails were failing because img src pointed at an authenticated endpoint without auth headers. Added AuthImage component that fetches images via Bearer token and renders as blob URLs. Photos now display inline in note entries. Clicking still opens via signed URL.
This commit is contained in:
@@ -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<string, string> = {
|
||||
@@ -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<string | null>(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 <div className={`${className} bg-muted animate-pulse`} />
|
||||
return <img src={src} alt={alt} className={className} onClick={onClick} />
|
||||
}
|
||||
|
||||
interface TicketNotesProps {
|
||||
ticketId: string
|
||||
}
|
||||
@@ -263,8 +289,8 @@ function NoteEntry({ note, formatDate, canDelete, onDelete }: {
|
||||
<div className="flex flex-wrap gap-2 mt-2">
|
||||
{photos.map((photo) => (
|
||||
<button key={photo.id} type="button" onClick={() => openSignedFile(photo.id)}>
|
||||
<img
|
||||
src={`/v1/files/serve/${photo.path}`}
|
||||
<AuthImage
|
||||
path={photo.path}
|
||||
alt={photo.filename}
|
||||
className="h-24 w-24 object-cover rounded-md border cursor-pointer hover:opacity-80 transition-opacity"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user