Add site banner, build number, and changelog
This commit is contained in:
85
frontend/app/changelog/page.tsx
Normal file
85
frontend/app/changelog/page.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { authFetch, clearToken, getApiBase, getToken } from '../lib/auth'
|
||||
|
||||
type SiteInfo = {
|
||||
changelog?: string
|
||||
}
|
||||
|
||||
const parseChangelog = (raw: string) =>
|
||||
raw
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
|
||||
export default function ChangelogPage() {
|
||||
const router = useRouter()
|
||||
const [entries, setEntries] = useState<string[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
const token = getToken()
|
||||
if (!token) {
|
||||
router.push('/login')
|
||||
return
|
||||
}
|
||||
let active = true
|
||||
const load = async () => {
|
||||
try {
|
||||
const baseUrl = getApiBase()
|
||||
const response = await authFetch(`${baseUrl}/site/info`)
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
clearToken()
|
||||
router.push('/login')
|
||||
return
|
||||
}
|
||||
throw new Error('Failed to load changelog')
|
||||
}
|
||||
const data: SiteInfo = await response.json()
|
||||
if (!active) return
|
||||
setEntries(parseChangelog(data?.changelog ?? ''))
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
if (!active) return
|
||||
setEntries([])
|
||||
} finally {
|
||||
if (active) setLoading(false)
|
||||
}
|
||||
}
|
||||
void load()
|
||||
return () => {
|
||||
active = false
|
||||
}
|
||||
}, [router])
|
||||
|
||||
const content = useMemo(() => {
|
||||
if (loading) {
|
||||
return <div className="loading-text">Loading changelog...</div>
|
||||
}
|
||||
if (entries.length === 0) {
|
||||
return <div className="meta">No updates posted yet.</div>
|
||||
}
|
||||
return (
|
||||
<ul className="changelog-list">
|
||||
{entries.map((entry, index) => (
|
||||
<li key={`${entry}-${index}`}>{entry}</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}, [entries, loading])
|
||||
|
||||
return (
|
||||
<div className="page">
|
||||
<section className="card changelog-card">
|
||||
<div className="changelog-header">
|
||||
<h1>Changelog</h1>
|
||||
<p className="lede">Latest updates and release notes.</p>
|
||||
</div>
|
||||
{content}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user