113 lines
3.2 KiB
TypeScript
113 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
export default function DashboardPage() {
|
|
const [salesAccountCode, setSalesAccountCode] = useState("");
|
|
const [stripeClearingAccountCode, setStripeClearingAccountCode] =
|
|
useState("");
|
|
const [stripeAccountId, setStripeAccountId] = useState("");
|
|
const [xeroTenantId, setXeroTenantId] = useState("");
|
|
const [loading, setLoading] = useState(true);
|
|
const [saved, setSaved] = useState(false);
|
|
|
|
useEffect(() => {
|
|
Promise.all([
|
|
fetch("/api/dashboard/xero-settings").then((res) => res.json()),
|
|
fetch("/api/dashboard/connections").then((res) => res.json()),
|
|
]).then(([settings, connections]) => {
|
|
setSalesAccountCode(settings.salesAccountCode ?? "");
|
|
setStripeClearingAccountCode(settings.stripeClearingAccountCode ?? "");
|
|
setStripeAccountId(connections.stripeAccountId ?? "");
|
|
setXeroTenantId(connections.xeroTenantId ?? "");
|
|
setLoading(false);
|
|
});
|
|
}, []);
|
|
|
|
async function save() {
|
|
setSaved(false);
|
|
|
|
await fetch("/api/dashboard/xero-settings", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({
|
|
salesAccountCode,
|
|
stripeClearingAccountCode,
|
|
}),
|
|
});
|
|
|
|
setSaved(true);
|
|
}
|
|
|
|
if (loading) return <p>Loading…</p>;
|
|
|
|
return (
|
|
<div className="max-w-xl space-y-6">
|
|
<h1 className="text-2xl font-semibold">
|
|
Stripe → Xero settings
|
|
</h1>
|
|
|
|
{/* Connected Accounts */}
|
|
<div className="border rounded p-4 bg-gray-50 space-y-3">
|
|
<h2 className="font-medium text-sm text-gray-600">Connected Accounts</h2>
|
|
<div className="space-y-2 text-sm">
|
|
<p>
|
|
<span className="font-medium">Stripe:</span>{" "}
|
|
<code className="bg-white px-2 py-1 rounded text-xs">
|
|
{stripeAccountId || "Not connected"}
|
|
</code>
|
|
</p>
|
|
<p>
|
|
<span className="font-medium">Xero:</span>{" "}
|
|
<code className="bg-white px-2 py-1 rounded text-xs">
|
|
{xeroTenantId || "Not connected"}
|
|
</code>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium">
|
|
Sales account code
|
|
</label>
|
|
<input
|
|
className="mt-1 w-full border px-3 py-2"
|
|
value={salesAccountCode}
|
|
onChange={(e) => setSalesAccountCode(e.target.value)}
|
|
/>
|
|
<p className="text-sm text-zinc-500">
|
|
Used on invoice line items
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium">
|
|
Stripe clearing account code
|
|
</label>
|
|
<input
|
|
className="mt-1 w-full border px-3 py-2"
|
|
value={stripeClearingAccountCode}
|
|
onChange={(e) =>
|
|
setStripeClearingAccountCode(e.target.value)
|
|
}
|
|
/>
|
|
<p className="text-sm text-zinc-500">
|
|
Receives Stripe payments
|
|
</p>
|
|
</div>
|
|
|
|
<button
|
|
onClick={save}
|
|
className="rounded bg-black px-4 py-2 text-white"
|
|
>
|
|
Save
|
|
</button>
|
|
|
|
{saved && (
|
|
<p className="text-sm text-green-600">
|
|
Saved
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|