lomavuokraus/app/admin/settings/page.tsx
Tero Halla-aho 0bb709d9c5
Some checks failed
CI / checks (push) Has been cancelled
chore: fix audit alerts and formatting
2026-02-04 12:43:03 +02:00

135 lines
4 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { useI18n } from "../../components/I18nProvider";
type SiteSettings = {
requireLoginForContactDetails: boolean;
};
export default function AdminSettingsPage() {
const { t } = useI18n();
const [settings, setSettings] = useState<SiteSettings | null>(null);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [error, setError] = useState<string | null>(null);
const [message, setMessage] = useState<string | null>(null);
const [isAdmin, setIsAdmin] = useState(false);
useEffect(() => {
async function load() {
setLoading(true);
setError(null);
try {
const meRes = await fetch("/api/auth/me", { cache: "no-store" });
const me = await meRes.json();
if (me.user?.role !== "ADMIN") {
setError(t("adminRequired"));
setLoading(false);
return;
}
setIsAdmin(true);
const res = await fetch("/api/admin/settings", { cache: "no-store" });
const data = await res.json();
if (!res.ok) {
setError(data.error || "Failed to load settings");
} else {
setSettings(data.settings);
}
} catch (err) {
console.error(err);
setError("Failed to load settings");
} finally {
setLoading(false);
}
}
load();
}, [t]);
async function save(next: Partial<SiteSettings>) {
if (!isAdmin) return;
setSaving(true);
setMessage(null);
setError(null);
try {
const res = await fetch("/api/admin/settings", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(next),
});
const data = await res.json();
if (!res.ok) {
setError(data.error || "Failed to save settings");
} else {
setSettings(data.settings);
setMessage(t("settingsSaved"));
}
} catch (err) {
console.error(err);
setError("Failed to save settings");
} finally {
setSaving(false);
}
}
function toggleRequireLoginForContactDetails() {
if (!settings) return;
save({
requireLoginForContactDetails: !settings.requireLoginForContactDetails,
});
}
return (
<main className="panel" style={{ maxWidth: 960, margin: "40px auto" }}>
<h1>{t("adminSettingsTitle")}</h1>
<p>{t("adminSettingsLead")}</p>
{loading ? <p>{t("loading")}</p> : null}
{message ? <p style={{ color: "green" }}>{message}</p> : null}
{error ? <p style={{ color: "red" }}>{error}</p> : null}
{!loading && settings ? (
<div style={{ display: "grid", gap: 16, marginTop: 16 }}>
<section
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "flex-start",
border: "1px solid #e5e7eb",
borderRadius: 12,
padding: 16,
background:
"linear-gradient(135deg, rgba(14,165,233,0.08), rgba(30,64,175,0.08))",
}}
>
<div style={{ maxWidth: 520 }}>
<h2 style={{ margin: "0 0 8px" }}>
{t("settingContactVisibilityTitle")}
</h2>
<p style={{ margin: 0, color: "#475569" }}>
{t("settingContactVisibilityHelp")}
</p>
</div>
<label
style={{
display: "flex",
alignItems: "center",
gap: 10,
fontWeight: 600,
}}
>
<input
type="checkbox"
checked={settings.requireLoginForContactDetails}
onChange={toggleRequireLoginForContactDetails}
disabled={saving}
/>
<span>{t("settingRequireLoginForContact")}</span>
</label>
</section>
</div>
) : null}
</main>
);
}