2026-07-17 01:38:48 +02:00
|
|
|
'use client';
|
|
|
|
|
|
2026-07-17 21:16:38 +02:00
|
|
|
import Image from 'next/image';
|
2026-07-17 01:38:48 +02:00
|
|
|
import { Modal } from '@/components/ui/Modal';
|
|
|
|
|
import { isImageMime, formatFileSize, type FileResponse } from '@/lib/files';
|
|
|
|
|
|
|
|
|
|
interface FilePreviewProps {
|
|
|
|
|
file: FileResponse | null;
|
|
|
|
|
open: boolean;
|
|
|
|
|
onClose: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function FilePreview({ file, open, onClose }: FilePreviewProps) {
|
|
|
|
|
if (!file) return null;
|
|
|
|
|
|
|
|
|
|
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api/v1';
|
|
|
|
|
const downloadUrl = `${API_BASE_URL}/vehicles/${file.vehicle_id}/files/${file.id}`;
|
|
|
|
|
const isImg = isImageMime(file.mime_type);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Modal open={open} onClose={onClose} title={file.original_filename}>
|
|
|
|
|
<div data-testid="file-preview" className="space-y-4">
|
|
|
|
|
{/* Preview content */}
|
|
|
|
|
{isImg ? (
|
|
|
|
|
<div className="flex justify-center">
|
2026-07-17 21:16:38 +02:00
|
|
|
<Image
|
2026-07-17 01:38:48 +02:00
|
|
|
src={downloadUrl}
|
|
|
|
|
alt={file.original_filename}
|
2026-07-17 21:16:38 +02:00
|
|
|
width={800}
|
|
|
|
|
height={600}
|
2026-07-17 01:38:48 +02:00
|
|
|
className="max-w-full max-h-[60vh] rounded-lg"
|
|
|
|
|
data-testid="preview-image"
|
2026-07-17 21:16:38 +02:00
|
|
|
unoptimized
|
2026-07-17 01:38:48 +02:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<div className="flex flex-col items-center gap-4 py-8">
|
|
|
|
|
<svg className="h-16 w-16 text-text-muted" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
|
|
|
|
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
|
|
|
</svg>
|
|
|
|
|
<p className="text-text-muted">Preview not available for this file type</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* File metadata */}
|
|
|
|
|
<div className="space-y-2 text-sm">
|
|
|
|
|
<div className="flex justify-between">
|
|
|
|
|
<span className="text-text-muted">File type:</span>
|
|
|
|
|
<span className="text-text">{file.mime_type}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex justify-between">
|
|
|
|
|
<span className="text-text-muted">Size:</span>
|
|
|
|
|
<span className="text-text">{formatFileSize(file.file_size)}</span>
|
|
|
|
|
</div>
|
|
|
|
|
{file.created_at && (
|
|
|
|
|
<div className="flex justify-between">
|
|
|
|
|
<span className="text-text-muted">Uploaded:</span>
|
|
|
|
|
<span className="text-text">
|
|
|
|
|
{new Date(file.created_at).toLocaleDateString()}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Download button */}
|
|
|
|
|
<div className="flex justify-end">
|
|
|
|
|
<a
|
|
|
|
|
href={downloadUrl}
|
|
|
|
|
download={file.original_filename}
|
|
|
|
|
className="inline-flex items-center px-4 py-2 rounded-lg bg-primary text-white hover:bg-primary-hover transition-colors"
|
|
|
|
|
data-testid="preview-download-btn"
|
|
|
|
|
>
|
|
|
|
|
Download
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Modal>
|
|
|
|
|
);
|
|
|
|
|
}
|