File size: 3,479 Bytes
2bc6d22 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
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>
);
} |