"use client"; import React, { useEffect, useState } from "react"; import { useAuth } from "@/hooks/useAuth"; import { useRouter } from "next/navigation"; import { apiFetch } from "@/lib/api"; import { Megaphone } from "lucide-react"; type BannerType = "info" | "warning" | "success" | "danger"; const TYPE_LABELS: Record = { info: "Info (blue)", warning: "Warning (amber)", success: "Success (green)", danger: "Danger (red)", }; export default function SetBannerPage() { const { user, token, loading } = useAuth(); const router = useRouter(); const [message, setMessage] = useState(""); const [type, setType] = useState("info"); const [liveFrom, setLiveFrom] = useState(""); const [liveTill, setLiveTill] = useState(""); const [busy, setBusy] = useState(false); const [status, setStatus] = useState(null); const [error, setError] = useState(null); useEffect(() => { if (loading) return; if (!user) { router.replace("/login"); return; } if (user.role !== "admin" && user.role !== "supervisor") { router.replace("/dashboard"); } }, [user, loading, router]); // Load current banner useEffect(() => { apiFetch("/api/banner") .then(b => { if (!b) return; setMessage(b.message || ""); setType(b.type || "info"); // Convert ISO strings back to datetime-local format setLiveFrom(b.liveFrom ? toLocalInput(b.liveFrom) : ""); setLiveTill(b.liveTill ? toLocalInput(b.liveTill) : ""); }) .catch(() => {}); }, []); function toLocalInput(iso: string) { const d = new Date(iso); if (isNaN(d.getTime())) return ""; // datetime-local wants "YYYY-MM-DDTHH:MM" const pad = (n: number) => String(n).padStart(2, "0"); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; } const submit = async (e: React.FormEvent) => { e.preventDefault(); if (!token) return; setError(null); setStatus(null); setBusy(true); try { await apiFetch("/api/banner", { method: "POST", authToken: token, body: { message, type, liveFrom: liveFrom ? new Date(liveFrom).toISOString() : null, liveTill: liveTill ? new Date(liveTill).toISOString() : null, }, }); setStatus("Banner saved."); } catch (e: any) { setError(e?.message || "Failed to save banner."); } finally { setBusy(false); } }; const clear = async () => { if (!token) return; setError(null); setStatus(null); setBusy(true); try { await apiFetch("/api/banner", { method: "POST", authToken: token, body: { message: "", type: "info", liveFrom: null, liveTill: null }, }); setMessage(""); setType("info"); setLiveFrom(""); setLiveTill(""); setStatus("Banner cleared."); } catch (e: any) { setError(e?.message || "Failed to clear banner."); } finally { setBusy(false); } }; return (

Site Banner

Set a message that appears at the top of every page for visitors within the scheduled window.

setMessage(e.target.value)} />
setLiveFrom(e.target.value)} />
setLiveTill(e.target.value)} />

Leave dates empty to show the banner immediately with no end date. Times use your local timezone.

{error &&

{error}

} {status &&

{status}

}
); }