"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { api } from "@/lib/client"; import type { GitStatus } from "@/lib/git"; import type { PublishStep } from "@/lib/publish"; type Config = { push: boolean; pushAuth: string; deploy: boolean; deployUrl: string | null }; function defaultMessage(status: GitStatus): string { const n = status.changes.length; return n === 1 && status.changes[0].path.endsWith("blog-posts.json") ? "blog: update posts" : `blog: update posts (${n} files)`; } export default function PublishPanel({ status: initial, config }: { status: GitStatus; config: Config }) { const router = useRouter(); const [status, setStatus] = useState(initial); const [message, setMessage] = useState(() => defaultMessage(initial)); const [running, setRunning] = useState(false); const [result, setResult] = useState<{ ok: boolean; steps: PublishStep[] } | null>(null); if (!status.available) { return (
git isn't usable on the portfolio checkout: {status.error}
); } const ahead = status.ahead ?? 0; const nothingToDo = status.changes.length === 0 && ahead === 0; async function run() { setRunning(true); setResult(null); try { const res = await api<{ ok: boolean; steps: PublishStep[]; status: GitStatus }>("/api/publish", { method: "POST", json: { message }, }); setResult(res); setStatus(res.status); } catch (err) { setResult({ ok: false, steps: [{ step: "stage", status: "failed", output: (err as Error).message }] }); } finally { setRunning(false); router.refresh(); } } return ( <>

Branch {status.branch} {status.ahead !== undefined && ( <> {" "}· {status.ahead} ahead / {status.behind} behind upstream (as of last fetch) )} . Only data/blog-posts.json and public/img/blog/ are committed.

Pending changes

{status.changes.length === 0 ? (

No uncommitted blog changes.{ahead > 0 && ` ${ahead} commit(s) waiting to be pushed.`}

) : ( {status.changes.map((c) => ( ))}
{c.code} {c.path}
)} {status.diffStat &&
{status.diffStat}
}

Publish

commit → {config.push ? `push (${config.pushAuth})` : "push disabled (GIT_PUSH=false)"} →{" "} {config.deploy ? `trigger redeploy at ${config.deployUrl}` : "redeploy trigger not configured"}

setMessage(e.target.value)} placeholder="commit message" />
{result && ( <>
{result.ok ? "Published." : "Publish failed. See log."}
            {result.steps.map((s) => `[${s.status}] ${s.step}${s.output ? `\n${s.output}` : ""}`).join("\n\n")}
          
)} ); }