/**
* 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}
)}
>
);
}