71 lines
1.7 KiB
TypeScript
71 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState, type CSSProperties } from "react";
|
|
import { authFetch, clearToken, getApiBase, getToken } from "../lib/auth";
|
|
|
|
type BannerInfo = {
|
|
enabled: boolean;
|
|
message: string;
|
|
tone?: string;
|
|
backgroundColor?: string | null;
|
|
borderColor?: string | null;
|
|
};
|
|
|
|
type SiteInfo = {
|
|
buildNumber?: string;
|
|
banner?: BannerInfo;
|
|
};
|
|
|
|
const buildRequest = () => {
|
|
const token = getToken();
|
|
const baseUrl = getApiBase();
|
|
const url = token ? `${baseUrl}/site/info` : `${baseUrl}/site/public`;
|
|
const fetcher = token ? authFetch : fetch;
|
|
return { token, url, fetcher };
|
|
};
|
|
|
|
export default function SiteStatus() {
|
|
const [info, setInfo] = useState<SiteInfo | null>(null);
|
|
|
|
useEffect(() => {
|
|
let active = true;
|
|
const load = async () => {
|
|
try {
|
|
const { token, url, fetcher } = buildRequest();
|
|
const response = await fetcher(url);
|
|
if (!response.ok) {
|
|
if (response.status === 401 && token) {
|
|
clearToken();
|
|
}
|
|
return;
|
|
}
|
|
const data = await response.json();
|
|
if (!active) return;
|
|
setInfo(data);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
};
|
|
void load();
|
|
return () => {
|
|
active = false;
|
|
};
|
|
}, []);
|
|
|
|
const banner = info?.banner;
|
|
const tone = banner?.tone || "info";
|
|
const bannerStyle = {
|
|
"--site-banner-background-color": banner?.backgroundColor || undefined,
|
|
"--site-banner-border-color": banner?.borderColor || undefined,
|
|
} as CSSProperties;
|
|
return (
|
|
<>
|
|
{banner?.enabled && banner.message ? (
|
|
<div className={`site-banner site-banner--${tone}`} style={bannerStyle}>
|
|
{banner.message}
|
|
</div>
|
|
) : null}
|
|
</>
|
|
);
|
|
}
|