/** * TotalSection Component * * Displays total amount, USD equivalent, exchange rate details, * and quote information for dynamic pricing. */ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context'; import type { TPaymentCurrency } from '@blocklet/payment-types'; import { Box, Skeleton, Stack, Tooltip, Typography } from '@mui/material'; import PaymentAmount from '../amount'; import QuoteDetailsPanel from '../../components/quote-details-panel'; import type { SlippageConfigValue } from '../../components/slippage-config'; export interface RateInfo { exchangeRate: string | null; baseCurrency: string; providerName?: string | null; providerId?: string | null; timestampMs?: number | null; } export interface QuoteDetailRow { label: string; value: string | React.ReactNode; isSlippage?: boolean; } export interface TotalSectionProps { totalAmountText: string; totalUsdDisplay: string | null; currency: TPaymentCurrency; hasDynamicPricing: boolean; rateDisplay: string | null; rateInfo: RateInfo; quoteDetailRows: QuoteDetailRow[]; currentSlippagePercent: number; slippageConfig?: SlippageConfigValue; isPriceLocked: boolean; isSubscription: boolean; completed?: boolean; onSlippageChange?: (slippageConfig: SlippageConfigValue) => void; isStripePayment?: boolean; thenInfo?: string; isRateLoading?: boolean; // Loading state for skeleton display during currency switch } export default function TotalSection({ totalAmountText, totalUsdDisplay, currency, hasDynamicPricing, rateDisplay, rateInfo, quoteDetailRows, currentSlippagePercent, slippageConfig = undefined, isPriceLocked, isSubscription, completed = false, onSlippageChange = undefined, isStripePayment = false, thenInfo = '', isRateLoading = false, }: TotalSectionProps) { const { t } = useLocaleContext(); return ( <> {t('common.total')} {isRateLoading ? ( ) : ( )} {/* USD equivalent display - hide for Stripe payments since base_amount is already USD */} {/* No skeleton for USD - it's based on base_amount which doesn't change */} {hasDynamicPricing && !isStripePayment && !isRateLoading && (totalUsdDisplay ? ( ≈ ${totalUsdDisplay} ) : ( ≈ — ))} {/* Quote details panel for dynamic pricing - hide for Stripe payments since no exchange rate conversion needed */} {/* Show panel if hasDynamicPricing is true, even without rateDisplay (for metered subscriptions waiting for first usage) */} {hasDynamicPricing && !isStripePayment && ( )} {/* Lock expired warning removed - per Final Freeze design, Quote doesn't expire by time */} {thenInfo && ( {t('common.nextCharge')} {thenInfo} )} ); }