'use client'; import { useState, useEffect, useCallback } from 'react'; import Image from 'next/image'; import { Button } from '@/components/ui/Button'; import { Modal } from '@/components/ui/Modal'; import { listFiles, deleteFile, isImageMime, formatFileSize, getThumbnailUrl, type FileResponse, } from '@/lib/files'; interface FileListProps { vehicleId: string; onFileDeleted?: () => void; } export function FileList({ vehicleId, onFileDeleted }: FileListProps) { const [files, setFiles] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [pageSize] = useState(20); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [deleteTarget, setDeleteTarget] = useState(null); const [deleting, setDeleting] = useState(false); const fetchFiles = useCallback(async () => { setLoading(true); setError(null); try { const data = await listFiles(vehicleId, page, pageSize); setFiles(data.items); setTotal(data.total); } catch (err: unknown) { const apiErr = err as { error?: { message?: string } }; setError(apiErr?.error?.message || 'Failed to load files'); } finally { setLoading(false); } }, [vehicleId, page, pageSize]); useEffect(() => { fetchFiles(); }, [fetchFiles]); const handleDelete = async () => { if (!deleteTarget) return; setDeleting(true); try { await deleteFile(vehicleId, deleteTarget.id); setDeleteTarget(null); await fetchFiles(); onFileDeleted?.(); } catch (err: unknown) { const apiErr = err as { error?: { message?: string } }; setError(apiErr?.error?.message || 'Failed to delete file'); } finally { setDeleting(false); } }; const handleDownload = (file: FileResponse) => { const token = typeof window !== 'undefined' ? localStorage.getItem('access_token') : null; const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api/v1'; const url = `${API_BASE_URL}/vehicles/${vehicleId}/files/${file.id}`; // Use fetch with auth header to download as blob fetch(url, { headers: token ? { Authorization: `Bearer ${token}` } : {}, }) .then((res) => res.blob()) .then((blob) => { const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = file.original_filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(downloadUrl); }) .catch(() => setError('Failed to download file')); }; if (loading && files.length === 0) { return (
Loading files...
); } if (error) { return (
{error}
); } if (files.length === 0) { return (
No files uploaded yet.
); } return (
{files.map((file) => { const thumbUrl = getThumbnailUrl(file); const isImg = isImageMime(file.mime_type); return (
{/* Thumbnail or file icon */}
{isImg && thumbUrl ? ( {file.original_filename} ) : (
{file.mime_type.split('/')[1]}
)}
{/* File info */}

{file.original_filename}

{formatFileSize(file.file_size)}

{/* Actions */}
); })}
{/* Pagination */} {total > pageSize && (
Page {page} of {Math.ceil(total / pageSize)}
)} {/* Delete confirmation modal */} setDeleteTarget(null)} title="Delete File" >

Are you sure you want to delete {deleteTarget?.original_filename}? This action cannot be undone.

); }