import React, { memo, useCallback } from '../../lib/teact/teact'; import { getActions } from '../../global'; import type { FC } from '../../lib/teact/teact'; import type { FormEditDispatch } from '../../hooks/reducers/usePaymentReducer'; import type { LangCode, Price } from '../../types'; import type { ApiChat, ApiInvoice, ApiPaymentCredentials } from '../../api/types'; import { PaymentStep } from '../../types'; import { getWebDocumentHash } from '../../global/helpers'; import { formatCurrency } from '../../util/formatCurrency'; import buildClassName from '../../util/buildClassName'; import renderText from '../common/helpers/renderText'; import useLang from '../../hooks/useLang'; import useMedia from '../../hooks/useMedia'; import Checkbox from '../ui/Checkbox'; import Skeleton from '../ui/Skeleton'; import SafeLink from '../common/SafeLink'; import ListItem from '../ui/ListItem'; import styles from './Checkout.module.scss'; export type OwnProps = { chat?: ApiChat; invoice?: ApiInvoice; checkoutInfo?: { paymentMethod?: string; paymentProvider?: string; shippingAddress?: string; name?: string; phone?: string; shippingMethod?: string; }; prices?: Price[]; totalPrice?: number; needAddress?: boolean; hasShippingOptions?: boolean; tipAmount?: number; shippingPrices?: Price[]; currency: string; isTosAccepted?: boolean; dispatch?: FormEditDispatch; onAcceptTos?: (isAccepted: boolean) => void; savedCredentials?: ApiPaymentCredentials[]; }; const Checkout: FC = ({ chat, invoice, prices, shippingPrices, checkoutInfo, currency, totalPrice, isTosAccepted, dispatch, onAcceptTos, tipAmount, needAddress, hasShippingOptions, savedCredentials, }) => { const { setPaymentStep } = getActions(); const lang = useLang(); const isInteractive = Boolean(dispatch); const { photo, title, text, isRecurring, recurringTermsUrl, suggestedTipAmounts, maxTipAmount, } = invoice || {}; const { paymentMethod, paymentProvider, shippingAddress, name, phone, shippingMethod, } = (checkoutInfo || {}); const photoUrl = useMedia(getWebDocumentHash(photo)); const handleTipsClick = useCallback((tips: number) => { dispatch!({ type: 'setTipAmount', payload: maxTipAmount ? Math.min(tips, maxTipAmount) : tips }); }, [dispatch, maxTipAmount]); const handlePaymentMethodClick = useCallback(() => { setPaymentStep({ step: savedCredentials?.length ? PaymentStep.SavedPayments : PaymentStep.PaymentInfo }); }, [savedCredentials?.length, setPaymentStep]); const handleShippingAddressClick = useCallback(() => { setPaymentStep({ step: PaymentStep.ShippingInfo }); }, [setPaymentStep]); const handleShippingMethodClick = useCallback(() => { setPaymentStep({ step: PaymentStep.Shipping }); }, [setPaymentStep]); function renderTips() { return ( <>
{title}
{formatCurrency(tipAmount!, currency, lang.code)}
{suggestedTipAmounts!.map((tip) => (
handleTipsClick(tip === tipAmount ? 0 : tip) : undefined} > {formatCurrency(tip, currency, lang.code, true)}
))}
); } function renderTosLink(url: string, isRtl?: boolean) { const langString = lang('PaymentCheckoutAcceptRecurrent', chat?.title); const langStringSplit = langString.split('*'); return ( <> {langStringSplit[0]} {langStringSplit.slice(2)} ); } function renderTos(url: string) { return ( ); } return (
{photoUrl && } {!photoUrl && photo && ( )}
{title}
{text &&
{renderText(text, ['br', 'links', 'emoji'])}
}
{prices && prices.map((item) => ( renderPaymentItem(lang.code, item.label, item.amount, currency) ))} {shippingPrices && shippingPrices.map((item) => ( renderPaymentItem(lang.code, item.label, item.amount, currency) ))} {suggestedTipAmounts && suggestedTipAmounts.length > 0 && renderTips()} {totalPrice !== undefined && ( renderPaymentItem(lang.code, lang('Checkout.TotalAmount'), totalPrice, currency, true) )}
{renderCheckoutItem({ title: paymentMethod || savedCredentials?.[0].title, label: lang('PaymentCheckoutMethod'), icon: 'card', onClick: isInteractive ? handlePaymentMethodClick : undefined, })} {paymentProvider && renderCheckoutItem({ title: paymentProvider, label: lang('PaymentCheckoutProvider'), customIcon: buildClassName(styles.provider, styles[paymentProvider.toLowerCase()]), })} {(needAddress || !isInteractive) && renderCheckoutItem({ title: shippingAddress, label: lang('PaymentShippingAddress'), icon: 'location', onClick: isInteractive ? handleShippingAddressClick : undefined, })} {name && renderCheckoutItem({ title: name, label: lang('PaymentCheckoutName'), icon: 'user', })} {phone && renderCheckoutItem({ title: phone, label: lang('PaymentCheckoutPhoneNumber'), icon: 'phone', })} {(hasShippingOptions || !isInteractive) && renderCheckoutItem({ title: shippingMethod, label: lang('PaymentCheckoutShippingMethod'), icon: 'truck', onClick: isInteractive ? handleShippingMethodClick : undefined, })} {isRecurring && renderTos(recurringTermsUrl!)}
); }; export default memo(Checkout); function renderPaymentItem( langCode: LangCode | undefined, title: string, value: number, currency: string, main = false, ) { return (
{title}
{formatCurrency(value, currency, langCode)}
); } function renderCheckoutItem({ title, label, icon, customIcon, onClick, }: { title : string | undefined; label: string | undefined; icon?: string; onClick?: NoneToVoidFunction; customIcon?: string; }) { return ( {customIcon && }
{title || label}
{title && label !== title && (

{label}

)}
); }