'use client'; import { useState, useEffect } from 'react'; interface Song { id: number; title: string; artist: string; filename: string; createdAt: string; activations: number; } type SortField = 'title' | 'artist' | 'createdAt'; type SortDirection = 'asc' | 'desc'; export default function AdminPage() { const [password, setPassword] = useState(''); const [isAuthenticated, setIsAuthenticated] = useState(false); const [file, setFile] = useState(null); const [message, setMessage] = useState(''); const [songs, setSongs] = useState([]); // Edit state const [editingId, setEditingId] = useState(null); const [editTitle, setEditTitle] = useState(''); const [editArtist, setEditArtist] = useState(''); // Sort state const [sortField, setSortField] = useState('artist'); const [sortDirection, setSortDirection] = useState('asc'); // Search and pagination state const [searchQuery, setSearchQuery] = useState(''); const [currentPage, setCurrentPage] = useState(1); const itemsPerPage = 10; const handleLogin = async () => { const res = await fetch('/api/admin/login', { method: 'POST', body: JSON.stringify({ password }), }); if (res.ok) { setIsAuthenticated(true); fetchSongs(); } else { alert('Wrong password'); } }; const fetchSongs = async () => { const res = await fetch('/api/songs'); if (res.ok) { const data = await res.json(); setSongs(data); } }; const handleUpload = async (e: React.FormEvent) => { e.preventDefault(); if (!file) return; const formData = new FormData(); formData.append('file', file); setMessage('Uploading...'); const res = await fetch('/api/songs', { method: 'POST', body: formData, }); if (res.ok) { setMessage('Song uploaded successfully!'); setFile(null); fetchSongs(); } else { setMessage('Upload failed.'); } }; const startEditing = (song: Song) => { setEditingId(song.id); setEditTitle(song.title); setEditArtist(song.artist); }; const cancelEditing = () => { setEditingId(null); setEditTitle(''); setEditArtist(''); }; const saveEditing = async (id: number) => { const res = await fetch('/api/songs', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id, title: editTitle, artist: editArtist }), }); if (res.ok) { setEditingId(null); fetchSongs(); } else { alert('Failed to update song'); } }; const handleDelete = async (id: number, title: string) => { if (!confirm(`Are you sure you want to delete "${title}"? This will also delete the file.`)) { return; } const res = await fetch('/api/songs', { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id }), }); if (res.ok) { fetchSongs(); } else { alert('Failed to delete song'); } }; const handleSort = (field: SortField) => { if (sortField === field) { setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); } else { setSortField(field); setSortDirection('asc'); } }; // Filter and sort songs const filteredSongs = songs.filter(song => song.title.toLowerCase().includes(searchQuery.toLowerCase()) || song.artist.toLowerCase().includes(searchQuery.toLowerCase()) ); const sortedSongs = [...filteredSongs].sort((a, b) => { const valA = a[sortField].toLowerCase(); const valB = b[sortField].toLowerCase(); if (valA < valB) return sortDirection === 'asc' ? -1 : 1; if (valA > valB) return sortDirection === 'asc' ? 1 : -1; return 0; }); // Pagination const totalPages = Math.ceil(sortedSongs.length / itemsPerPage); const startIndex = (currentPage - 1) * itemsPerPage; const paginatedSongs = sortedSongs.slice(startIndex, startIndex + itemsPerPage); // Reset to page 1 when search changes useEffect(() => { setCurrentPage(1); }, [searchQuery]); if (!isAuthenticated) { return (

Admin Login

setPassword(e.target.value)} className="form-input" style={{ marginBottom: '1rem', maxWidth: '300px' }} placeholder="Password" />
); } return (

Admin Dashboard

Upload New Song

setFile(e.target.files?.[0] || null)} className="form-input" required />
{message &&

{message}

}

Song Library

{/* Search */}
setSearchQuery(e.target.value)} className="form-input" />
{paginatedSongs.map(song => ( {editingId === song.id ? ( <> ) : ( <> )} ))} {paginatedSongs.length === 0 && ( )}
ID handleSort('title')} > Title {sortField === 'title' && (sortDirection === 'asc' ? '↑' : '↓')} handleSort('artist')} > Artist {sortField === 'artist' && (sortDirection === 'asc' ? '↑' : '↓')} handleSort('createdAt')} > Added {sortField === 'createdAt' && (sortDirection === 'asc' ? '↑' : '↓')} Activations Actions
{song.id} setEditTitle(e.target.value)} className="form-input" style={{ padding: '0.25rem' }} /> setEditArtist(e.target.value)} className="form-input" style={{ padding: '0.25rem' }} /> {new Date(song.createdAt).toLocaleDateString('de-DE')} {song.activations}
{song.title} {song.artist} {new Date(song.createdAt).toLocaleDateString('de-DE')} {song.activations}
{searchQuery ? 'No songs found matching your search.' : 'No songs uploaded yet.'}
{/* Pagination */} {totalPages > 1 && (
Page {currentPage} of {totalPages}
)}
); }