ledgerone_frontend/components/hero-actions.tsx
2026-02-24 21:47:18 +00:00

92 lines
2.6 KiB
TypeScript

"use client";
import { useState } from "react";
type ApiResponse<T> = {
data: T;
meta: { timestamp: string; version: "v1" };
error: null | { message: string; code?: string };
};
type LinkTokenData = { linkToken?: string };
type ExportData = { status?: string; url?: string; csv?: string };
async function postJson<T>(path: string) {
const res = await fetch(path, {
method: "POST"
});
if (!res.ok) {
throw new Error("Request failed");
}
const payload = (await res.json()) as ApiResponse<T>;
return payload.data;
}
async function getJson<T>(path: string) {
const res = await fetch(path);
if (!res.ok) {
throw new Error("Request failed");
}
const payload = (await res.json()) as ApiResponse<T>;
return payload.data;
}
export function HeroActions() {
const [status, setStatus] = useState<string>("");
const onStart = async () => {
setStatus("Requesting a secure link token...");
try {
const data = await postJson<LinkTokenData>("/api/accounts/link");
if (data.linkToken) {
setStatus(`Link token ready: ${data.linkToken}`);
} else {
setStatus("Link token requested.");
}
} catch {
setStatus("Unable to request link token.");
}
};
const onViewExport = async () => {
setStatus("Preparing export sample...");
try {
const userId = localStorage.getItem("ledgerone_user_id");
const query = userId ? `?user_id=${encodeURIComponent(userId)}` : "";
const data = await getJson<ExportData>(`/api/exports/csv${query}`);
if (data.csv) {
const blob = new Blob([data.csv], { type: "text/csv" });
const url = URL.createObjectURL(blob);
window.open(url, "_blank", "noopener,noreferrer");
setStatus("Export sample opened.");
} else {
setStatus("Export sample ready.");
}
} catch {
setStatus("Unable to fetch export sample.");
}
};
return (
<div className="space-y-3">
<div className="flex flex-wrap gap-4">
<button
type="button"
onClick={onStart}
className="rounded-full bg-ink px-6 py-3 text-sm font-semibold text-haze shadow-glow"
>
Start a private ledger
</button>
<button
type="button"
onClick={onViewExport}
className="rounded-full border border-ink/20 bg-white/70 px-6 py-3 text-sm font-semibold text-ink"
>
View export sample
</button>
</div>
{status ? <p className="text-xs text-muted">{status}</p> : null}
</div>
);
}