diff options
Diffstat (limited to 'ui/app/components/transaction-list-item')
4 files changed, 182 insertions, 0 deletions
diff --git a/ui/app/components/transaction-list-item/index.js b/ui/app/components/transaction-list-item/index.js new file mode 100644 index 000000000..697cc55e9 --- /dev/null +++ b/ui/app/components/transaction-list-item/index.js @@ -0,0 +1 @@ +export { default } from './transaction-list-item.container' diff --git a/ui/app/components/transaction-list-item/index.scss b/ui/app/components/transaction-list-item/index.scss new file mode 100644 index 000000000..8a3973f92 --- /dev/null +++ b/ui/app/components/transaction-list-item/index.scss @@ -0,0 +1,71 @@ +.transaction-list-item { + box-sizing: border-box; + height: 74px; + padding: 0 21px; + display: flex; + flex-direction: row; + align-items: center; + border-bottom: 1px solid $geyser; + cursor: pointer; + + @media screen and (max-width: $break-small) { + padding: 0 12px; + } + + &__identicon-wrapper { + padding-top: 2px; + } + + &__action-block { + padding: 0 8px 0 12px; + width: 180px; + + @media screen and (max-width: $break-small) { + padding: 0 8px; + width: 160px; + } + } + + &__action { + text-transform: capitalize; + padding-bottom: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + @media screen and (max-width: $break-small) { + padding-bottom: 0; + font-size: .875rem; + } + } + + &__nonce { + font-size: .75rem; + color: #5e6064; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + &__transaction-amounts { + flex: 1; + } + + &__primary-transaction-amount { + text-align: end; + + @media screen and (max-width: $break-small) { + font-size: .75rem; + } + } + + &__secondary-transaction-amount { + text-align: end; + font-size: .75rem; + color: #5e6064; + } + + &:hover { + background: rgba($alto, .2); + } +} diff --git a/ui/app/components/transaction-list-item/transaction-list-item.component.js b/ui/app/components/transaction-list-item/transaction-list-item.component.js new file mode 100644 index 000000000..e334cd938 --- /dev/null +++ b/ui/app/components/transaction-list-item/transaction-list-item.component.js @@ -0,0 +1,82 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import Media from 'react-media' +import Identicon from '../identicon' +import TransactionStatus from '../transaction-status' +import TransactionAction from '../transaction-action' +import { formatDate } from '../../util' +import prefixForNetwork from '../../../lib/etherscan-prefix-for-network' +import { CONFIRM_TRANSACTION_ROUTE } from '../../routes' +import { UNAPPROVED_STATUS } from '../../constants/transactions' +import { hexToDecimal } from '../../helpers/conversions.util' + +export default class TransactionListItem extends PureComponent { + static propTypes = { + history: PropTypes.object, + methodData: PropTypes.object, + transaction: PropTypes.object, + ethTransactionAmount: PropTypes.string, + fiatDisplayValue: PropTypes.string, + } + + handleClick = () => { + const { transaction, history } = this.props + const { id, status, hash, metamaskNetworkId } = transaction + + if (status === UNAPPROVED_STATUS) { + history.push(`${CONFIRM_TRANSACTION_ROUTE}/${id}`) + } else if (hash) { + const prefix = prefixForNetwork(metamaskNetworkId) + const etherscanUrl = `https://${prefix}etherscan.io/tx/${hash}` + global.platform.openWindow({ url: etherscanUrl }) + } + } + + render () { + const { + transaction, + ethTransactionAmount, + fiatDisplayValue, + } = this.props + const { txParams = {} } = transaction + const nonce = hexToDecimal(txParams.nonce) + + return ( + <div + className="transaction-list-item" + onClick={this.handleClick} + > + <div className="transaction-list-item__identicon-wrapper"> + <Media query="(max-width: 575px)"> + { + matches => ( + <Identicon + address={txParams.to} + diameter={matches ? 26 : 34} + /> + ) + } + </Media> + </div> + <div className="transaction-list-item__action-block"> + <TransactionAction + transaction={transaction} + className="transaction-list-item__action" + /> + <div className="transaction-list-item__nonce"> + { `#${nonce} - ${formatDate(transaction.time)}` } + </div> + </div> + <TransactionStatus status={transaction.status} /> + <div className="transaction-list-item__transaction-amounts"> + <div className="transaction-list-item__primary-transaction-amount"> + { `-${fiatDisplayValue}` } + </div> + <div className="transaction-list-item__secondary-transaction-amount"> + { `-${ethTransactionAmount} ETH` } + </div> + </div> + </div> + ) + } +} diff --git a/ui/app/components/transaction-list-item/transaction-list-item.container.js b/ui/app/components/transaction-list-item/transaction-list-item.container.js new file mode 100644 index 000000000..bc47f20aa --- /dev/null +++ b/ui/app/components/transaction-list-item/transaction-list-item.container.js @@ -0,0 +1,28 @@ +import { connect } from 'react-redux' +import { withRouter } from 'react-router-dom' +import { compose } from 'recompose' +import TransactionListItem from './transaction-list-item.component' +import { getEthFromWeiHex, getValueFromWeiHex } from '../../helpers/conversions.util' +import { formatCurrency } from '../../helpers/confirm-transaction/util' + +const mapStateToProps = (state, ownProps) => { + const { metamask } = state + const { currentCurrency, conversionRate } = metamask + const { transaction: { txParams: { value } = {} } = {} } = ownProps + const ethTransactionAmount = getEthFromWeiHex({ value, conversionRate }) + const fiatTransactionAmount = getValueFromWeiHex({ + value, conversionRate, toCurrency: currentCurrency, numberOfDecimals: 2, + }) + const fiatFormattedAmount = formatCurrency(fiatTransactionAmount, currentCurrency) + const fiatDisplayValue = `${fiatFormattedAmount} ${currentCurrency.toUpperCase()}` + + return { + ethTransactionAmount, + fiatDisplayValue, + } +} + +export default compose( + withRouter, + connect(mapStateToProps), +)(TransactionListItem) |