From d76aa9f4e92d889aaf52b1d05db676380c0c404d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=B6rdle=20Bot?= Date: Tue, 2 Dec 2025 13:28:33 +0100 Subject: [PATCH] Bump version to v0.1.4.7 --- app/[locale]/admin/page.tsx | 250 +++++++++++++++++++++++++++++++++++- app/[locale]/layout.tsx | 2 + package.json | 2 +- 3 files changed, 251 insertions(+), 3 deletions(-) diff --git a/app/[locale]/admin/page.tsx b/app/[locale]/admin/page.tsx index 58d907d..ba3f881 100644 --- a/app/[locale]/admin/page.tsx +++ b/app/[locale]/admin/page.tsx @@ -68,6 +68,14 @@ interface News { } | null; } +interface PoliticalStatement { + id: number; + text: string; + active?: boolean; + source?: string; + locale: string; +} + type SortField = 'id' | 'title' | 'artist' | 'createdAt' | 'releaseYear' | 'activations' | 'averageRating'; type SortDirection = 'asc' | 'desc'; @@ -169,6 +177,11 @@ export default function AdminPage({ params }: { params: { locale: string } }) { const [showSpecials, setShowSpecials] = useState(false); const [showGenres, setShowGenres] = useState(false); const [showNews, setShowNews] = useState(false); + const [showPoliticalStatements, setShowPoliticalStatements] = useState(false); + const [politicalStatementsLocale, setPoliticalStatementsLocale] = useState<'de' | 'en'>('de'); + const [politicalStatements, setPoliticalStatements] = useState([]); + const [newPoliticalStatementText, setNewPoliticalStatementText] = useState(''); + const [newPoliticalStatementActive, setNewPoliticalStatementActive] = useState(true); const fileInputRef = useRef(null); // Check for existing auth on mount @@ -447,6 +460,100 @@ export default function AdminPage({ params }: { params: { locale: string } }) { } }; + // Political Statements functions (JSON-backed via API) + const fetchPoliticalStatements = async (targetLocale: 'de' | 'en') => { + const res = await fetch(`/api/political-statements?locale=${encodeURIComponent(targetLocale)}&admin=true`, { + headers: getAuthHeaders(), + }); + if (res.ok) { + const data = await res.json(); + const enriched: PoliticalStatement[] = data.map((s: any) => ({ + id: s.id, + text: s.text, + active: s.active !== false, + source: s.source, + locale: targetLocale, + })); + setPoliticalStatements(prev => { + const others = prev.filter(p => p.locale !== targetLocale); + return [...others, ...enriched]; + }); + } + }; + + const handleCreatePoliticalStatement = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newPoliticalStatementText.trim()) return; + + const res = await fetch('/api/political-statements', { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + locale: politicalStatementsLocale, + text: newPoliticalStatementText.trim(), + active: newPoliticalStatementActive, + }), + }); + + if (res.ok) { + setNewPoliticalStatementText(''); + setNewPoliticalStatementActive(true); + fetchPoliticalStatements(politicalStatementsLocale); + } else { + alert('Failed to create statement'); + } + }; + + const handleEditPoliticalStatementText = (locale: string, id: number, text: string) => { + setPoliticalStatements(prev => + prev.map(s => (s.locale === locale && s.id === id ? { ...s, text } : s)), + ); + }; + + const handleEditPoliticalStatementActive = (locale: string, id: number, active: boolean) => { + setPoliticalStatements(prev => + prev.map(s => (s.locale === locale && s.id === id ? { ...s, active } : s)), + ); + }; + + const handleSavePoliticalStatement = async (locale: string, id: number) => { + const stmt = politicalStatements.find(s => s.locale === locale && s.id === id); + if (!stmt) return; + + const res = await fetch('/api/political-statements', { + method: 'PUT', + headers: getAuthHeaders(), + body: JSON.stringify({ + locale, + id, + text: stmt.text, + active: stmt.active !== false, + source: stmt.source, + }), + }); + + if (!res.ok) { + alert('Failed to save statement'); + fetchPoliticalStatements(locale as 'de' | 'en'); + } + }; + + const handleDeletePoliticalStatement = async (locale: string, id: number) => { + if (!confirm('Delete this statement?')) return; + + const res = await fetch('/api/political-statements', { + method: 'DELETE', + headers: getAuthHeaders(), + body: JSON.stringify({ locale, id }), + }); + + if (res.ok) { + setPoliticalStatements(prev => prev.filter(s => !(s.locale === locale && s.id === id))); + } else { + alert('Failed to delete statement'); + } + }; + const handleCreateNews = async (e: React.FormEvent) => { e.preventDefault(); if ((!newNewsTitle.de.trim() && !newNewsTitle.en.trim()) || (!newNewsContent.de.trim() && !newNewsContent.en.trim())) return; @@ -524,9 +631,13 @@ export default function AdminPage({ params }: { params: { locale: string } }) { } }; - // Load specials after auth + // Load specials and political statements after auth useEffect(() => { - if (isAuthenticated) fetchSpecials(); + if (isAuthenticated) { + fetchSpecials(); + fetchPoliticalStatements('de'); + fetchPoliticalStatements('en'); + } }, [isAuthenticated]); const deleteGenre = async (id: number) => { @@ -1580,6 +1691,141 @@ export default function AdminPage({ params }: { params: { locale: string } }) { )} + {/* Political Statements Management */} +
+
+

+ Political Statements +

+ +
+ {showPoliticalStatements && ( + <> + {/* Language Tabs */} +
+ {(['de', 'en'] as const).map(lang => ( + + ))} +
+ + {/* Create Form */} +
+
+