57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
import React from 'react';
|
|
|
|
export type UploadQueueItem = {
|
|
id: string;
|
|
fileName: string;
|
|
progress: number;
|
|
status: 'queued' | 'uploading' | 'saving' | 'success' | 'error';
|
|
error?: string;
|
|
};
|
|
|
|
type UploadProgressListProps = {
|
|
items: UploadQueueItem[];
|
|
};
|
|
|
|
const UploadProgressList: React.FC<UploadProgressListProps> = ({ items }) => {
|
|
const pendingItems = items.filter((item) => item.status !== 'success');
|
|
|
|
if (pendingItems.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<ul className='space-y-1 mb-3 max-h-40 overflow-auto'>
|
|
{pendingItems.map((item) => (
|
|
<li
|
|
key={item.id}
|
|
className='text-xs border border-gray-200 dark:border-dark-700 rounded p-2'
|
|
>
|
|
<div className='flex items-center justify-between gap-2'>
|
|
<span className='truncate'>{item.fileName}</span>
|
|
<span>
|
|
{item.status === 'error'
|
|
? 'Error'
|
|
: item.status === 'success'
|
|
? 'Done'
|
|
: item.status}
|
|
</span>
|
|
</div>
|
|
{item.status !== 'success' && (
|
|
<div className='w-full h-1 bg-gray-200 rounded mt-1'>
|
|
<div
|
|
className='h-1 bg-blue-500 rounded'
|
|
style={{ width: `${item.progress}%` }}
|
|
/>
|
|
</div>
|
|
)}
|
|
{item.error && (
|
|
<p className='text-red-500 mt-1 truncate'>{item.error}</p>
|
|
)}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
);
|
|
};
|
|
|
|
export default UploadProgressList;
|