"use client"; import { useEffect, useState } from "react"; export default function AdminSystemSettings() { const [apiKey, setApiKey] = useState(""); const [provider, setProvider] = useState("osm"); const [registrationEnabled, setRegistrationEnabled] = useState(true); const [publicAccessEnabled, setPublicAccessEnabled] = useState(true); const [appName, setAppName] = useState("Vereinskalender"); const [logoFile, setLogoFile] = useState(null); const [logoVersion, setLogoVersion] = useState(() => Date.now()); const [hasLogo, setHasLogo] = useState(null); const [status, setStatus] = useState(null); const [error, setError] = useState(null); const load = async () => { try { const [placesResponse, appNameResponse] = await Promise.all([ fetch("/api/settings/system"), fetch("/api/settings/app-name") ]); if (!placesResponse.ok) { throw new Error("Einstellungen konnten nicht geladen werden."); } const payload = await placesResponse.json(); setApiKey(payload.apiKey || ""); setProvider(payload.provider || "osm"); setRegistrationEnabled(payload.registrationEnabled !== false); setPublicAccessEnabled(payload.publicAccessEnabled !== false); if (appNameResponse.ok) { const appPayload = await appNameResponse.json(); setAppName(appPayload.name || "Vereinskalender"); } } catch (err) { setError((err as Error).message); } }; const loadLogoStatus = async () => { try { const response = await fetch("/api/branding/logo", { method: "HEAD", cache: "no-store" }); setHasLogo(response.ok); } catch { setHasLogo(false); } }; useEffect(() => { load(); loadLogoStatus(); }, []); const onSubmit = async (event: React.FormEvent) => { event.preventDefault(); setStatus(null); setError(null); const [settingsResponse, appNameResponse] = await Promise.all([ fetch("/api/settings/system", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ apiKey, provider, registrationEnabled, publicAccessEnabled }) }), fetch("/api/settings/app-name", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: appName }) }) ]); if (!settingsResponse.ok) { const data = await settingsResponse.json(); setError(data.error || "Speichern fehlgeschlagen."); return; } if (!appNameResponse.ok) { const data = await appNameResponse.json(); setError(data.error || "App-Name konnte nicht gespeichert werden."); return; } setStatus("Gespeichert."); }; const onLogoUpload = async (event: React.FormEvent) => { event.preventDefault(); setStatus(null); setError(null); if (!logoFile) { setError("Bitte ein Logo auswählen."); return; } const formData = new FormData(); formData.append("file", logoFile); const response = await fetch("/api/settings/logo", { method: "POST", body: formData }); if (!response.ok) { const data = await response.json(); setError(data.error || "Logo-Upload fehlgeschlagen."); return; } setLogoFile(null); setLogoVersion(Date.now()); setHasLogo(true); setStatus("Logo gespeichert."); }; const onLogoRemove = async () => { setStatus(null); setError(null); const response = await fetch("/api/settings/logo", { method: "DELETE" }); if (!response.ok) { const data = await response.json(); setError(data.error || "Logo konnte nicht gelöscht werden."); return; } setHasLogo(false); setLogoVersion(Date.now()); setStatus("Logo entfernt."); }; return (

System

API Einstellungen

App-Logo

PNG, JPG, WEBP oder SVG. Empfohlen: 240×64 px.

{hasLogo ? (
Aktuelles Logo setHasLogo(false)} />
) : (

Kein Logo hinterlegt.

)}
{logoFile ? logoFile.name : "Keine Datei ausgewählt"}
setAppName(event.target.value)} className="w-full rounded-xl border border-slate-300 px-3 py-2" placeholder="Vereinskalender" required maxLength={60} />
{provider === "google" && (
setApiKey(event.target.value)} className="w-full rounded-xl border border-slate-300 px-3 py-2" placeholder="AIza..." required />
)}

Zugriff

{status &&

{status}

} {error &&

{error}

}
); }