From 5dac1e5713b7003752a8c7709b6845c56bdd6ba9 Mon Sep 17 00:00:00 2001 From: Temiloluwa Omosuwa Date: Thu, 23 Apr 2026 09:28:58 +0100 Subject: [PATCH 1/2] Align color palette in Onboarding, fix Sidebar a11y, improve Transaction Table responsiveness, and optimize Wallet Modal performance --- .../(authenticated)/payment-history/page.tsx | 66 +++++++++++++++- frontend/src/app/(public)/register/page.tsx | 6 +- frontend/src/components/RegistrationForm.tsx | 4 +- frontend/src/components/Sidebar.tsx | 28 ++++--- frontend/src/components/WalletSelector.tsx | 76 ++++++++++--------- 5 files changed, 126 insertions(+), 54 deletions(-) diff --git a/frontend/src/app/(authenticated)/payment-history/page.tsx b/frontend/src/app/(authenticated)/payment-history/page.tsx index 17787efb..4663025e 100644 --- a/frontend/src/app/(authenticated)/payment-history/page.tsx +++ b/frontend/src/app/(authenticated)/payment-history/page.tsx @@ -807,8 +807,70 @@ export default function PaymentHistoryPage() {

- {/* Payment Table */} -
+ {/* Payment List (Mobile Card View) */} +
+ {payments.map((payment) => ( +
handlePaymentClick(payment.id)} + className={`cursor-pointer rounded-2xl border border-white/10 bg-white/5 p-4 transition-all active:scale-[0.98] ${flashedIds.has(payment.id) + ? "animate-payment-confirmed bg-green-500/10" + : "" + }`} + > +
+ + {toStatusLabel(t, payment.status)} + +

+ {new Date(payment.created_at).toLocaleDateString(locale, { + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + })} +

+
+
+
+

+ {payment.amount} {payment.asset} +

+

+ {payment.description || "No description"} +

+
+
+ + + +
+
+
+ ))} +
+ + {/* Payment Table (Desktop View) */} +
diff --git a/frontend/src/app/(public)/register/page.tsx b/frontend/src/app/(public)/register/page.tsx index b3e9c8ae..8f4ae0b7 100644 --- a/frontend/src/app/(public)/register/page.tsx +++ b/frontend/src/app/(public)/register/page.tsx @@ -7,21 +7,21 @@ export default function RegisterPage() {
-

Onboarding

+

Onboarding

Join the Network

Create your merchant profile to start accepting Stellar payments and managing assets.

-
+

Already have an account?{" "} - + Log in here

diff --git a/frontend/src/components/RegistrationForm.tsx b/frontend/src/components/RegistrationForm.tsx index 6d2df3ec..2d57a19b 100644 --- a/frontend/src/components/RegistrationForm.tsx +++ b/frontend/src/components/RegistrationForm.tsx @@ -50,12 +50,12 @@ export default function RegistrationForm() { if (registeredMerchant) { return (
-
+

Registration Success

-

+

Welcome, {registeredMerchant.business_name}!

diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index 6ace6482..62883e41 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -106,30 +106,34 @@ function NavLinks({ const navItems = getNavItems(t); return ( -

); } diff --git a/frontend/src/components/WalletSelector.tsx b/frontend/src/components/WalletSelector.tsx index a61b881a..feba5e37 100644 --- a/frontend/src/components/WalletSelector.tsx +++ b/frontend/src/components/WalletSelector.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslations } from "next-intl"; import { useWallet } from "@/lib/wallet-context"; import { connectWalletConnect } from "@/lib/wallet-walletconnect"; @@ -44,10 +44,9 @@ export default function WalletSelector({ }; }, [providers]); - // If the active provider is already selected, nothing to show - if (activeProvider) return null; - async function handleSelect(id: string) { + + const handleSelect = useCallback(async (id: string) => { if (id === "walletconnect") { setWcError(null); setWcPairing(true); @@ -68,7 +67,43 @@ export default function WalletSelector({ selectProvider(id); onConnected(); - } + }, [networkPassphrase, onConnected, selectProvider, t]); + + const providerButtons = useMemo(() => { + return providers.map((p) => { + const available = providerAvailability[p.id] ?? false; + const isWc = p.id === "walletconnect"; + + return ( + + ); + }); + }, [providers, providerAvailability, wcPairing, handleSelect, t]); + + // If the active provider is already selected, nothing to show + if (activeProvider) return null; return (
@@ -77,36 +112,7 @@ export default function WalletSelector({

- {providers.map((p) => { - const available = providerAvailability[p.id] ?? false; - const isWc = p.id === "walletconnect"; - - return ( - - ); - })} + {providerButtons}
{/* WalletConnect QR code */} From 9d7bd0db5d7bb84035c8c6dd687e7bec91a6d490 Mon Sep 17 00:00:00 2001 From: Temiloluwa Omosuwa Date: Thu, 23 Apr 2026 09:40:42 +0100 Subject: [PATCH 2/2] Fix syntax errors, missing imports, and lint warnings after conflict resolution --- .../app/(authenticated)/dashboard/page.tsx | 1 + frontend/src/components/RecentPayments.tsx | 2 +- frontend/src/components/WalletSelector.tsx | 93 +++++++++---------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/frontend/src/app/(authenticated)/dashboard/page.tsx b/frontend/src/app/(authenticated)/dashboard/page.tsx index ba29dcb4..0c040057 100644 --- a/frontend/src/app/(authenticated)/dashboard/page.tsx +++ b/frontend/src/app/(authenticated)/dashboard/page.tsx @@ -16,6 +16,7 @@ import FirstApiKeyModal from "@/components/FirstApiKeyModal"; import PaymentMetrics from "@/components/PaymentMetrics"; import RecentPayments from "@/components/RecentPayments"; import WithdrawModal from "@/components/WithdrawModal"; +import FirstPaymentCelebration from "@/components/FirstPaymentCelebration"; export default function DashboardPage() { const t = useTranslations("dashboardPage"); diff --git a/frontend/src/components/RecentPayments.tsx b/frontend/src/components/RecentPayments.tsx index 97424be1..95e6de25 100644 --- a/frontend/src/components/RecentPayments.tsx +++ b/frontend/src/components/RecentPayments.tsx @@ -555,7 +555,7 @@ export default function RecentPayments({
- )))} + ))}
diff --git a/frontend/src/components/WalletSelector.tsx b/frontend/src/components/WalletSelector.tsx index 8cca116e..8b491bac 100644 --- a/frontend/src/components/WalletSelector.tsx +++ b/frontend/src/components/WalletSelector.tsx @@ -41,6 +41,51 @@ const SUBTITLES: Record = { walletconnect: "Mobile & desktop wallets", }; +function getFriendlyErrorMessage(id: string, err: unknown, t: (key: string) => string) { + const message = err instanceof Error ? err.message : String(err ?? ""); + const normalized = message.toLowerCase(); + + if ( + normalized.includes("4001") || + normalized.includes("reject") || + normalized.includes("declin") || + normalized.includes("denied") || + normalized.includes("canceled") || + normalized.includes("cancelled") + ) { + return t("userRejected"); + } + + if ( + normalized.includes("project_id") || + normalized.includes("project id") || + normalized.includes("walletconnect is disabled") || + normalized.includes("pairing uri") + ) { + return t("walletConnectUnavailable"); + } + + if ( + normalized.includes("not installed") || + normalized.includes("not found") || + normalized.includes("extension") + ) { + return t("extensionNotFound"); + } + + if ( + normalized.includes("no stellar accounts") || + normalized.includes("public key") || + normalized.includes("session not established") + ) { + return t("noAccountFound"); + } + + return id === "walletconnect" + ? t("walletConnectFailed") + : t("connectionFailed"); +} + export default function WalletSelector({ networkPassphrase, onConnected }: WalletSelectorProps) { const t = useTranslations("walletSelector"); const { providers, activeProvider, selectProvider } = useWallet(); @@ -65,51 +110,6 @@ export default function WalletSelector({ networkPassphrase, onConnected }: Walle return () => { cancelled = true; }; }, [providers]); - function getFriendlyErrorMessage(id: string, err: unknown) { - const message = err instanceof Error ? err.message : String(err ?? ""); - const normalized = message.toLowerCase(); - - if ( - normalized.includes("4001") || - normalized.includes("reject") || - normalized.includes("declin") || - normalized.includes("denied") || - normalized.includes("canceled") || - normalized.includes("cancelled") - ) { - return t("userRejected"); - } - - if ( - normalized.includes("project_id") || - normalized.includes("project id") || - normalized.includes("walletconnect is disabled") || - normalized.includes("pairing uri") - ) { - return t("walletConnectUnavailable"); - } - - if ( - normalized.includes("not installed") || - normalized.includes("not found") || - normalized.includes("extension") - ) { - return t("extensionNotFound"); - } - - if ( - normalized.includes("no stellar accounts") || - normalized.includes("public key") || - normalized.includes("session not established") - ) { - return t("noAccountFound"); - } - - return id === "walletconnect" - ? t("walletConnectFailed") - : t("connectionFailed"); - } - const handleSelect = useCallback(async (id: string) => { setConnectError(null); setWcError(null); @@ -141,7 +141,7 @@ export default function WalletSelector({ networkPassphrase, onConnected }: Walle selectProvider(id); onConnected(); } catch (err) { - const msg = getFriendlyErrorMessage(id, err); + const msg = getFriendlyErrorMessage(id, err, t); if (id === "walletconnect") { setWcError(msg); setWcUri(null); @@ -220,7 +220,6 @@ export default function WalletSelector({ networkPassphrase, onConnected }: Walle
{providerButtons}
-
{/* WalletConnect QR */} {wcUri && (