|
import React from 'react'; |
|
import { X, CheckCircle, AlertCircle, Loader2, Download } from 'lucide-react'; |
|
import type { ImageFile } from '../types'; |
|
import { formatFileSize } from '../utils/imageProcessing'; |
|
import { downloadImage } from '../utils/download'; |
|
|
|
interface ImageListProps { |
|
images: ImageFile[]; |
|
onRemove: (id: string) => void; |
|
} |
|
|
|
export function ImageList({ images, onRemove }: ImageListProps) { |
|
if (images.length === 0) return null; |
|
|
|
return ( |
|
<div className="space-y-4"> |
|
{images.map((image) => ( |
|
<div |
|
key={image.id} |
|
className="bg-white rounded-lg shadow-sm p-4 flex items-center gap-4" |
|
> |
|
{image.preview && ( |
|
<img |
|
src={image.preview} |
|
alt={image.file.name} |
|
className="w-16 h-16 object-cover rounded" |
|
/> |
|
)} |
|
<div className="flex-1 min-w-0"> |
|
<div className="flex items-center justify-between"> |
|
<p className="text-sm font-medium text-gray-900 truncate"> |
|
{image.file.name} |
|
</p> |
|
<div className="flex items-center gap-2"> |
|
{image.status === 'complete' && ( |
|
<button |
|
onClick={() => downloadImage(image)} |
|
className="text-gray-400 hover:text-gray-600" |
|
title="Download" |
|
> |
|
<Download className="w-5 h-5" /> |
|
</button> |
|
)} |
|
<button |
|
onClick={() => onRemove(image.id)} |
|
className="text-gray-400 hover:text-gray-600" |
|
title="Remove" |
|
> |
|
<X className="w-5 h-5" /> |
|
</button> |
|
</div> |
|
</div> |
|
<div className="mt-1 flex items-center gap-2 text-sm text-gray-500"> |
|
{image.status === 'pending' && ( |
|
<span>Ready to process</span> |
|
)} |
|
{image.status === 'processing' && ( |
|
<span className="flex items-center gap-2"> |
|
<Loader2 className="w-4 h-4 animate-spin" /> |
|
Processing... |
|
</span> |
|
)} |
|
{image.status === 'complete' && ( |
|
<span className="flex items-center gap-2 text-green-600"> |
|
<CheckCircle className="w-4 h-4" /> |
|
Complete |
|
</span> |
|
)} |
|
{image.status === 'error' && ( |
|
<span className="flex items-center gap-2 text-red-600"> |
|
<AlertCircle className="w-4 h-4" /> |
|
{image.error || 'Error processing image'} |
|
</span> |
|
)} |
|
</div> |
|
<div className="mt-1 text-sm text-gray-500"> |
|
{formatFileSize(image.originalSize)} |
|
{image.compressedSize && ( |
|
<> |
|
{' → '} |
|
{formatFileSize(image.compressedSize)}{' '} |
|
<span className="text-green-600"> |
|
( |
|
{Math.round( |
|
((image.originalSize - image.compressedSize) / |
|
image.originalSize) * |
|
100 |
|
)} |
|
% smaller) |
|
</span> |
|
</> |
|
)} |
|
</div> |
|
</div> |
|
</div> |
|
))} |
|
</div> |
|
); |
|
} |