Add Sheets-first mirror control
This commit is contained in:
parent
10d386bc7d
commit
fbd1c2cc4a
6
app/api/google/data-system-mode/route.ts
Normal file
6
app/api/google/data-system-mode/route.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { NextRequest } from "next/server";
|
||||||
|
import { proxyRequest } from "@/lib/backend";
|
||||||
|
|
||||||
|
export async function POST(req: NextRequest) {
|
||||||
|
return proxyRequest(req, "google/data-system-mode");
|
||||||
|
}
|
||||||
@ -24,6 +24,23 @@ type TellerEnrollment = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type GoogleStatus = {
|
||||||
|
connected: boolean;
|
||||||
|
googleEmail?: string;
|
||||||
|
driveMirror?: {
|
||||||
|
enabled: boolean;
|
||||||
|
status: string;
|
||||||
|
url?: string | null;
|
||||||
|
lastSyncedAt?: string | null;
|
||||||
|
};
|
||||||
|
dataSystem?: {
|
||||||
|
mode: string;
|
||||||
|
operationalSystemOfRecord: string;
|
||||||
|
userOwnedMirror: boolean;
|
||||||
|
note: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
TellerConnect?: {
|
TellerConnect?: {
|
||||||
@ -53,6 +70,7 @@ export default function ConnectPage() {
|
|||||||
const [manualType, setManualType] = useState("checking");
|
const [manualType, setManualType] = useState("checking");
|
||||||
const [accounts, setAccounts] = useState<Account[]>([]);
|
const [accounts, setAccounts] = useState<Account[]>([]);
|
||||||
const [tellerReady, setTellerReady] = useState(false);
|
const [tellerReady, setTellerReady] = useState(false);
|
||||||
|
const [googleStatus, setGoogleStatus] = useState<GoogleStatus | null>(null);
|
||||||
|
|
||||||
const createLinkToken = useCallback(async () => {
|
const createLinkToken = useCallback(async () => {
|
||||||
setStatus("Requesting Plaid link token...");
|
setStatus("Requesting Plaid link token...");
|
||||||
@ -84,6 +102,13 @@ export default function ConnectPage() {
|
|||||||
setAccounts(payload.data?.accounts ?? payload.data ?? []);
|
setAccounts(payload.data?.accounts ?? payload.data ?? []);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const loadGoogleStatus = useCallback(async () => {
|
||||||
|
const res = await fetch("/api/google/status");
|
||||||
|
if (!res.ok) return;
|
||||||
|
const payload = await res.json();
|
||||||
|
setGoogleStatus(payload.data ?? payload);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const loadTellerScript = useCallback(() => {
|
const loadTellerScript = useCallback(() => {
|
||||||
if (typeof window === "undefined") return Promise.resolve(false);
|
if (typeof window === "undefined") return Promise.resolve(false);
|
||||||
if (window.TellerConnect) {
|
if (window.TellerConnect) {
|
||||||
@ -115,8 +140,9 @@ export default function ConnectPage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
createLinkToken();
|
createLinkToken();
|
||||||
loadAccounts();
|
loadAccounts();
|
||||||
|
loadGoogleStatus();
|
||||||
loadTellerScript();
|
loadTellerScript();
|
||||||
}, [createLinkToken, loadAccounts, loadTellerScript]);
|
}, [createLinkToken, loadAccounts, loadGoogleStatus, loadTellerScript]);
|
||||||
|
|
||||||
const onSuccess = useCallback(
|
const onSuccess = useCallback(
|
||||||
async (publicToken: string | null) => {
|
async (publicToken: string | null) => {
|
||||||
@ -301,6 +327,22 @@ export default function ConnectPage() {
|
|||||||
await loadAccounts();
|
await loadAccounts();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const enableSheetsMirror = async () => {
|
||||||
|
setStatus("Enabling Sheets-first mirror mode...");
|
||||||
|
const res = await fetch("/api/google/data-system-mode", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ mode: "google_sheets_mirror" })
|
||||||
|
});
|
||||||
|
const payload = await res.json();
|
||||||
|
if (!res.ok || payload.error) {
|
||||||
|
setStatus(payload.error?.message ?? "Unable to enable Sheets-first mirror mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setStatus("Sheets-first mirror mode enabled.");
|
||||||
|
await loadGoogleStatus();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppShell
|
<AppShell
|
||||||
title="Connect a bank"
|
title="Connect a bank"
|
||||||
@ -447,6 +489,34 @@ export default function ConnectPage() {
|
|||||||
Free includes two connections. Pro supports ten active accounts, and Elite supports unlimited accounts.
|
Free includes two connections. Pro supports ten active accounts, and Elite supports unlimited accounts.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="glass-panel mt-6 p-6 rounded-2xl shadow-sm">
|
||||||
|
<h2 className="text-lg font-bold text-foreground">Google Sheets ownership</h2>
|
||||||
|
<p className="mt-2 text-sm text-muted-foreground">
|
||||||
|
Keep a user-owned Google Sheets mirror synced from LedgerOne transaction changes.
|
||||||
|
</p>
|
||||||
|
<div className="mt-4 rounded-xl border border-border bg-secondary/30 px-4 py-3 text-sm">
|
||||||
|
<p className="font-semibold text-foreground">
|
||||||
|
{googleStatus?.connected ? `Connected: ${googleStatus.googleEmail}` : "Google is not connected"}
|
||||||
|
</p>
|
||||||
|
<p className="mt-1 text-xs text-muted-foreground">
|
||||||
|
Mode: {googleStatus?.dataSystem?.mode ?? "backend_db"} · Mirror: {googleStatus?.driveMirror?.status ?? "not_started"}
|
||||||
|
</p>
|
||||||
|
{googleStatus?.driveMirror?.url ? (
|
||||||
|
<a className="mt-2 inline-block text-xs font-semibold text-primary" href={googleStatus.driveMirror.url} target="_blank" rel="noreferrer">
|
||||||
|
Open Google Sheet
|
||||||
|
</a>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="mt-4 rounded-full border border-border bg-background px-5 py-2 text-sm font-semibold text-foreground hover:bg-secondary transition-colors disabled:opacity-50"
|
||||||
|
onClick={enableSheetsMirror}
|
||||||
|
disabled={!googleStatus?.connected || googleStatus?.dataSystem?.mode === "google_sheets_mirror"}
|
||||||
|
>
|
||||||
|
Enable Sheets-first mirror
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</AppShell>
|
</AppShell>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user