v1 review pass: fixed some minor bugs

This commit is contained in:
khannurien
2026-03-16 11:08:39 +00:00
parent e88fed4e98
commit 867e64cb5b
37 changed files with 1228 additions and 400 deletions

View File

@@ -1,9 +1,10 @@
import { useEffect, useState } from "react";
import { Link, useLocation, useParams } from "react-router";
import { Link, useLocation, useNavigate, useParams } from "react-router";
import { API_URL } from "../config/api.ts";
import type { Dump, PublicUser } from "../model.ts";
import { deserializeDump, deserializePublicUser } from "../model.ts";
import { useAuth } from "../hooks/useAuth.ts";
import { relativeTime } from "../utils/relativeTime.ts";
@@ -13,6 +14,7 @@ import RichContentCard from "../components/RichContentCard.tsx";
import FilePreview from "../components/FilePreview.tsx";
import { VoteButton } from "../components/VoteButton.tsx";
import { PageShell } from "../components/PageShell.tsx";
import { PageError } from "../components/PageError.tsx";
type DumpState =
| { status: "loading" }
@@ -22,6 +24,7 @@ type DumpState =
export function Dump() {
const { selectedDump } = useParams();
const location = useLocation();
const navigate = useNavigate();
const preloaded = (location.state as { dump?: Dump } | null)?.dump ?? null;
const [dumpState, setDumpState] = useState<DumpState>(
@@ -38,7 +41,7 @@ export function Dump() {
if (preloaded) {
fetch(`${API_URL}/api/users/by-id/${preloaded.userId}`)
.then((r) => r.json())
.then((r) => r.success && setOp(r.data))
.then((r) => r.success && setOp(deserializePublicUser(r.data)))
.catch(() => {});
return;
}
@@ -48,16 +51,18 @@ export function Dump() {
(async () => {
try {
const res = await fetch(`${API_URL}/api/dumps/${selectedDump}`, { cache: "no-store" });
const res = await fetch(`${API_URL}/api/dumps/${selectedDump}`, {
cache: "no-store",
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const apiResponse = await res.json();
const dump: Dump = apiResponse.data;
const dump: Dump = deserializeDump(apiResponse.data);
setDumpState({ status: "loaded", dump });
fetch(`${API_URL}/api/users/by-id/${dump.userId}`)
.then((r) => r.json())
.then((r) => r.success && setOp(r.data))
.then((r) => r.success && setOp(deserializePublicUser(r.data)))
.catch(() => {});
} catch (err) {
setDumpState({
@@ -66,22 +71,39 @@ export function Dump() {
});
}
})();
}, [selectedDump]);
}, [selectedDump, preloaded]);
if (dumpState.status === "loading") {
return <PageShell><p className="page-loading">Loading dump</p></PageShell>;
return (
<PageShell>
<p className="page-loading">Loading dump</p>
</PageShell>
);
}
if (dumpState.status === "error") {
return (
<PageShell>
<div className="page-error">
<h2>Error</h2>
<p>{dumpState.error}</p>
<button type="button" onClick={() => globalThis.location.reload()}>Retry</button>
<Link to="/"> Back to all dumps</Link>
</div>
</PageShell>
<PageError
message={dumpState.error}
actions={
<>
<button
className="logout-btn"
type="button"
onClick={() => globalThis.location.reload()}
>
Retry
</button>
<button
className="logout-btn"
type="button"
onClick={() => navigate("/")}
>
Back to all dumps
</button>
</>
}
/>
);
}
@@ -112,9 +134,17 @@ export function Dump() {
size={22}
/>
{op
? <Link to={`/users/${op.username}`} className="dump-op-link">{op.username}</Link>
? (
<Link to={`/users/${op.username}`} className="dump-op-link">
{op.username}
</Link>
)
: <span className="dump-op-link"></span>}
<time className="dump-card-date" dateTime={dump.createdAt} title={new Date(dump.createdAt).toLocaleString()}>
<time
className="dump-card-date"
dateTime={dump.createdAt.toISOString()}
title={dump.createdAt.toLocaleString()}
>
{relativeTime(dump.createdAt)}
</time>
</div>
@@ -133,7 +163,12 @@ export function Dump() {
: dump.richContent
? <RichContentCard richContent={dump.richContent} />
: (
<a href={dump.url} target="_blank" rel="noopener noreferrer" className="dump-url-link">
<a
href={dump.url}
target="_blank"
rel="noopener noreferrer"
className="dump-url-link"
>
{dump.url}
</a>
)}