Files

117 lines
3.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import PageHeading from "../ui/PageHeading";
import { useEffect, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { authFetch, clearToken, getApiBase, getToken } from "../lib/auth";
type SiteInfo = {
changelog?: string;
};
type ChangelogGroup = {
date: string;
entries: string[];
};
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
const parseChangelog = (raw: string): ChangelogGroup[] => {
const groups: ChangelogGroup[] = [];
for (const rawLine of raw.split("\n")) {
const line = rawLine.trim();
if (!line) continue;
const [candidateDate, ...messageParts] = line.split("|");
if (DATE_PATTERN.test(candidateDate) && messageParts.length > 0) {
const message = messageParts.join("|").trim();
if (!message) continue;
const currentGroup = groups[groups.length - 1];
if (currentGroup?.date === candidateDate) {
currentGroup.entries.push(message);
} else {
groups.push({ date: candidateDate, entries: [message] });
}
continue;
}
if (groups.length === 0) {
groups.push({ date: "Updates", entries: [line] });
} else {
groups[groups.length - 1].entries.push(line);
}
}
return groups;
};
export default function ChangelogPage() {
const router = useRouter();
const [groups, setGroups] = useState<ChangelogGroup[]>([]);
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;
setGroups(parseChangelog(data?.changelog ?? ""));
} catch (err) {
console.error(err);
if (!active) return;
setGroups([]);
} 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 (groups.length === 0) {
return <div className="meta">No updates posted yet.</div>;
}
return (
<div className="changelog-groups">
{groups.map((group) => (
<section key={group.date} className="changelog-group">
<h2>{group.date}</h2>
<ul className="changelog-list">
{group.entries.map((entry, index) => (
<li key={`${group.date}-${entry}-${index}`}>{entry}</li>
))}
</ul>
</section>
))}
</div>
);
}, [groups, loading]);
return (
<main className="card changelog-page">
<PageHeading title="Changelog" description="Whats new and improved in Magent." />
{content}
</main>
);
}