76 lines
3.5 KiB
TypeScript
76 lines
3.5 KiB
TypeScript
import React, { useEffect, useRef } from 'react';
|
|
import { TransferItem } from '../types';
|
|
import { ArrowUp, ArrowDown, CheckCircle, XCircle, Clock } from 'lucide-react';
|
|
|
|
interface TransferQueueProps {
|
|
queue: TransferItem[];
|
|
}
|
|
|
|
const TransferQueue: React.FC<TransferQueueProps> = ({ queue }) => {
|
|
return (
|
|
<div className="flex flex-col h-full bg-white border border-slate-300 rounded-lg overflow-hidden shadow-sm">
|
|
<div className="bg-slate-50 px-3 py-2 border-b border-slate-200 flex justify-between items-center">
|
|
<span className="text-slate-600 text-xs font-semibold uppercase tracking-wider">전송 대기열 (Queue)</span>
|
|
<div className="text-xs text-slate-500">
|
|
{queue.filter(i => i.status === 'transferring').length} 개 진행 중
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex-1 overflow-y-auto bg-white">
|
|
<table className="w-full text-xs text-left border-collapse">
|
|
<thead className="bg-slate-50 text-slate-500 sticky top-0 border-b border-slate-200">
|
|
<tr>
|
|
<th className="p-2 w-8"></th>
|
|
<th className="p-2">파일명</th>
|
|
<th className="p-2 w-24">구분</th>
|
|
<th className="p-2 w-48">진행률</th>
|
|
<th className="p-2 w-24 text-right">속도</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{queue.map((item) => (
|
|
<tr key={item.id} className="border-b border-slate-100 hover:bg-slate-50 text-slate-700">
|
|
<td className="p-2 text-center">
|
|
{item.status === 'completed' && <CheckCircle size={14} className="text-emerald-500" />}
|
|
{item.status === 'failed' && <XCircle size={14} className="text-red-500" />}
|
|
{item.status === 'queued' && <Clock size={14} className="text-slate-400" />}
|
|
{item.status === 'transferring' && (
|
|
<div className="w-3 h-3 rounded-full border-2 border-blue-500 border-t-transparent animate-spin mx-auto"></div>
|
|
)}
|
|
</td>
|
|
<td className="p-2 truncate max-w-[200px] font-medium">{item.filename}</td>
|
|
<td className="p-2">
|
|
<span className={`flex items-center gap-1 ${item.direction === 'upload' ? 'text-blue-600' : 'text-green-600'}`}>
|
|
{item.direction === 'upload' ? <ArrowUp size={12} /> : <ArrowDown size={12} />}
|
|
{item.direction === 'upload' ? '업로드' : '다운로드'}
|
|
</span>
|
|
</td>
|
|
<td className="p-2">
|
|
<div className="w-full bg-slate-100 rounded-full h-2 overflow-hidden border border-slate-200">
|
|
<div
|
|
className={`h-full transition-all duration-200 ${
|
|
item.status === 'completed' ? 'bg-emerald-500' :
|
|
item.status === 'failed' ? 'bg-red-500' : 'bg-blue-500'
|
|
}`}
|
|
style={{ width: `${item.progress}%` }}
|
|
/>
|
|
</div>
|
|
</td>
|
|
<td className="p-2 text-right font-mono text-slate-500">{item.speed}</td>
|
|
</tr>
|
|
))}
|
|
{queue.length === 0 && (
|
|
<tr>
|
|
<td colSpan={5} className="p-8 text-center text-slate-400 italic">
|
|
전송 대기열이 비어있습니다.
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default TransferQueue; |