ge-tool/components/QueueStatus.tsx
2025-12-10 13:41:43 +07:00

97 lines
3.7 KiB
TypeScript
Executable File

import React, { memo } from 'react';
export type GeIdItem = {
key: string;
id: string;
lang: string;
status: 'waiting' | 'processing' | 'done' | 'error';
usernames?: string;
};
interface QueueStatusProps {
currentSubmission: { username: string; geIdAndLang: string } | null;
queueItems: GeIdItem[];
pendingSubmissionsCount?: number;
onOpenQueueModal: () => void;
}
const getStatusStyles = (status: GeIdItem['status']) => {
switch (status) {
case 'processing':
return 'bg-amber-500/20 text-amber-300 border-amber-500/30';
case 'done':
return 'bg-green-500/20 text-green-300 border-green-500/30';
case 'error':
return 'bg-rose-500/20 text-rose-300 border-rose-500/30';
case 'waiting':
default:
return 'bg-slate-700/50 text-slate-400 border-slate-600';
}
};
const QueueStatus: React.FC<QueueStatusProps> = ({ currentSubmission, queueItems, pendingSubmissionsCount = 0, onOpenQueueModal }) => {
// derive usernames from queueItems when available; fallback to currentSubmission
const derivedUsernames = (() => {
if (queueItems && queueItems.length > 0) {
const all = queueItems.flatMap(i => (i.usernames || '').split('\n').map(s => s.trim()).filter(Boolean));
return Array.from(new Set(all));
}
if (currentSubmission) return currentSubmission.username.split('\n').map(s => s.trim()).filter(Boolean);
return [];
})();
const userCount = derivedUsernames.length;
const geIdCount = queueItems.length;
// Show details only when there are queue items available (currently processing submission)
const showDetails = geIdCount > 0;
return (
<div className="mt-8 bg-slate-800/50 backdrop-blur-sm p-6 rounded-2xl shadow-lg border border-slate-700 min-h-[10rem]">
<div className="flex justify-between items-center mb-4 border-b border-slate-700 pb-3">
<h2 className="text-xl font-semibold text-white">Hàng đi Trạng thái</h2>
<span className="text-sm font-semibold tabular-nums rounded-md px-2 py-1 text-slate-400">
Submit đang chờ: {pendingSubmissionsCount}
</span>
</div>
{showDetails ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 font-mono text-sm animate-fade-in">
<div>
<h3 className="text-slate-400 mb-2 font-sans font-semibold">Username ({userCount})</h3>
<pre className="bg-slate-900/50 p-3 rounded-lg whitespace-pre-wrap break-all h-48 overflow-y-auto">{derivedUsernames.join('\n')}</pre>
</div>
<div>
<h3 className="text-slate-400 mb-2 font-sans font-semibold">GE ID & Lang ({geIdCount})</h3>
<div className="bg-slate-900/50 p-3 rounded-lg h-48 overflow-y-auto flex flex-wrap gap-2 content-start">
{queueItems.map(item => (
<button
key={item.key}
className={`px-2 py-1 text-xs rounded-md border transition-all duration-300 ${getStatusStyles(item.status)}`}
disabled
>
{item.id} {item.lang.toUpperCase()}
</button>
))}
</div>
</div>
</div>
) : (
<div className="flex justify-center items-center h-full min-h-[12rem]">
<p className="text-slate-500">Không submit nào đang đưc xử .</p>
</div>
)}
<style>{`
@keyframes fade-in {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fade-in {
animation: fade-in 0.5s ease-out forwards;
}
`}</style>
</div>
);
};
export default memo(QueueStatus);