import { AppLayout } from '@/components/AppLayout' import { Button } from '@/components/ui/button' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Checkbox } from '@/components/ui/checkbox' import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { type NormalizationResponse, type ScanResponse, adminService, } from '@/lib/api/services/admin' import { AudioWaveform, FolderSync, Loader2, Scan, Settings as SettingsIcon, Volume2, } from 'lucide-react' import { useState } from 'react' import { toast } from 'sonner' export function SettingsPage() { // Sound scanning state const [scanningInProgress, setScanningInProgress] = useState(false) const [lastScanResults, setLastScanResults] = useState( null, ) // Sound normalization state const [normalizationInProgress, setNormalizationInProgress] = useState(false) const [normalizationOptions, setNormalizationOptions] = useState({ force: false, onePass: false, soundType: 'all' as 'all' | 'SDB' | 'TTS' | 'EXT', }) const [lastNormalizationResults, setLastNormalizationResults] = useState(null) const handleScanSounds = async () => { setScanningInProgress(true) try { const response = await adminService.scanSounds() setLastScanResults(response) toast.success( `Sound scan completed! Added: ${response.results.added}, Updated: ${response.results.updated}, Deleted: ${response.results.deleted}${response.results.duplicates > 0 ? `, Duplicates: ${response.results.duplicates}` : ''}`, ) } catch (error) { toast.error('Failed to scan sounds') console.error('Sound scan error:', error) } finally { setScanningInProgress(false) } } const handleNormalizeSounds = async () => { setNormalizationInProgress(true) try { let response: NormalizationResponse if (normalizationOptions.soundType === 'all') { response = await adminService.normalizeAllSounds( normalizationOptions.force, normalizationOptions.onePass, ) } else { response = await adminService.normalizeSoundsByType( normalizationOptions.soundType, normalizationOptions.force, normalizationOptions.onePass, ) } setLastNormalizationResults(response) toast.success( `Sound normalization completed! Processed: ${response.results.processed}, Normalized: ${response.results.normalized}`, ) } catch (error) { toast.error('Failed to normalize sounds') console.error('Sound normalization error:', error) } finally { setNormalizationInProgress(false) } } return (

System Settings

Manage system-wide settings and operations

{/* Sound Scanning */} Sound Scanning

Scan the sound directories to synchronize new, updated, and deleted audio files with the database.

{lastScanResults && (
Last Scan Results:
✅ Added: {lastScanResults.results.added}
🔄 Updated: {lastScanResults.results.updated}
🗑️ Deleted: {lastScanResults.results.deleted}
⏭️ Skipped: {lastScanResults.results.skipped}
{lastScanResults.results.duplicates > 0 && (
📄 Duplicates: {lastScanResults.results.duplicates}
)} {lastScanResults.results.errors.length > 0 && (
❌ Errors: {lastScanResults.results.errors.length}
)}
)}
{/* Sound Normalization */} Sound Normalization

Normalize audio levels across all sounds using FFmpeg's loudnorm filter for consistent volume.

setNormalizationOptions(prev => ({ ...prev, force: !!checked, })) } />
setNormalizationOptions(prev => ({ ...prev, onePass: !!checked, })) } />
{lastNormalizationResults && (
Last Normalization Results:
🔄 Processed: {lastNormalizationResults.results.processed}
✅ Normalized:{' '} {lastNormalizationResults.results.normalized}
⏭️ Skipped: {lastNormalizationResults.results.skipped}
❌ Errors: {lastNormalizationResults.results.errors}
{lastNormalizationResults.results.error_details.length > 0 && (
View Error Details
{lastNormalizationResults.results.error_details.map( (error, index) => (
• {error}
), )}
)}
)}
) }