import { memo, useState } from 'react' import { useTranslation } from 'react-i18next' import type { Job } from '@/types/job' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '@/components/ui/alert-dialog' import { Trash2, AlertCircle, Loader2, Clock, Eye } from 'lucide-react' import { getRelativeTime, cn } from '@/lib/utils' import { JobDetailDialog } from '@/components/JobDetailDialog' interface HistoryItemProps { job: Job onDelete: (id: number) => void } const jobTypeBadgeVariant = { custom_voice: 'default' as const, voice_design: 'secondary' as const, voice_clone: 'outline' as const, } const HistoryItem = memo(({ job, onDelete }: HistoryItemProps) => { const { t } = useTranslation('job') const { t: tCommon } = useTranslation('common') const [detailDialogOpen, setDetailDialogOpen] = useState(false) const jobTypeLabel = { custom_voice: t('typeCustomVoice'), voice_design: t('typeVoiceDesign'), voice_clone: t('typeVoiceClone'), } const getLanguageDisplay = (lang: string | undefined) => { if (!lang || lang === 'Auto') return t('autoDetect') return lang } const handleCardClick = (e: React.MouseEvent) => { if ((e.target as HTMLElement).closest('button')) return setDetailDialogOpen(true) } return (
{jobTypeLabel[job.type]}
{getRelativeTime(job.created_at)}
{job.parameters?.text && (
{t('synthesisText')}: {job.parameters.text}
)}
{t('language')}{getLanguageDisplay(job.parameters?.language)}
{job.type === 'custom_voice' && job.parameters?.speaker && (
{t('speaker')}{job.parameters.speaker}
)} {job.type === 'voice_design' && job.parameters?.instruct && (
{t('voiceDescription')}: {job.parameters.instruct}
)} {job.type === 'voice_clone' && job.parameters?.ref_text && (
{t('referenceText')}: {job.parameters.ref_text}
)}
{job.status === 'processing' && (
{t('statusProcessing')}
)} {job.status === 'pending' && (
{t('statusPending')}
)} {job.status === 'failed' && job.error_message && (
{job.error_message}
)}
{t('deleteJob')} {t('deleteJobConfirm')} {tCommon('cancel')} onDelete(job.id)} className="bg-destructive text-destructive-foreground hover:bg-destructive/90" > {tCommon('delete')}
) }, (prevProps, nextProps) => { return ( prevProps.job.id === nextProps.job.id && prevProps.job.status === nextProps.job.status && prevProps.job.updated_at === nextProps.job.updated_at && prevProps.job.error_message === nextProps.job.error_message ) }) HistoryItem.displayName = 'HistoryItem' export { HistoryItem }