CASA-MIL / frontend /src /components /FileList.tsx
quoctrong's picture
UI Redesign: clean premium loading radar animation and teal-emerald color theme
354aaac
Raw
History Blame Contribute Delete
3.33 kB
import { FileImage, X, ScanLine, FileStack, Trash2 } from 'lucide-react'
interface Props {
files: File[]
onRemove: (name: string) => void
onClearAll: () => void
onAnalyze: () => void
}
function formatBytes(bytes: number): string {
if (bytes < 1024) return `${bytes} B`
if (bytes < 1024 ** 2) return `${(bytes / 1024).toFixed(1)} KB`
return `${(bytes / 1024 ** 2).toFixed(1)} MB`
}
export default function FileList({ files, onRemove, onClearAll, onAnalyze }: Props) {
const totalSize = files.reduce((sum, f) => sum + f.size, 0)
return (
<div className="animate-fade-up space-y-4">
{/* Header row */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 text-sm text-slate-500">
<FileStack className="h-4 w-4 text-slate-400" />
<span>
<span className="font-semibold text-slate-700">{files.length}</span>{' '}
tệp đã chọn
</span>
<span className="text-slate-300">·</span>
<span>{formatBytes(totalSize)}</span>
</div>
<button
type="button"
onClick={onClearAll}
className="flex items-center gap-1.5 rounded-md border border-slate-200 bg-white px-3 py-1.5
text-xs font-medium text-slate-500 transition-all duration-150
hover:border-red-200 hover:bg-red-50 hover:text-red-500 active:scale-95"
>
<Trash2 className="h-3.5 w-3.5" />
Xóa tất cả
</button>
</div>
{/* File rows */}
<ul className="max-h-52 space-y-1.5 overflow-y-auto pr-1">
{files.map((file, idx) => (
<li
key={file.name}
className="group flex items-center gap-3 rounded-lg border border-slate-100
bg-white px-3 py-2 transition-colors hover:border-slate-200"
>
<div className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-slate-100">
<FileImage className="h-3.5 w-3.5 text-slate-400" />
</div>
<div className="min-w-0 flex-1">
<p className="text-sm font-medium text-slate-700">Slice {idx + 1}</p>
<p className="text-xs text-slate-400">{formatBytes(file.size)}</p>
</div>
<button
type="button"
aria-label={`Xóa ${file.name}`}
onClick={() => onRemove(file.name)}
className="ml-auto flex h-6 w-6 shrink-0 items-center justify-center rounded-md
text-slate-300 opacity-0 transition-all group-hover:opacity-100
hover:bg-red-50 hover:text-red-400"
>
<X className="h-3.5 w-3.5" />
</button>
</li>
))}
</ul>
{/* CTA */}
<button
type="button"
onClick={onAnalyze}
className="flex w-full items-center justify-center gap-2 rounded-lg
bg-teal-600 px-6 py-3
text-sm font-semibold text-white shadow-sm shadow-teal-100
transition-all duration-150 hover:bg-teal-700 active:scale-[0.98]"
>
<ScanLine className="h-4 w-4" />
Bắt đầu phân tích
</button>
</div>
)
}