feat: add TTS statistics to DashboardPage and StatisticsGrid components

This commit is contained in:
JSC
2025-09-27 21:38:07 +02:00
parent 79d9bd7f76
commit d17dc5558c
2 changed files with 79 additions and 6 deletions

View File

@@ -2,7 +2,7 @@ import { StatisticCard } from '@/components/dashboard/StatisticCard'
import { NumberFlowDuration } from '@/components/ui/number-flow-duration' import { NumberFlowDuration } from '@/components/ui/number-flow-duration'
import { NumberFlowSize } from '@/components/ui/number-flow-size' import { NumberFlowSize } from '@/components/ui/number-flow-size'
import NumberFlow from '@number-flow/react' import NumberFlow from '@number-flow/react'
import { Clock, HardDrive, Music, Play, Volume2 } from 'lucide-react' import { Clock, HardDrive, Music, Play, Volume2, MessageSquare } from 'lucide-react'
interface SoundboardStatistics { interface SoundboardStatistics {
sound_count: number sound_count: number
@@ -18,12 +18,20 @@ interface TrackStatistics {
total_size: number total_size: number
} }
interface TTSStatistics {
sound_count: number
total_play_count: number
total_duration: number
total_size: number
}
interface StatisticsGridProps { interface StatisticsGridProps {
soundboardStatistics: SoundboardStatistics soundboardStatistics: SoundboardStatistics
trackStatistics: TrackStatistics trackStatistics: TrackStatistics
ttsStatistics: TTSStatistics
} }
export function StatisticsGrid({ soundboardStatistics, trackStatistics }: StatisticsGridProps) { export function StatisticsGrid({ soundboardStatistics, trackStatistics, ttsStatistics }: StatisticsGridProps) {
return ( return (
<div className="space-y-6"> <div className="space-y-6">
<div> <div>
@@ -109,6 +117,48 @@ export function StatisticsGrid({ soundboardStatistics, trackStatistics }: Statis
/> />
</div> </div>
</div> </div>
<div>
<h2 className="text-lg font-semibold mb-3 text-muted-foreground">
TTS Statistics
</h2>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<StatisticCard
title="Total TTS"
icon={MessageSquare}
value={<NumberFlow value={ttsStatistics.sound_count} />}
description="Text-to-speech audio files"
/>
<StatisticCard
title="Total Plays"
icon={Play}
value={<NumberFlow value={ttsStatistics.total_play_count} />}
description="All-time play count"
/>
<StatisticCard
title="Total Duration"
icon={Clock}
value={
<NumberFlowDuration
duration={ttsStatistics.total_duration}
variant="wordy"
/>
}
description="Combined TTS duration"
/>
<StatisticCard
title="Total Size"
icon={HardDrive}
value={
<NumberFlowSize
size={ttsStatistics.total_size}
binary={true}
/>
}
description="Original + normalized files"
/>
</div>
</div>
</div> </div>
) )
} }

View File

@@ -19,6 +19,13 @@ interface TrackStatistics {
total_size: number total_size: number
} }
interface TTSStatistics {
sound_count: number
total_play_count: number
total_duration: number
total_size: number
}
interface TopSound { interface TopSound {
id: number id: number
name: string name: string
@@ -33,6 +40,8 @@ export function DashboardPage() {
useState<SoundboardStatistics | null>(null) useState<SoundboardStatistics | null>(null)
const [trackStatistics, setTrackStatistics] = const [trackStatistics, setTrackStatistics] =
useState<TrackStatistics | null>(null) useState<TrackStatistics | null>(null)
const [ttsStatistics, setTtsStatistics] =
useState<TTSStatistics | null>(null)
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
@@ -74,6 +83,19 @@ export function DashboardPage() {
const trackData = await trackResponse.json() const trackData = await trackResponse.json()
setTrackStatistics(trackData) setTrackStatistics(trackData)
// Fetch TTS statistics separately to avoid Promise.all failures
const ttsResponse = await fetch('/api/v1/dashboard/tts-statistics', {
credentials: 'include'
})
if (!ttsResponse.ok) {
const errorText = await ttsResponse.text()
throw new Error(`Failed to fetch TTS statistics: ${errorText}`)
}
const ttsData = await ttsResponse.json()
setTtsStatistics(ttsData)
} catch (err) { } catch (err) {
console.error('Dashboard statistics error:', err) console.error('Dashboard statistics error:', err)
setError(err instanceof Error ? err.message : 'An error occurred') setError(err instanceof Error ? err.message : 'An error occurred')
@@ -174,13 +196,13 @@ export function DashboardPage() {
useEffect(() => { useEffect(() => {
const interval = setInterval(() => { const interval = setInterval(() => {
// Only auto-refresh if not currently loading or in error state // Only auto-refresh if not currently loading or in error state
if (!loading && !refreshing && (!error || (soundboardStatistics && trackStatistics))) { if (!loading && !refreshing && (!error || (soundboardStatistics && trackStatistics && ttsStatistics))) {
refreshAll() refreshAll()
} }
}, 30000) // Increased to 30 seconds }, 30000) // Increased to 30 seconds
return () => clearInterval(interval) return () => clearInterval(interval)
}, [refreshAll, loading, refreshing, error, soundboardStatistics, trackStatistics]) }, [refreshAll, loading, refreshing, error, soundboardStatistics, trackStatistics, ttsStatistics])
useEffect(() => { useEffect(() => {
fetchTopSounds(true) // Show loading on initial load and filter changes fetchTopSounds(true) // Show loading on initial load and filter changes
@@ -190,7 +212,7 @@ export function DashboardPage() {
return <LoadingSkeleton /> return <LoadingSkeleton />
} }
if (error && (!soundboardStatistics || !trackStatistics)) { if (error && (!soundboardStatistics || !trackStatistics || !ttsStatistics)) {
return <ErrorState error={error} onRetry={retryFromError} /> return <ErrorState error={error} onRetry={retryFromError} />
} }
@@ -204,10 +226,11 @@ export function DashboardPage() {
<DashboardHeader onRefresh={refreshAll} isRefreshing={refreshing} /> <DashboardHeader onRefresh={refreshAll} isRefreshing={refreshing} />
<div className="space-y-6"> <div className="space-y-6">
{soundboardStatistics && trackStatistics && ( {soundboardStatistics && trackStatistics && ttsStatistics && (
<StatisticsGrid <StatisticsGrid
soundboardStatistics={soundboardStatistics} soundboardStatistics={soundboardStatistics}
trackStatistics={trackStatistics} trackStatistics={trackStatistics}
ttsStatistics={ttsStatistics}
/> />
)} )}