refactor: update TTSHeader component for improved sorting and search functionality

This commit is contained in:
JSC
2025-09-21 13:21:02 +02:00
parent 6f477a1aa7
commit 620418c405

View File

@@ -1,6 +1,5 @@
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
Select,
SelectContent,
@@ -8,15 +7,16 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { Plus, RefreshCw, Search } from 'lucide-react'
import type { TTSSortField, TTSSortOrder } from '@/lib/api/services/tts'
import { Plus, RefreshCw, Search, SortAsc, SortDesc, X } from 'lucide-react'
interface TTSHeaderProps {
searchQuery: string
onSearchChange: (query: string) => void
sortBy: string
onSortByChange: (sortBy: string) => void
sortOrder: 'asc' | 'desc'
onSortOrderChange: (order: 'asc' | 'desc') => void
sortBy: TTSSortField
onSortByChange: (sortBy: TTSSortField) => void
sortOrder: TTSSortOrder
onSortOrderChange: (order: TTSSortOrder) => void
onRefresh: () => void
onCreateClick: () => void
loading: boolean
@@ -38,90 +38,94 @@ export function TTSHeader({
ttsCount,
}: TTSHeaderProps) {
return (
<div className="space-y-4">
<>
{/* Header */}
<div className="flex items-center justify-between">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-3xl font-bold tracking-tight">Text to Speech</h1>
<h1 className="text-2xl font-bold">Text to Speech</h1>
<p className="text-muted-foreground">
Generate speech from text using various TTS providers
</p>
</div>
<Button onClick={onCreateClick}>
<Plus className="mr-2 h-4 w-4" />
Generate TTS
</Button>
<div className="flex items-center gap-4">
{!loading && !error && (
<div className="text-sm text-muted-foreground">
{ttsCount} generation{ttsCount !== 1 ? 's' : ''}
</div>
)}
<Button onClick={onCreateClick}>
<Plus className="h-4 w-4 mr-2" />
Generate TTS
</Button>
</div>
</div>
{/* Controls */}
<div className="flex flex-col gap-4 sm:flex-row sm:items-end">
{/* Search and Sort Controls */}
<div className="flex flex-col sm:flex-row gap-4 mb-6">
<div className="flex-1">
<Label htmlFor="search">Search</Label>
<div className="relative">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
id="search"
placeholder="Search by text or provider..."
value={searchQuery}
onChange={(e) => onSearchChange(e.target.value)}
className="pl-9"
onChange={e => onSearchChange(e.target.value)}
className="pl-9 pr-9"
/>
{searchQuery && (
<Button
variant="ghost"
size="sm"
onClick={() => onSearchChange('')}
className="absolute right-1 top-1/2 transform -translate-y-1/2 h-7 w-7 p-0 hover:bg-muted"
title="Clear search"
>
<X className="h-3 w-3" />
</Button>
)}
</div>
</div>
<div className="flex gap-2">
<div>
<Label htmlFor="sortBy">Sort by</Label>
<Select value={sortBy} onValueChange={onSortByChange}>
<SelectTrigger id="sortBy" className="w-40">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="created_at">Created</SelectItem>
<SelectItem value="text">Text</SelectItem>
<SelectItem value="provider">Provider</SelectItem>
</SelectContent>
</Select>
</div>
<Select
value={sortBy}
onValueChange={value => onSortByChange(value as TTSSortField)}
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Sort by" />
</SelectTrigger>
<SelectContent>
<SelectItem value="created_at">Created Date</SelectItem>
<SelectItem value="text">Text</SelectItem>
<SelectItem value="provider">Provider</SelectItem>
</SelectContent>
</Select>
<div>
<Label htmlFor="sortOrder">Order</Label>
<Select
value={sortOrder}
onValueChange={(value: 'asc' | 'desc') => onSortOrderChange(value)}
>
<SelectTrigger id="sortOrder" className="w-32">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="desc">Newest</SelectItem>
<SelectItem value="asc">Oldest</SelectItem>
</SelectContent>
</Select>
</div>
<Button
variant="outline"
size="icon"
onClick={() => onSortOrderChange(sortOrder === 'asc' ? 'desc' : 'asc')}
title={sortOrder === 'asc' ? 'Sort ascending' : 'Sort descending'}
>
{sortOrder === 'asc' ? (
<SortAsc className="h-4 w-4" />
) : (
<SortDesc className="h-4 w-4" />
)}
</Button>
<div className="flex items-end">
<Button
variant="outline"
size="icon"
onClick={onRefresh}
disabled={loading}
>
<RefreshCw className={`h-4 w-4 ${loading ? 'animate-spin' : ''}`} />
</Button>
</div>
<Button
variant="outline"
size="icon"
onClick={onRefresh}
disabled={loading}
title="Refresh TTS history"
>
<RefreshCw
className={`h-4 w-4 ${loading ? 'animate-spin' : ''}`}
/>
</Button>
</div>
</div>
{/* Stats */}
<div className="flex items-center gap-4 text-sm text-muted-foreground">
<span>
{ttsCount} generation{ttsCount !== 1 ? 's' : ''}
</span>
{error && (
<span className="text-destructive">Error: {error}</span>
)}
</div>
</div>
</>
)
}