Etappe 3: Metadaten-Lookup + Pre-Scan

- SQLite-Cache für API-Rate-Limits (LRU, 10k Einträge)
- TMDB/MusicBrainz/TheTVDB Clients
- Pre-Scan-Modul für TOC-Lesung ohne Ripping
- Metadaten-Preview UI
- Jellyfin-Formatierung (NFO + Images)
- API Endpoints für Lookup, Confirm, Format
This commit is contained in:
Hitonabi
2026-07-21 17:17:35 +02:00
parent 0cf5413ac0
commit 518155051f
15 changed files with 1530 additions and 3 deletions
+43 -1
View File
@@ -1,10 +1,52 @@
import { useState } from 'react'
import Dashboard from './pages/Dashboard'
import MetadataPreview from './pages/MetadataPreview'
function App() {
const [page, setPage] = useState<'dashboard' | 'metadata'>('dashboard')
const navItems = [
{ id: 'dashboard', label: 'Dashboard' },
{ id: 'metadata', label: 'Metadaten-Preview' },
]
return (
<div className="min-h-screen bg-gray-100">
<Dashboard />
{/* Navigation */}
<nav className="bg-white shadow-md">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
<div className="flex items-center">
<div className="flex-shrink-0 flex items-center gap-2">
<svg className="h-8 w-8 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
<span className="font-bold text-xl text-gray-900">Rippy</span>
</div>
</div>
<div className="flex items-center gap-4">
{navItems.map((item) => (
<button
key={item.id}
onClick={() => setPage(item.id as 'dashboard' | 'metadata')}
className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${
page === item.id
? 'bg-blue-100 text-blue-700'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
{item.label}
</button>
))}
</div>
</div>
</div>
</nav>
{/* Content */}
<main className="max-w-7xl mx-auto py-6">
{page === 'dashboard' ? <Dashboard /> : <MetadataPreview />}
</main>
</div>
)
}