veza/apps/web/src/components/upload/FilePreviewCard.tsx

106 lines
3 KiB
TypeScript

import React from 'react';
import { Card } from '../ui/card';
import { UploadProgressBar } from './UploadProgressBar';
import {
FileAudio,
FileImage,
FolderArchive,
File,
CheckCircle,
AlertCircle,
} from 'lucide-react';
export interface UploadFile {
id: string;
file: File;
progress: number;
status: 'uploading' | 'paused' | 'completed' | 'error' | 'processing';
previewUrl?: string;
}
interface FilePreviewCardProps {
fileData: UploadFile;
onPause: () => void;
onResume: () => void;
onCancel: () => void;
}
export const FilePreviewCard: React.FC<FilePreviewCardProps> = ({
fileData,
onPause,
onResume,
onCancel,
}) => {
const { file, progress, status, previewUrl } = fileData;
const formatSize = (bytes: number) => {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
};
const getIcon = () => {
if (file.type.startsWith('image/'))
return <FileImage className="w-6 h-6 text-kodo-magenta" />;
if (file.type.startsWith('audio/'))
return <FileAudio className="w-6 h-6 text-kodo-cyan" />;
if (file.type.includes('zip') || file.type.includes('compressed'))
return <FolderArchive className="w-6 h-6 text-kodo-gold" />;
return <File className="w-6 h-6 text-gray-400" />;
};
return (
<Card
variant="gaming"
className="p-3 flex items-center gap-4 border-l-4 border-l-kodo-slate hover:border-l-kodo-cyan transition-all"
>
{/* Thumbnail / Icon */}
<div className="w-12 h-12 rounded-lg bg-black/40 flex items-center justify-center overflow-hidden flex-shrink-0 border border-white/5">
{previewUrl && file.type.startsWith('image/') ? (
<img
src={previewUrl}
alt="Preview"
className="w-full h-full object-cover"
/>
) : (
getIcon()
)}
</div>
{/* Info & Progress */}
<div className="flex-1 min-w-0">
<div className="flex justify-between items-start mb-1">
<h4
className="font-bold text-white text-sm truncate pr-2"
title={file.name}
>
{file.name}
</h4>
<span className="text-[10px] text-gray-500 font-mono flex-shrink-0">
{formatSize(file.size)}
</span>
</div>
{status === 'completed' ? (
<div className="flex items-center gap-2 text-xs text-kodo-lime font-bold">
<CheckCircle className="w-3 h-3" /> Ready
</div>
) : status === 'error' ? (
<div className="flex items-center gap-2 text-xs text-kodo-red font-bold">
<AlertCircle className="w-3 h-3" /> Failed
</div>
) : (
<UploadProgressBar
progress={progress}
status={status}
onPause={onPause}
onResume={onResume}
onCancel={onCancel}
/>
)}
</div>
</Card>
);
};