66 lines
1.5 KiB
TypeScript
66 lines
1.5 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
import { authFetch, clearToken, getApiBase, getToken } from '../lib/auth'
|
|
|
|
type BannerInfo = {
|
|
enabled: boolean
|
|
message: string
|
|
tone?: string
|
|
}
|
|
|
|
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'
|
|
return (
|
|
<>
|
|
{banner?.enabled && banner.message ? (
|
|
<div className={`site-banner site-banner--${tone}`}>{banner.message}</div>
|
|
) : null}
|
|
{info?.buildNumber ? (
|
|
<div className="site-version">Build {info.buildNumber}</div>
|
|
) : null}
|
|
</>
|
|
)
|
|
}
|