feat: implement TTS event handling for creation, completion, and failure in TTSPage and SocketContext

This commit is contained in:
JSC
2025-09-21 14:39:15 +02:00
parent 75b52caf85
commit 92846c6d3a
6 changed files with 107 additions and 29 deletions

View File

@@ -22,6 +22,7 @@ import { Badge } from '@/components/ui/badge'
import { Label } from '@/components/ui/label'
import { Loader2, Mic } from 'lucide-react'
import { ttsService, type TTSProvider } from '@/lib/api/services/tts'
import { TTS_EVENTS, ttsEvents } from '@/lib/events'
import { toast } from 'sonner'
interface FormData {
@@ -88,8 +89,8 @@ export function CreateTTSDialog({ open, onOpenChange }: CreateTTSDialogProps) {
onOpenChange(false)
handleReset()
// Trigger refresh of parent list if needed
window.dispatchEvent(new CustomEvent('tts-generated'))
// Emit event for new TTS created
ttsEvents.emit(TTS_EVENTS.TTS_CREATED, response.tts)
} catch (error: any) {
toast.error(error.response?.data?.detail || 'Failed to generate TTS')
} finally {

View File

@@ -1,4 +1,4 @@
import { Calendar, CheckCircle, Loader, Mic, Trash2, Volume2 } from 'lucide-react'
import { AlertCircle, Calendar, CheckCircle, Clock, Loader, Mic, Trash2, Volume2, XCircle } from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
@@ -57,22 +57,36 @@ export function TTSTable({ ttsHistory, onTTSDeleted }: TTSTableProps) {
}
const getStatusBadge = (tts: TTSResponse) => {
const isCompleted = tts.sound_id !== null
if (isCompleted) {
return (
<Badge variant="secondary" className="gap-1">
<CheckCircle className="h-3 w-3" />
Complete
</Badge>
)
} else {
return (
<Badge variant="outline" className="gap-1">
<Loader className="h-3 w-3 animate-spin" />
Processing
</Badge>
)
switch (tts.status) {
case 'completed':
return (
<Badge variant="secondary" className="gap-1">
<CheckCircle className="h-3 w-3" />
Completed
</Badge>
)
case 'processing':
return (
<Badge variant="outline" className="gap-1">
<Loader className="h-3 w-3 animate-spin" />
Processing
</Badge>
)
case 'failed':
return (
<Badge variant="destructive" className="gap-1">
<XCircle className="h-3 w-3" />
Failed
</Badge>
)
case 'pending':
default:
return (
<Badge variant="outline" className="gap-1">
<Clock className="h-3 w-3" />
Pending
</Badge>
)
}
}
@@ -83,8 +97,8 @@ export function TTSTable({ ttsHistory, onTTSDeleted }: TTSTableProps) {
<TableRow>
<TableHead>Text</TableHead>
<TableHead>Provider</TableHead>
<TableHead>Status</TableHead>
<TableHead>Options</TableHead>
<TableHead>Status</TableHead>
<TableHead>Created</TableHead>
<TableHead className="w-[120px]">Actions</TableHead>
</TableRow>
@@ -103,9 +117,6 @@ export function TTSTable({ ttsHistory, onTTSDeleted }: TTSTableProps) {
{tts.provider.toUpperCase()}
</Badge>
</TableCell>
<TableCell>
{getStatusBadge(tts)}
</TableCell>
<TableCell>
{Object.keys(tts.options).length > 0 ? (
<div className="flex gap-1 flex-wrap">
@@ -119,6 +130,19 @@ export function TTSTable({ ttsHistory, onTTSDeleted }: TTSTableProps) {
<span className="text-muted-foreground text-sm">None</span>
)}
</TableCell>
<TableCell>
<div className="space-y-1">
{getStatusBadge(tts)}
{tts.error && (
<div
className="text-xs text-destructive max-w-48 truncate"
title={tts.error}
>
{tts.error}
</div>
)}
</div>
</TableCell>
<TableCell>
<div className="flex items-center gap-1 text-sm text-muted-foreground">
<Calendar className="h-3 w-3" />