feat: add NumberFlowDuration component for enhanced duration display in DashboardPage
This commit is contained in:
87
src/components/ui/number-flow-duration.tsx
Normal file
87
src/components/ui/number-flow-duration.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import NumberFlow from '@number-flow/react'
|
||||
import { formatDuration } from '@/utils/format-duration'
|
||||
|
||||
interface NumberFlowDurationProps {
|
||||
duration: number
|
||||
variant?: 'clock' | 'wordy'
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function NumberFlowDuration({
|
||||
duration,
|
||||
variant = 'clock',
|
||||
className
|
||||
}: NumberFlowDurationProps) {
|
||||
const formatted = formatDuration(duration)
|
||||
|
||||
// Split the formatted duration to get individual parts
|
||||
const parts = formatted.split(':')
|
||||
|
||||
if (variant === 'clock') {
|
||||
// For clock variant
|
||||
if (parts.length === 2) {
|
||||
// Format: MM:SS
|
||||
const [minutes, seconds] = parts
|
||||
return (
|
||||
<span className={className}>
|
||||
<NumberFlow
|
||||
value={parseInt(minutes)}
|
||||
digits={{ 1: { max: 5 } }}
|
||||
format={{ minimumIntegerDigits: 2 }}
|
||||
/>
|
||||
<NumberFlow
|
||||
value={parseInt(seconds)}
|
||||
prefix=":"
|
||||
digits={{ 1: { max: 5 } }}
|
||||
format={{ minimumIntegerDigits: 2 }}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
} else {
|
||||
// Format: HH:MM:SS
|
||||
const [hours, minutes, seconds] = parts
|
||||
return (
|
||||
<span className={className}>
|
||||
<NumberFlow
|
||||
value={parseInt(hours)}
|
||||
format={{ minimumIntegerDigits: 2 }}
|
||||
/>
|
||||
<NumberFlow
|
||||
value={parseInt(minutes)}
|
||||
prefix=":"
|
||||
digits={{ 1: { max: 5 } }}
|
||||
format={{ minimumIntegerDigits: 2 }}
|
||||
/>
|
||||
<NumberFlow
|
||||
value={parseInt(seconds)}
|
||||
prefix=":"
|
||||
digits={{ 1: { max: 5 } }}
|
||||
format={{ minimumIntegerDigits: 2 }}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// For wordy variant
|
||||
if (parts.length === 2) {
|
||||
// Format: MM:SS
|
||||
const [minutes, seconds] = parts
|
||||
return (
|
||||
<span className={className}>
|
||||
<NumberFlow value={parseInt(minutes)} />m{' '}
|
||||
<NumberFlow value={parseInt(seconds)} />s
|
||||
</span>
|
||||
)
|
||||
} else {
|
||||
// Format: HH:MM:SS
|
||||
const [hours, minutes, seconds] = parts
|
||||
return (
|
||||
<span className={className}>
|
||||
<NumberFlow value={parseInt(hours)} />h{' '}
|
||||
<NumberFlow value={parseInt(minutes)} />m{' '}
|
||||
<NumberFlow value={parseInt(seconds)} />s
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { Volume2, Play, Clock, HardDrive, Music, Trophy, Loader2, RefreshCw } fr
|
||||
import { formatDuration } from '@/lib/format'
|
||||
import NumberFlow from '@number-flow/react'
|
||||
import { formatSizeObject } from '@/utils/format-size'
|
||||
import { NumberFlowDuration } from '@/components/ui/number-flow-duration'
|
||||
|
||||
interface SoundboardStatistics {
|
||||
sound_count: number
|
||||
@@ -298,7 +299,9 @@ export function DashboardPage() {
|
||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{formatDuration(soundboardStatistics.total_duration)}</div>
|
||||
<div className="text-2xl font-bold">
|
||||
<NumberFlowDuration duration={soundboardStatistics.total_duration} variant='wordy' />
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Combined audio duration
|
||||
</p>
|
||||
@@ -365,7 +368,9 @@ export function DashboardPage() {
|
||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{formatDuration(trackStatistics.total_duration)}</div>
|
||||
<div className="text-2xl font-bold">
|
||||
<NumberFlowDuration duration={trackStatistics.total_duration} variant='wordy' />
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Combined track duration
|
||||
</p>
|
||||
@@ -478,7 +483,7 @@ export function DashboardPage() {
|
||||
{sound.duration && (
|
||||
<span className="flex items-center gap-1">
|
||||
<Clock className="h-3 w-3" />
|
||||
{formatDuration(sound.duration)}
|
||||
<NumberFlowDuration duration={sound.duration} variant='wordy' />
|
||||
</span>
|
||||
)}
|
||||
<span className="px-1.5 py-0.5 bg-secondary rounded text-xs">
|
||||
|
||||
Reference in New Issue
Block a user