From f6fcf0915f8374610028312bbdffbde13777543f Mon Sep 17 00:00:00 2001 From: adepojuemmanuel235 Date: Sat, 3 Oct 2026 16:26:42 +0000 Subject: [PATCH] Account page: payout address, USDG balances per chain, sign-in methods Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- app/app/(app)/app/account/page.tsx | 7 +++ app/app/signin/sign-in.tsx | 2 +- app/components/app/account.tsx | 89 ++++++++++++++++++++++++++++ app/components/app/app-header.tsx | 6 +- app/components/app/quick-sign-in.tsx | 7 +-- app/components/booking/bookings.tsx | 2 - 6 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 app/app/(app)/app/account/page.tsx create mode 100644 app/components/app/account.tsx diff --git a/app/app/(app)/app/account/page.tsx b/app/app/(app)/app/account/page.tsx new file mode 100644 index 0000000..06128bd --- /dev/null +++ b/app/app/(app)/app/account/page.tsx @@ -0,0 +1,7 @@ +import { Account } from "@/components/app/account"; + +export const metadata = { title: "Account" }; + +export default function Page() { + return ; +} diff --git a/app/app/signin/sign-in.tsx b/app/app/signin/sign-in.tsx index cd1eb3e..d7c7c8e 100644 --- a/app/app/signin/sign-in.tsx +++ b/app/app/signin/sign-in.tsx @@ -17,7 +17,7 @@ function safeNext(raw: string | null) { } const QUICK_FAILED = (method: "Google" | "passkey") => - `Couldn't sign in with ${method === "Google" ? "Google" : "a passkey"}. If you haven't turned on ${method} sign-in for your Setlo account yet, sign in with an email code first, then turn it on from your bookings page.`; + `Couldn't sign in with ${method === "Google" ? "Google" : "a passkey"}. If you haven't turned on ${method} sign-in for your Setlo account yet, sign in with an email code first, then turn it on from your Account page.`; export function SignIn() { const { ready, authenticated } = usePrivy(); diff --git a/app/components/app/account.tsx b/app/components/app/account.tsx new file mode 100644 index 0000000..51b4e79 --- /dev/null +++ b/app/components/app/account.tsx @@ -0,0 +1,89 @@ +"use client"; + +import { useCallback, useEffect, useState } from "react"; +import { QuickSignIn } from "@/components/app/quick-sign-in"; +import { useSession } from "@/components/app/session"; +import { AddressLink, Amount, CopyButton } from "@/components/booking/parts"; +import { Button } from "@/components/ui/button"; +import { Card, Notice, Skeleton } from "@/components/ui/status"; +import { CHAINS } from "@/lib/chains"; +import { account } from "@/lib/client/actions"; +import { friendly } from "@/lib/client/errors"; +import type { AccountState } from "@/lib/types"; + +type Row = { chainId: number; state?: AccountState; error?: string }; +const chainIds = Object.keys(CHAINS).map(Number); + +export function Account() { + const { email, wallet, logout } = useSession(); + const [rows, setRows] = useState(null); + const [loading, setLoading] = useState(false); + + const load = useCallback(async () => { + setLoading(true); + const res = await Promise.allSettled(chainIds.map((id) => account(id, wallet))); + setRows(res.map((r, i) => (r.status === "fulfilled" ? { chainId: chainIds[i], state: r.value } : { chainId: chainIds[i], error: friendly(r.reason) }))); + setLoading(false); + }, [wallet]); + useEffect(() => void load(), [load]); + + return ( +
+
+

Account

+

Signed in as {email}

+
+ + +
+
+

Payout account

+

Setlo created this wallet for you. Payments from your bookings arrive here.

+
+ +
+
+ {wallet} + +
+
    + {chainIds.map((id) => { + const row = rows?.find((r) => r.chainId === id); + return ( +
  • +

    {CHAINS[id].chain.name}

    + {!row ? ( + + ) : row.error ? ( + Couldn't load the balance. {row.error} + ) : ( + <> + + {BigInt(row.state!.claimable) > BigInt(0) && ( +

    + Plus on its way +

    + )} + + )} +
    + +
    +
  • + ); + })} +
+
+ + + +
+ +
+
+ ); +} diff --git a/app/components/app/app-header.tsx b/app/components/app/app-header.tsx index 3be943c..0c13fb2 100644 --- a/app/components/app/app-header.tsx +++ b/app/components/app/app-header.tsx @@ -20,9 +20,9 @@ export function AppHeader() { New package - - {email} - + + Account + diff --git a/app/components/app/quick-sign-in.tsx b/app/components/app/quick-sign-in.tsx index 51ff6d7..3a73d7b 100644 --- a/app/components/app/quick-sign-in.tsx +++ b/app/components/app/quick-sign-in.tsx @@ -23,7 +23,6 @@ export function QuickSignIn() { if (!user) return null; const google = user.google?.email; const passkeys = user.linkedAccounts.filter((a) => a.type === "passkey").length; - if (google && passkeys > 0 && !done) return null; async function addPasskey() { setBusy(true); @@ -40,9 +39,9 @@ export function QuickSignIn() { return ( -

Sign in faster next time

+

Sign-in methods

- Skip the email code when you come back. These sign in to this same account, so your bookings and payout account stay the same. + Email code always works. Add Google or a passkey to skip the code next time. They sign in to this same account, so your bookings and payout account stay the same.

{done && {done}} {error && {error}} @@ -55,7 +54,7 @@ export function QuickSignIn() { )} {passkeys > 0 ? ( -

Passkey sign-in is on.

+

Passkey sign-in is on ({passkeys === 1 ? "1 passkey" : `${passkeys} passkeys`}).

) : (