"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import Link from "next/link"; import { useRouter, useSearchParams } from "next/navigation"; import type { User } from "@supabase/supabase-js"; import { User as UserIcon, Shield, Fingerprint, Bot, RefreshCw, LogOut, ChevronLeft, Copy, CheckCircle2, UserCheck, Mail, Hash, LogIn, Clock, Crown, ExternalLink, Trophy, Coins, TrendingUp, Info, Wallet, Zap, Minus, ShieldCheck, BarChart3, Sparkles, ChevronRight, Loader2, CreditCard, } from "lucide-react"; import { getSupabaseBrowserClient, hasSupabasePublicEnv, } from "@/lib/supabase/client"; import { markAnalyticsOnce, trackAppEvent } from "@/lib/app-analytics"; import { useI18n } from "@/hooks/useI18n"; import type { AuthMeResponse } from "./types"; import { TELEGRAM_BOT_URL, TELEGRAM_GROUP_URL, TELEGRAM_TOPICS_GROUP_URL, WALLETCONNECT_PROJECT_ID, } from "./constants"; import { InfoRow, PlusIcon } from "./AccountInfoRow"; import { AccountFeedbackPanel } from "./AccountFeedbackPanel"; import { TurnstileWidget } from "@/components/security/TurnstileWidget"; import { chainIdToDisplayName, clearStoredPaymentRecovery, formatTime, parseSubscriptionExpiry, shortAddress, } from "./formatters"; import { createAccountCopy } from "./account-copy"; import { resetWalletConnectProvider } from "./wallet"; import { useAccountPayment } from "./useAccountPayment"; import { buildTrialValueReplaySummary, readTrialValueReplay, } from "@/lib/trial-value-replay"; import { getTurnstileTokenForAction } from "@/lib/turnstile-client"; // --- Main Component --- function pointSourceLabel(source?: string, isEn = false) { const key = String(source || "").trim().toLowerCase(); if (key === "feedback_reward") return isEn ? "Feedback reward" : "反馈奖励"; if (key === "ops_manual_grant") return isEn ? "Ops manual grant" : "后台补发"; if (key === "paid_referral") return isEn ? "Paid referral" : "有效付费邀请"; if (key === "growth_milestone_reward") return isEn ? "Growth reward" : "增长奖励"; if (key === "points_redemption") return isEn ? "Payment redemption" : "支付抵扣"; if (key === "ops_subscription_deduction") return isEn ? "Ops deduction" : "后台订阅扣分"; return key || (isEn ? "Unknown source" : "未知来源"); } export function AccountCenter() { const router = useRouter(); const searchParams = useSearchParams(); const { locale } = useI18n(); const isEn = locale === "en-US"; const copy = useMemo(() => createAccountCopy(isEn), [isEn]); // ── UI-only state ────────────────────────────────────── const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [copied, setCopied] = useState(false); const [showSecondarySections, setShowSecondarySections] = useState(false); const [trialValueReplay, setTrialValueReplay] = useState(() => readTrialValueReplay()); // ── Shared state (declared in component, written by hook via setters) ─ const [usePoints, setUsePoints] = useState(true); const [errorText, setErrorText] = useState(""); const [updatedAt, setUpdatedAt] = useState(""); const [user, setUser] = useState(null); const [backend, setBackend] = useState(null); const [referralCodeInput, setReferralCodeInput] = useState(""); const [referralApplying, setReferralApplying] = useState(false); const [paymentTurnstileToken, setPaymentTurnstileToken] = useState(""); const [paymentTurnstileResetKey, setPaymentTurnstileResetKey] = useState(0); const supabaseReady = hasSupabasePublicEnv(); const walletConnectEnabled = Boolean(WALLETCONNECT_PROJECT_ID); const resetPaymentTurnstile = useCallback(() => { setPaymentTurnstileToken(""); setPaymentTurnstileResetKey((value) => value + 1); }, []); const getPaymentTurnstileToken = useCallback( ( action: "payment_intent_create" | "payment_tx_submit", options?: { optional?: boolean }, ) => { if (options?.optional && !paymentTurnstileToken) return undefined; return getTurnstileTokenForAction(paymentTurnstileToken, action); }, [paymentTurnstileToken], ); // ── Hook ──────────────────────────────────────────────── const { // State from usePaymentState paymentBusy, paymentInfo, paymentError, lastIntentId, lastPaymentStartedAt, telegramBindOpening, telegramBindUrl, telegramBindCommand, manualPayment, manualTxHash, txValidation, paymentMethodTab, clearPaymentMessages, clearPaymentState, // Setters setPaymentBusy, setPaymentInfo, setPaymentError, setLastIntentId, setLastTxHash, setLastPaymentStartedAt, setTelegramBindOpening, setPaymentMethodTab, setManualPayment, setManualTxHash, setTxValidation, // Additional state paymentConfig, boundWallets, walletAddress, selectedPlanCode, selectedPaymentChainId, selectedTokenAddress, selectedWallet, providerMode, injectedProviderOptions, selectedInjectedProviderKey, reconcileBusy, // Shared setters setSelectedTokenAddress, setSelectedPaymentChainId, setSelectedPlanCode, setSelectedWallet, setSelectedInjectedProviderKey, setProviderMode, // Derived values authUserId, authIsAuthenticated, paymentReadyForRecovery, hasRecentPaymentRecovery, allowedPaymentHosts, currentPaymentHost, paymentHostAllowed, selectedPaymentToken, selectedTokenLabel, availableTokenList, availableChainList, selectedPaymentChain, effectivePlanList, resolvedSelectedTokenAddress, paymentReceiverAddress, paymentWalletLabel, totalPoints, billing, // Callbacks loadSnapshot, loadPaymentSnapshot, connectAndBindWallet, handleUnbindWallet, createManualPaymentIntent, submitManualPaymentTx, validateTxHash, createTelegramBotBindCommand, openTelegramBotBindLink, } = useAccountPayment({ isEn, supabaseReady, walletConnectEnabled, copy, backend, user, setUser, setBackend, setErrorText, setUpdatedAt, usePoints, setUsePoints, getPaymentTurnstileToken, resetPaymentTurnstile, }); // ── Auth analytics effect ────────────────────────────── useEffect(() => { if (!authIsAuthenticated || !authUserId) return; const actorKey = authUserId.toLowerCase(); const subscriptionPlanCode = String(backend?.subscription_plan_code || "").trim(); const subscriptionSource = String(backend?.subscription_source || "").trim(); const trialSubscription = Boolean( backend?.subscription_is_trial === true || subscriptionPlanCode.toLowerCase().includes("trial") || subscriptionSource.toLowerCase().includes("trial"), ); if (markAnalyticsOnce(`signup_completed:${actorKey}`, "local")) { trackAppEvent("signup_completed", { entry: "account_center", user_id: authUserId, }); } if (markAnalyticsOnce(`signup_success:${actorKey}`, "local")) { trackAppEvent("signup_success", { entry: "account_center", user_id: authUserId, }); } if (markAnalyticsOnce(`dashboard_active:${actorKey}`, "session")) { trackAppEvent("dashboard_active", { entry: "account_center", user_id: authUserId, }); } if (trialSubscription && markAnalyticsOnce(`trial_created:${actorKey}`, "local")) { trackAppEvent("trial_created", { entry: "account_center", user_id: authUserId, subscription_plan_code: subscriptionPlanCode || null, subscription_source: subscriptionSource || null, subscription_expires_at: backend?.subscription_expires_at || null, subscription_is_trial: backend?.subscription_is_trial === true, }); } }, [ authIsAuthenticated, authUserId, backend?.subscription_expires_at, backend?.subscription_is_trial, backend?.subscription_plan_code, backend?.subscription_source, ]); // ── Idle callback effect ────────────────────────────── useEffect(() => { let canceled = false; let timeoutId: number | null = null; let idleId: number | null = null; const win = typeof window !== "undefined" ? (window as any) : null; const reveal = () => { if (!canceled) { setShowSecondarySections(true); } }; if (win && typeof win.requestIdleCallback === "function") { idleId = win.requestIdleCallback(reveal, { timeout: 320 }); } else if (typeof window !== "undefined") { timeoutId = window.setTimeout(reveal, 140); } else { setShowSecondarySections(true); } return () => { canceled = true; if ( win && idleId != null && typeof win.cancelIdleCallback === "function" ) { win.cancelIdleCallback(idleId); } if (timeoutId != null && typeof window !== "undefined") { window.clearTimeout(timeoutId); } }; }, []); // ── Initial load effect ──────────────────────────────── useEffect(() => { let cancelled = false; const run = async () => { setLoading(true); await loadSnapshot(); if (!cancelled) setLoading(false); }; void run(); return () => { cancelled = true; }; }, [loadSnapshot]); // ── Refresh ──────────────────────────────────────────── const onRefresh = async () => { setRefreshing(true); await loadSnapshot(); await loadPaymentSnapshot(); setRefreshing(false); }; // ── Sign out ──────────────────────────────────────────── const onSignOut = async () => { clearPaymentState(); clearStoredPaymentRecovery(); await resetWalletConnectProvider(); if (supabaseReady) { try { await getSupabaseBrowserClient().auth.signOut(); } catch { // ignore } } router.replace("/"); }; // ── Derived display values ────────────────────────────── const userId = backend?.user_id || user?.id || ""; const isAuthenticated = Boolean(userId); const email = backend?.email || user?.email || ""; const displayName = String(user?.user_metadata?.full_name || "").trim() || (email ? String(email).split("@")[0] : "") || copy.guestUser; const initials = (displayName.slice(0, 2) || "PW").toUpperCase(); const joinedAt = formatTime(user?.created_at, locale); const backendAuthenticated = backend?.authenticated === true; const localAuthenticated = Boolean(user?.id); const isSubscriptionUnknown = Boolean( localAuthenticated && (!backend || backend.subscription_active == null || backend.authenticated === false), ); const isSubscribed = backend?.subscription_active === true; const subscriptionSource = String(backend?.subscription_source || "").trim(); const isTrialSubscription = Boolean( backend?.subscription_is_trial === true || String(backend?.subscription_plan_code || "").toLowerCase().includes("trial") || subscriptionSource.toLowerCase().includes("trial"), ); const subscriptionStatusLabel = isSubscribed ? isTrialSubscription ? copy.trialBadge : copy.proMember : isSubscriptionUnknown ? copy.subscriptionChecking : isEn ? "UNSUBSCRIBED" : "未订阅"; const planCode = String(backend?.subscription_plan_code || "").trim(); const currentExpiryRaw = String( backend?.subscription_expires_at || user?.user_metadata?.pro_expiry || "", ).trim(); const totalExpiryRaw = String( backend?.subscription_total_expires_at || backend?.subscription_expires_at || user?.user_metadata?.pro_expiry || "", ).trim(); const queuedExtensionDays = Math.max( 0, Number(backend?.subscription_queued_days || 0), ); const hasQueuedExtension = Boolean( isSubscribed && queuedExtensionDays > 0, ); const canAccessPaidTelegramGroup = Boolean(isSubscribed && !isTrialSubscription); const hasTelegramPanel = Boolean(isTrialSubscription || canAccessPaidTelegramGroup); const telegramBound = Number(backend?.telegram_pricing?.telegram_id || 0) > 0; const displayExpiryRaw = isSubscribed ? totalExpiryRaw : currentExpiryRaw; const reminderExpiryRaw = isSubscribed ? totalExpiryRaw : currentExpiryRaw || totalExpiryRaw; const expiryInfo = parseSubscriptionExpiry(reminderExpiryRaw); const expiryFormatted = formatTime(displayExpiryRaw, locale); const currentExpiryFormatted = formatTime(currentExpiryRaw, locale); const totalExpiryFormatted = formatTime(totalExpiryRaw, locale); const proExpiry = isSubscribed ? expiryFormatted !== "--" ? expiryFormatted : displayExpiryRaw || copy.proPendingSync : isSubscriptionUnknown ? copy.subscriptionUnknown : copy.noProSubscription; const showExpiringSoon = Boolean( isSubscribed && !hasQueuedExtension && expiryInfo && !expiryInfo.expired && expiryInfo.daysLeft <= 3, ); const showExpiredReminder = Boolean( !isSubscribed && expiryInfo && expiryInfo.expired, ); const paymentFeatureReady = paymentReadyForRecovery; const canTrialUpgrade = Boolean(isSubscribed && isTrialSubscription); const canStartPayment = Boolean( paymentFeatureReady && (canTrialUpgrade || !isSubscribed || showExpiringSoon || showExpiredReminder), ); const subscriptionStatusTitle = showExpiredReminder ? copy.proExpiredTitle : showExpiringSoon ? copy.proEndsSoonTitle : ""; const subscriptionStatusBody = showExpiredReminder ? copy.proExpiredBody : showExpiringSoon ? copy.proEndsSoonBody : ""; const subscriptionStatusMeta = expiryInfo && (showExpiringSoon || showExpiredReminder) ? `${formatTime(expiryInfo.raw, locale)} · ${copy.daysLeft.replace("{days}", String(Math.max(expiryInfo.daysLeft, 0)))}` : ""; const queuedExtensionSummary = hasQueuedExtension ? copy.queuedExtensionSummary .replace("{current}", currentExpiryFormatted) .replace("{days}", String(queuedExtensionDays)) .replace("{total}", totalExpiryFormatted) : ""; const expiryLabel = hasQueuedExtension ? copy.accessUntil : copy.renewalDate; const displayPlanList = effectivePlanList.length ? effectivePlanList : [ { plan_code: "pro_monthly", plan_id: 101, amount_usdc: "29.9", duration_days: 30 }, { plan_code: "pro_quarterly", plan_id: 102, amount_usdc: "79.9", duration_days: 90 }, ]; const manualTxHashReady = /^0x[a-fA-F0-9]{64}$/.test(manualTxHash.trim()); const trialValueReplaySummary = useMemo( () => buildTrialValueReplaySummary(trialValueReplay, { isEn, trialExpiresAt: displayExpiryRaw, }), [displayExpiryRaw, isEn, trialValueReplay], ); const referral = backend?.referral; const referralCode = String(referral?.code || "").trim(); const appliedReferralCode = String(referral?.applied_code || "").trim(); const canApplyReferralCode = Boolean( isAuthenticated && !isSubscribed && !appliedReferralCode && referralCodeInput.trim(), ); const focusPaymentManagement = useCallback(() => { trackAppEvent("paywall_viewed", { entry: "account_center", user_state: isAuthenticated ? "logged_in" : "guest", expired: showExpiredReminder, expiring_soon: showExpiringSoon, subscription_plan_code: planCode || null, }); const paymentSection = document.getElementById("payment-management"); paymentSection?.scrollIntoView({ behavior: "smooth", block: "start" }); }, [ isAuthenticated, planCode, showExpiredReminder, showExpiringSoon, ]); useEffect(() => { if (searchParams.get("checkout") === "1") { window.setTimeout(focusPaymentManagement, 0); } }, [focusPaymentManagement, searchParams]); useEffect(() => { if (!isTrialSubscription) return; setTrialValueReplay(readTrialValueReplay()); }, [authUserId, isTrialSubscription]); const openTrialValueReplayCheckout = useCallback(() => { trackAppEvent("paywall_feature_clicked", { entry: "account_center", feature: "trial_value_replay_upgrade", user_id: authUserId || null, replay_cities: trialValueReplay.citiesViewed.length, replay_terminal_visits: trialValueReplay.terminalVisits, replay_rows_available: trialValueReplay.rowsAvailableMax, subscription_plan_code: planCode || null, }); focusPaymentManagement(); }, [authUserId, focusPaymentManagement, planCode, trialValueReplay]); // ── Referral points display ──────────────────────────── const referralRewardPointsRaw = Number(referral?.reward_points ?? 3500); const referralRewardPoints = Number.isFinite(referralRewardPointsRaw) ? Math.max(0, referralRewardPointsRaw) : 3500; const monthlyReferralCountRaw = Number(referral?.monthly_reward_count ?? 0); const monthlyReferralCount = Number.isFinite(monthlyReferralCountRaw) ? Math.max(0, monthlyReferralCountRaw) : 0; const monthlyReferralLimitRaw = Number(referral?.monthly_reward_limit ?? 10); const monthlyReferralLimit = Number.isFinite(monthlyReferralLimitRaw) ? Math.max(0, monthlyReferralLimitRaw) : 10; const monthlyReferralPointsRaw = Number( referral?.monthly_reward_points ?? monthlyReferralCount * referralRewardPoints, ); const monthlyReferralPoints = Number.isFinite(monthlyReferralPointsRaw) ? Math.max(0, monthlyReferralPointsRaw) : 0; const monthlyReferralPointsLimitRaw = Number( referral?.monthly_reward_points_limit ?? monthlyReferralLimit * referralRewardPoints, ); const monthlyReferralPointsLimit = Number.isFinite(monthlyReferralPointsLimitRaw) ? Math.max(0, monthlyReferralPointsLimitRaw) : monthlyReferralLimit * referralRewardPoints; const pointsLedger = backend?.points_ledger; const pointSourceRows = Object.entries(pointsLedger?.by_source ?? {}); const recentPointEvents = pointsLedger?.recent ?? []; // ── Telegram bind command ────────────────────────────── const bindCommand = telegramBindCommand || copy.telegramBindCommandPlaceholder; // ── Copy handler ────────────────────────────────────── const handleCopy = (text: string) => { navigator.clipboard.writeText(text).then(() => { setCopied(true); window.setTimeout(() => setCopied(false), 2000); }); }; const handleCopyTelegramBindCommand = async () => { if (!isAuthenticated || telegramBindOpening) return; const command = await createTelegramBotBindCommand(); if (!command) return; handleCopy(command); }; const applyReferralCode = useCallback(async () => { const code = referralCodeInput.trim(); if (!code || referralApplying) return; setReferralApplying(true); setPaymentError(""); setPaymentInfo(""); try { const headers: Record = { "Content-Type": "application/json", }; if (supabaseReady) { const { data: { session }, } = await getSupabaseBrowserClient().auth.getSession(); const token = String(session?.access_token || "").trim(); if (token) headers.Authorization = `Bearer ${token}`; } const res = await fetch("/api/auth/referral/apply", { method: "POST", headers, body: JSON.stringify({ code }), }); if (!res.ok) { const raw = (await res.text()).slice(0, 240); throw new Error(raw || copy.referralApplyFailed); } setPaymentInfo(copy.referralApplied); setReferralCodeInput(""); await loadSnapshot(); await loadPaymentSnapshot(); } catch (error) { setPaymentError( error instanceof Error ? error.message : copy.referralApplyFailed, ); } finally { setReferralApplying(false); } }, [ copy.referralApplied, copy.referralApplyFailed, loadPaymentSnapshot, loadSnapshot, referralApplying, referralCodeInput, setPaymentError, setPaymentInfo, supabaseReady, ]); // ── Render ──────────────────────────────────────────── if (loading && !refreshing) { return (

{copy.loadingAccount}

); } return (
{/* Header */}

{copy.accountCenter}

{canStartPayment && ( )} {isAuthenticated ? ( ) : ( {copy.signIn} )}
{(showExpiringSoon || showExpiredReminder) && (
{subscriptionStatusTitle}

{subscriptionStatusBody}

{subscriptionStatusMeta ? (

{subscriptionStatusMeta}

) : null} {billing.canRedeem ? (

当前可用 {billing.pointsUsed} 积分抵扣 $ {billing.discountAmount.toFixed(2)}, 续费时会自动生效。

) : null}
)} {isTrialSubscription && canStartPayment && (
{isEn ? "Trial value replay" : "试用价值回放"} {trialValueReplaySummary.hasUsageEvidence ? ( {isEn ? "Based on your trial" : "基于你的试用"} ) : null}

{trialValueReplaySummary.headline}

{trialValueReplaySummary.bullets.map((bullet) => (
{bullet}
))}
)} {/* User Card */}
{initials}

{displayName}

{subscriptionStatusLabel}

{email || copy.guestUser}

{" "} {userId ? `${userId.substring(0, 12)}...` : "--"}
{" "} {copy.joinedAt}: {joinedAt}

{copy.totalPoints}

{" "} {totalPoints.toLocaleString()}

{copy.weeklyPoints}

{" "} {monthlyReferralCount.toLocaleString()}

{copy.weeklyRank}

{" "} {monthlyReferralCount}/{monthlyReferralLimit}

{/* Referral rewards */} {showSecondarySections ? (

{" "} {copy.weeklyRewards}

{" "} {copy.referralRewardHint} +{referralRewardPoints.toLocaleString()}
{" "} {copy.weeklyPoints} {monthlyReferralCount}/{monthlyReferralLimit}
{" "} {copy.totalPoints} {monthlyReferralPoints.toLocaleString()}/{monthlyReferralPointsLimit.toLocaleString()}

{copy.pointsRule}

) : (
)}

{isEn ? "Point Sources" : "积分来源"}

{isEn ? "Current balance" : "当前余额"} {Number(pointsLedger?.balance ?? totalPoints).toLocaleString()}
{pointSourceRows.length === 0 && recentPointEvents.length === 0 ? (

{copy.pointsRule}

) : (
{pointSourceRows.map(([source, item]) => (
{pointSourceLabel(source, isEn)}
{Number(item?.points ?? 0).toLocaleString()}
{Number(item?.count ?? 0).toLocaleString()} {isEn ? "events" : "笔记录"} · {source}
))}
{isEn ? "Recent point ledger" : "最近积分流水"}
{recentPointEvents.slice(0, 5).map((event, index) => (
{pointSourceLabel(event.source, isEn)}
{event.reference_type || "ledger"} · {event.created_at ? formatTime(event.created_at, locale) : "--"}
= 0 ? "text-emerald-600" : "text-red-600"}`}> {Number(event.delta_points ?? 0) >= 0 ? "+" : ""} {Number(event.delta_points ?? 0).toLocaleString()}
))}
)}
{/* Subscription Info & Paywall */}

{copy.membershipDetails}

{copy.identityStatus}

{queuedExtensionSummary ? (

{queuedExtensionSummary}

) : null}
{/* Telegram Bot Section & Payment Details */} {showSecondarySections ? (
{isTrialSubscription && (

{copy.telegramBind}

{copy.trialPaidGroupLocked}

)} {canAccessPaidTelegramGroup && (

{copy.telegramBind}

{copy.telegramHint}

{TELEGRAM_TOPICS_GROUP_URL && TELEGRAM_TOPICS_GROUP_URL !== TELEGRAM_GROUP_URL && telegramBound ? ( {copy.telegramTopicsGroupLink} ) : null} {TELEGRAM_GROUP_URL && telegramBound ? ( {copy.telegramGroupLink} ) : null}
{bindCommand}

{copy.telegramFallbackHint}

{copy.paymentManualSupport}
)} {/* Payment Details / Wallet Management */}

{copy.paymentMgmt}

{paymentError ? (
{paymentError}
) : null} {!paymentError && paymentInfo ? (
{paymentInfo} {telegramBindUrl ? ( {telegramBindUrl} ) : null}
) : null} {!paymentHostAllowed ? (
{copy.paymentHostBlocked.replace( "{host}", allowedPaymentHosts[0] || "polyweather.top", )}
) : null}

{copy.proPlan}

{displayPlanList.map((plan) => { const code = String(plan.plan_code || ""); const active = code === selectedPlanCode; const isQuarterly = code === "pro_quarterly"; return ( ); })}
{appliedReferralCode && selectedPlanCode === "pro_monthly" ? (

{copy.referralDiscountHint}

) : null}

{copy.referralTitle}

{copy.referralInviteLimit}

{copy.referralMyCode}

{referralCode || "--"} {referralCode ? ( ) : null}

{copy.referralRewardHint}

{copy.referralApplyLabel}

{appliedReferralCode ? (
{appliedReferralCode}
) : (
setReferralCodeInput(event.target.value)} placeholder={copy.referralApplyPlaceholder} className="min-w-0 flex-1 rounded-xl border border-slate-300 bg-white px-3 py-2 text-xs text-slate-950 outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20" />
)}

{copy.referralDiscountHint}

{copy.paymentGuardHint}

{availableChainList.length > 1 && (

{copy.paymentNetwork}

{availableChainList.map((chain) => { const active = chain.chain_id === selectedPaymentChainId; return ( ); })}
)} {availableTokenList.length > 0 && (

{copy.paymentToken}

{availableTokenList.map((token) => { const active = token.address === (resolvedSelectedTokenAddress || token.address); return ( ); })}
)} {/* Payment Method Tabs */}

{copy.paymentMethodLabel}

{paymentMethodTab === "wallet" ? (

{copy.paymentWalletDesc}

{copy.paymentGasWarning}
{boundWallets.length ? (
{boundWallets.map((w) => (
{shortAddress(w.address)} {w.is_primary && ( {copy.primary} )}
{chainIdToDisplayName(w.chain_id)}
))}
) : (

{copy.noWallet}

)}
{injectedProviderOptions.length > 1 && ( )} {!walletConnectEnabled && (

{copy.walletConnectMissing} NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID

)}
) : (

{copy.paymentManualDesc}

{copy.paymentManualTitle}

{copy.paymentManualHint}

{manualPayment ? (

{copy.paymentAmount}

{manualPayment.amount_usdc}{" "} {manualPayment.token_symbol || selectedTokenLabel}

{copy.paymentReceiverLabel}

{ manualPayment.receiver_address }

Tx Hash

{ setManualTxHash( event.target.value, ); void validateTxHash( manualPayment.intent_id || lastIntentId || "", event.target.value, ); }} placeholder="0x..." className="mt-1 w-full rounded-xl border border-slate-300 bg-white px-3 py-2 font-mono text-xs text-slate-950 outline-none focus:border-emerald-500 focus:ring-2 focus:ring-emerald-500/20" /> {txValidation.loading ? (

{copy.verifying}

) : txValidation.checked && txValidation.valid ? (

{copy.verifyAddressMatch}

) : txValidation.checked && txValidation.valid === false ? (

{txValidation.reason === "tx_not_mined" ? copy.verifyTxNotMined : txValidation.reason === "receiver_mismatch" ? copy .verifyAddressMismatch : txValidation.reason === "amount_insufficient" ? copy .verifyAmountLow : txValidation.reason === "direct_self_transfer" ? copy .verifySelfTransfer : txValidation.reason === "tx_reverted" ? copy .verifyTxReverted : txValidation.detail || copy.verifyFailed + (txValidation.reason || copy .verifyUnknown)}

) : null}
) : null}
)}
) : (
)}
); }