diff --git a/src/app/dashboard/wallets/[id]/payment-links/page.tsx b/src/app/dashboard/wallets/[id]/payment-links/page.tsx index a5ae12b..106374a 100644 --- a/src/app/dashboard/wallets/[id]/payment-links/page.tsx +++ b/src/app/dashboard/wallets/[id]/payment-links/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { use, useCallback, useEffect, useState } from "react"; +import { use, useCallback, useEffect, useRef, useState } from "react"; import { useAuth } from "@/lib/useAuth"; import { useWallet } from "@/lib/useWallet"; import { PaymentLinkList } from "@/components/payment-links/PaymentLinkList"; @@ -51,12 +51,17 @@ export default function PaymentLinksPage({ const [pageIndex, setPageIndex] = useState(0); const [nextCursor, setNextCursor] = useState(null); + // Latest non-silent request id; a response that no longer matches it is stale and dropped. + const latestReq = useRef(0); + const load = useCallback( (before: string | null, opts?: { silent?: boolean }) => { if (!token) return; + const reqId = opts?.silent ? latestReq.current : ++latestReq.current; if (!opts?.silent) setRefreshing(true); - listPaymentLinksPage(asAuthToken(token), asWalletId(id), { before }) + return listPaymentLinksPage(asAuthToken(token), asWalletId(id), { before }) .then((page) => { + if (reqId !== latestReq.current) return; setLinks(page.data); setNextCursor(page.next_cursor); setError(null); @@ -148,14 +153,14 @@ export default function PaymentLinksPage({
- - + +
diff --git a/src/app/dashboard/wallets/[id]/transactions/page.tsx b/src/app/dashboard/wallets/[id]/transactions/page.tsx index e5d2a96..8907404 100644 --- a/src/app/dashboard/wallets/[id]/transactions/page.tsx +++ b/src/app/dashboard/wallets/[id]/transactions/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { use, useCallback, useEffect, useMemo, useState } from "react"; +import { use, useCallback, useEffect, useRef, useMemo, useState } from "react"; import { useAuth } from "@/lib/useAuth"; import { useWallet } from "@/lib/useWallet"; import { @@ -43,12 +43,17 @@ export default function TransactionsPage({ const [pageIndex, setPageIndex] = useState(0); const [nextCursor, setNextCursor] = useState(null); + // Latest non-silent request id; a response that no longer matches it is stale and dropped. + const latestReq = useRef(0); + const load = useCallback( (before: string | null, opts?: { silent?: boolean }) => { if (!token) return; + const reqId = opts?.silent ? latestReq.current : ++latestReq.current; if (!opts?.silent) setRefreshing(true); - listTransactionsPage(token, id, { before }) + return listTransactionsPage(token, id, { before }) .then((page) => { + if (reqId !== latestReq.current) return; setTxns(page.data); setNextCursor(page.next_cursor); setError(null); diff --git a/src/components/addresses/AddressSearchBox.tsx b/src/components/addresses/AddressSearchBox.tsx index e76de9f..c14a0aa 100644 --- a/src/components/addresses/AddressSearchBox.tsx +++ b/src/components/addresses/AddressSearchBox.tsx @@ -16,8 +16,8 @@ export function AddressSearchBox({ onChange }: { onChange: (query: string) => vo type="search" value={value} onChange={(e) => setValue(e.target.value)} - placeholder="Search by customer reference" - aria-label="Search addresses by customer reference" + placeholder="Search loaded addresses by customer reference" + aria-label="Search loaded addresses by customer reference" className="w-full max-w-sm rounded-xl border border-border bg-surface-raised px-4 py-2 text-sm text-foreground placeholder:text-muted/60 focus:border-burgundy-bright focus:outline-none" /> );