import React, { useState, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { List, ListItem, Alert, Chip, ListItemAvatar, ListItemText, ListItemIcon, Divider, Grid, Collapse, useTheme, Typography, IconButton, } from '@mui/material'; import Countdown, { CountdownRenderProps, zeroPad } from 'react-countdown'; import RobotAvatar from '../../components/RobotAvatar'; import currencies from '../../../static/assets/currencies.json'; import { AccessTime, Numbers, PriceChange, Payments, Article, HourglassTop, ExpandLess, ExpandMore, } from '@mui/icons-material'; import { PaymentStringAsIcons } from '../../components/PaymentMethods'; import { FlagWithProps, SendReceiveIcon } from '../Icons'; import LinearDeterminate from './LinearDeterminate'; import { Order, Info } from '../../models'; import { statusBadgeColor, pn, amountToString, computeSats } from '../../utils'; import TakeButton from './TakeButton'; interface OrderDetailsProps { order: Order; setOrder: (state: Order) => void; info: Info; baseUrl: string; hasRobot: boolean; } const OrderDetails = ({ order, info, setOrder, baseUrl, hasRobot, }: OrderDetailsProps): JSX.Element => { const { t } = useTranslation(); const theme = useTheme(); const currencyCode: string = currencies[`${order.currency}`]; const [showSatsDetails, setShowSatsDetails] = useState(false); const amountString = useMemo(() => { // precision to 8 decimal if currency is BTC otherwise 4 decimals if (order.currency == 1000) { return ( amountToString( order.amount * 100000000, order.amount ? false : order.has_range, order.min_amount * 100000000, order.max_amount * 100000000, ) + ' Sats' ); } else { return ( amountToString( order.amount, order.amount ? false : order.has_range, order.min_amount, order.max_amount, ) + ` ${currencyCode}` ); } }, [order.currency, order.amount, order.min_amount, order.max_amount, order.has_range]); // Countdown Renderer callback with condition const countdownRenderer = function ({ total, hours, minutes, seconds, completed, }: CountdownRenderProps) { if (completed) { // Render a completed state return {t('The order has expired')}; } else { let color = 'inherit'; const fraction_left = total / 1000 / order.total_secs_exp; // Make orange at 25% of time left if (fraction_left < 0.25) { color = theme.palette.warning.main; } // Make red at 10% of time left if (fraction_left < 0.1) { color = theme.palette.error.main; } // Render a countdown, bold when less than 25% return fraction_left < 0.25 ? ( {`${hours}h ${zeroPad(minutes)}m ${zeroPad(seconds)}s `} ) : ( {`${hours}h ${zeroPad(minutes)}m ${zeroPad(seconds)}s `} ); } }; const timerRenderer = function (seconds: number) { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds - hours * 3600) / 60); return ( {hours > 0 ? hours + 'h' : ''} {minutes > 0 ? zeroPad(minutes) + 'm' : ''}{' '} ); }; // Countdown Renderer callback with condition const countdownPenaltyRenderer = function ({ minutes, seconds, completed }) { if (completed) { // Render a completed state return {t('Penalty lifted, good to go!')}; } else { return ( {' '} {t('You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s', { timeMin: zeroPad(minutes), timeSec: zeroPad(seconds), })}{' '} ); } }; const satsSummary = useMemo(() => { let send: string = ''; let receive: string = ''; let sats: string = ''; const isBuyer = (order.type == 0 && order.is_maker) || (order.type == 1 && !order.is_maker); const tradeFee = order.is_maker ? info?.maker_fee ?? 0 : info?.taker_fee ?? 0; const defaultRoutingBudget = 0.001; const btc_now = order.satoshis_now / 100000000; const rate = order.amount ? order.amount / btc_now : order.max_amount / btc_now; if (isBuyer) { if (order.amount) { sats = computeSats({ amount: order.amount, fee: -tradeFee, routingBudget: defaultRoutingBudget, rate: rate, }); } else { const min = computeSats({ amount: Number(order.min_amount), fee: -tradeFee, routingBudget: defaultRoutingBudget, rate: rate, }); const max = computeSats({ amount: Number(order.max_amount), fee: -tradeFee, routingBudget: defaultRoutingBudget, rate: rate, }); sats = `${min}-${max}`; } send = t('You send via {{method}} {{amount}}', { amount: amountString, method: order.payment_method, currencyCode, }); receive = t('You receive via Lightning {{amount}} Sats (Approx)', { amount: sats, }); } else { if (order.amount) { sats = computeSats({ amount: order.amount, fee: tradeFee, rate: rate, }); } else { const min = computeSats({ amount: order.min_amount, fee: tradeFee, rate: rate, }); const max = computeSats({ amount: order.max_amount, fee: tradeFee, rate: rate, }); sats = `${min}-${max}`; } send = t('You send via Lightning {{amount}} Sats (Approx)', { amount: sats }); receive = t('You receive via {{method}} {{amount}}', { amount: amountString, method: order.payment_method, }); } return { send, receive }; }, [order.currency, order.satoshis_now, order.amount, order.has_range]); return (
setShowSatsDetails(!showSatsDetails)}> {showSatsDetails ? : }
{satsSummary.send} {satsSummary.receive} } secondary={ order.currency == 1000 ? t('Swap destination') : t('Accepted payment methods') } /> {/* If there is live Price and Premium data, show it. Otherwise show the order maker settings */} {order.price_now !== undefined ? ( ) : null} {!order.price_now && order.is_explicit ? ( ) : null} {!order.price_now && !order.is_explicit ? ( ) : null} {/* if order is in a status that does not expire, do not show countdown */} {/* If the user has a penalty/limit */} {order.penalty !== undefined ? ( ) : ( <> )} {!order.is_participant ? ( ) : ( <> )} ); }; export default OrderDetails;