import { useState, useEffect } from 'react' import { Settings, Save, Disc, Cpu, Database, Globe, AlertCircle, CheckCircle } from 'lucide-react' import { api } from '../lib/api' import { useDarkMode } from '../context/ThemeContext' interface SettingsState { tmdbApiKey: string tvdbApiKey: string outputDir: string movieDir: string seriesDir: string musicDir: string ripAllTracks: boolean mainFeatureOnly: boolean autoEject: boolean notificationWebhook: string } const defaultSettings: SettingsState = { tmdbApiKey: '', tvdbApiKey: '', outputDir: '/app/media', movieDir: 'movies', seriesDir: 'series', musicDir: 'music', ripAllTracks: true, mainFeatureOnly: false, autoEject: true, notificationWebhook: '', } export default function SettingsPage() { const [settings, setSettings] = useState(defaultSettings) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [saved, setSaved] = useState(false) const { theme } = useDarkMode() useEffect(() => { const loadSettings = async () => { try { const response = await api.get('/settings') // Leeres Objekt von der API = noch nichts gespeichert → Defaults behalten setSettings({ ...defaultSettings, ...response.data }) } catch { setSettings(defaultSettings) } finally { setLoading(false) } } loadSettings() }, []) const handleChange = (field: keyof SettingsState, value: any) => { setSettings(prev => ({ ...prev, [field]: value })) setSaved(false) } const handleSave = async () => { setSaving(true) try { await api.post('/settings', settings) setSaved(true) setTimeout(() => setSaved(false), 3000) } finally { setSaving(false) } } if (loading) { return (
) } return (

Einstellungen

Konfiguriere Rippy nach deinen Wünschen

{saved && (
Einstellungen erfolgreich gespeichert!
)}
{/* Tabs */}
{/* Content */}
{/* Ripping Settings */}

Ripping-Einstellungen

Alle Tracks rippen

Rippe alle Tracks einer CD (nicht nur Main Feature)

handleChange('ripAllTracks', v)} darkMode={theme === 'dark'} />

Nur Hauptfeature

Rippe bei DVDs/Blu-rays nur das Hauptfeature

handleChange('mainFeatureOnly', v)} darkMode={theme === 'dark'} />

Automatischer Auswurf

Disk nach erfolgreichem Ripping auswerfen

handleChange('autoEject', v)} darkMode={theme === 'dark'} />
{/* Output Directories */}

Ausgabeverzeichnisse

handleChange('outputDir', e.target.value)} className={`w-full px-3 py-2 ${theme === 'dark' ? 'bg-slate-800 border-slate-600 text-slate-200 focus:ring-indigo-500' : 'bg-white border-slate-300 text-slate-900 focus:ring-indigo-600'} border rounded-lg focus:ring-2 focus:border-transparent transition-all`} placeholder="/app/media" />

Basisverzeichnis für alle Ausgaben

handleChange('movieDir', e.target.value)} className={`w-full px-3 py-2 ${theme === 'dark' ? 'bg-slate-800 border-slate-600 text-slate-200' : 'bg-white border-slate-300 text-slate-900'} border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all`} placeholder="movies" />
handleChange('seriesDir', e.target.value)} className={`w-full px-3 py-2 ${theme === 'dark' ? 'bg-slate-800 border-slate-600 text-slate-200' : 'bg-white border-slate-300 text-slate-900'} border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all`} placeholder="series" />
handleChange('musicDir', e.target.value)} className={`w-full px-3 py-2 ${theme === 'dark' ? 'bg-slate-800 border-slate-600 text-slate-200' : 'bg-white border-slate-300 text-slate-900'} border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all`} placeholder="music" />
{/* API Keys */}

API-Schlüssel

handleChange('tmdbApiKey', e.target.value)} className={`w-full px-3 py-2 ${theme === 'dark' ? 'bg-slate-800 border-slate-600 text-slate-200' : 'bg-white border-slate-300 text-slate-900'} border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all`} placeholder="Dein TMDB API Key" />

Hol dir einen Key auf themoviedb.org

handleChange('tvdbApiKey', e.target.value)} className={`w-full px-3 py-2 ${theme === 'dark' ? 'bg-slate-800 border-slate-600 text-slate-200' : 'bg-white border-slate-300 text-slate-900'} border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all`} placeholder="Dein TVDb API Key" />
{/* Webhook */}

Webhook-Benachrichtigungen

handleChange('notificationWebhook', e.target.value)} className={`w-full px-3 py-2 ${theme === 'dark' ? 'bg-slate-800 border-slate-600 text-slate-200' : 'bg-white border-slate-300 text-slate-900'} border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all`} placeholder="https://discord.com/api/webhooks/..." />

Optional: URL für Benachrichtigungen bei Job-Ende (Discord, Slack, etc.)

{/* Save Button */}
) } function TabButton({ icon: Icon, label, isActive, darkMode }: { icon: any, label: string, isActive: boolean, darkMode: boolean }) { const { theme } = useDarkMode() return ( ) } function Toggle({ checked, onChange, darkMode }: { checked: boolean, onChange: (v: boolean) => void, darkMode: boolean }) { const { theme } = useDarkMode() return ( ) }