import React, { useMemo, useState, useCallback } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { useHistory } from 'react-router-dom'; import ListItem from '../../ui/list-item'; import { useTransactionDisplayData } from '../../../hooks/useTransactionDisplayData'; import { useI18nContext } from '../../../hooks/useI18nContext'; import TransactionListItemDetails from '../transaction-list-item-details'; import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes'; import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp'; import TransactionStatus from '../transaction-status/transaction-status.component'; import TransactionIcon from '../transaction-icon'; import { TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, } from '../../../../shared/constants/transaction'; import { EDIT_GAS_MODES } from '../../../../shared/constants/gas'; import EditGasPopover from '../edit-gas-popover'; import { useMetricEvent } from '../../../hooks/useMetricEvent'; import Button from '../../ui/button'; import CancelButton from '../cancel-button'; export default function TransactionListItem({ transactionGroup, isEarliestNonce = false, }) { const t = useI18nContext(); const history = useHistory(); const { hasCancelled } = transactionGroup; const [showDetails, setShowDetails] = useState(false); const [showCancelEditGasPopover, setShowCancelEditGasPopover] = useState( false, ); const [showRetryEditGasPopover, setShowRetryEditGasPopover] = useState(false); const { initialTransaction: { id }, primaryTransaction: { err, status }, } = transactionGroup; const speedUpMetricsEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Activity Log', name: 'Clicked "Speed Up"', }, }); const cancelMetricsEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Activity Log', name: 'Clicked "Cancel"', }, }); const retryTransaction = useCallback( async (event) => { event.stopPropagation(); setShowRetryEditGasPopover(true); speedUpMetricsEvent(); }, [speedUpMetricsEvent], ); const cancelTransaction = useCallback( (event) => { event.stopPropagation(); setShowCancelEditGasPopover(true); cancelMetricsEvent(); }, [cancelMetricsEvent], ); const shouldShowSpeedUp = useShouldShowSpeedUp( transactionGroup, isEarliestNonce, ); const { title, subtitle, subtitleContainsOrigin, date, category, primaryCurrency, recipientAddress, secondaryCurrency, displayedStatusKey, isPending, senderAddress, } = useTransactionDisplayData(transactionGroup); const isSignatureReq = category === TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST; const isApproval = category === TRANSACTION_GROUP_CATEGORIES.APPROVAL; const isUnapproved = status === TRANSACTION_STATUSES.UNAPPROVED; const isSwap = category === TRANSACTION_GROUP_CATEGORIES.SWAP; const className = classnames('transaction-list-item', { 'transaction-list-item--unconfirmed': isPending || [ TRANSACTION_STATUSES.FAILED, TRANSACTION_STATUSES.DROPPED, TRANSACTION_STATUSES.REJECTED, ].includes(displayedStatusKey), }); const toggleShowDetails = useCallback(() => { if (isUnapproved) { history.push(`${CONFIRM_TRANSACTION_ROUTE}/${id}`); return; } setShowDetails((prev) => !prev); }, [isUnapproved, history, id]); const speedUpButton = useMemo(() => { if (!shouldShowSpeedUp || !isPending || isUnapproved) { return null; } return ( ); }, [ shouldShowSpeedUp, isUnapproved, t, isPending, hasCancelled, retryTransaction, cancelTransaction, ]); const showCancelButton = !hasCancelled && isPending && !isUnapproved; return ( <> } subtitle={

{subtitle}

} rightContent={ !isSignatureReq && !isApproval && ( <>

{primaryCurrency}

{secondaryCurrency}

) } >
{speedUpButton} {showCancelButton && ( )}
{showDetails && ( )} {showRetryEditGasPopover && ( setShowRetryEditGasPopover(false)} mode={EDIT_GAS_MODES.SPEED_UP} transaction={transactionGroup.primaryTransaction} /> )} {showCancelEditGasPopover && ( setShowCancelEditGasPopover(false)} mode={EDIT_GAS_MODES.CANCEL} transaction={transactionGroup.primaryTransaction} /> )} ); } TransactionListItem.propTypes = { transactionGroup: PropTypes.object.isRequired, isEarliestNonce: PropTypes.bool, };