Fix: Waveform Editor lädt nicht für Titel ohne vollständige Song-Daten

- Filtere Songs ohne vollständige Song-Daten (song, filename) in CurateSpecialEditor
- Füge defensive Prüfungen hinzu bevor WaveformEditor gerendert wird
- Filtere unvollständige Songs bereits auf API-Ebene in curator/specials/[id]
- Verhindert Fehler wenn Songs ohne filename oder song-Objekt geladen werden
This commit is contained in:
Hördle Bot
2025-12-07 10:07:43 +01:00
parent a4e61de53f
commit fb833a7976
2 changed files with 24 additions and 8 deletions

View File

@@ -52,7 +52,14 @@ export async function GET(
return NextResponse.json({ error: 'Special not found' }, { status: 404 });
}
return NextResponse.json(special);
// Filtere Songs ohne vollständige Song-Daten (song, song.filename)
// Dies verhindert Fehler im Frontend, wenn Songs gelöscht wurden oder Daten fehlen
const filteredSongs = special.songs.filter(ss => ss.song && ss.song.filename);
return NextResponse.json({
...special,
songs: filteredSongs,
});
}

View File

@@ -62,11 +62,14 @@ export default function CurateSpecialEditor({
saveChangesLabel = '💾 Save Changes',
savedLabel = '✓ Saved',
}: CurateSpecialEditorProps) {
// Filtere Songs ohne vollständige Song-Daten (song, song.filename)
const validSongs = special.songs.filter(ss => ss.song && ss.song.filename);
const [selectedSongId, setSelectedSongId] = useState<number | null>(
special.songs.length > 0 ? special.songs[0].songId : null
validSongs.length > 0 ? validSongs[0].songId : null
);
const [pendingStartTime, setPendingStartTime] = useState<number | null>(
special.songs.length > 0 ? special.songs[0].startTime : null
validSongs.length > 0 ? validSongs[0].startTime : null
);
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const [saving, setSaving] = useState(false);
@@ -77,7 +80,7 @@ export default function CurateSpecialEditor({
const unlockSteps = JSON.parse(special.unlockSteps);
const totalDuration = unlockSteps[unlockSteps.length - 1];
const selectedSpecialSong = special.songs.find(ss => ss.songId === selectedSongId) ?? null;
const selectedSpecialSong = validSongs.find(ss => ss.songId === selectedSongId) ?? null;
const handleStartTimeChange = (newStartTime: number) => {
setPendingStartTime(newStartTime);
@@ -111,7 +114,7 @@ export default function CurateSpecialEditor({
</p>
</div>
{special.songs.length === 0 ? (
{validSongs.length === 0 ? (
<div style={{ padding: '2rem', background: '#f3f4f6', borderRadius: '0.5rem', textAlign: 'center' }}>
<p>{noSongsHint}</p>
<p style={{ fontSize: '0.875rem', color: '#666', marginTop: '0.5rem' }}>
@@ -125,7 +128,7 @@ export default function CurateSpecialEditor({
Select Song to Curate
</h2>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))', gap: '1rem' }}>
{special.songs.map(ss => (
{validSongs.map(ss => (
<div
key={ss.songId}
onClick={() => {
@@ -152,7 +155,7 @@ export default function CurateSpecialEditor({
</div>
</div>
{selectedSpecialSong && (
{selectedSpecialSong && selectedSpecialSong.song && selectedSpecialSong.song.filename ? (
<div>
<h2 style={{ fontSize: '1.25rem', fontWeight: 'bold', marginBottom: '1rem' }}>
Curate: {selectedSpecialSong.song.title}
@@ -189,7 +192,13 @@ export default function CurateSpecialEditor({
/>
</div>
</div>
)}
) : selectedSpecialSong ? (
<div style={{ padding: '2rem', background: '#fee2e2', borderRadius: '0.5rem', textAlign: 'center' }}>
<p style={{ color: '#991b1b', fontWeight: 'bold' }}>
Fehler: Song-Daten unvollständig. Bitte wählen Sie einen anderen Song.
</p>
</div>
) : null}
</div>
)}
</div>