Browse Source
- make sure no extra field is used in the app - use currency settings to display confirmed/not-confirmed operation - add blockHeight fetch when syncing accountmaster
meriadec
7 years ago
9 changed files with 422 additions and 322 deletions
@ -0,0 +1,209 @@ |
|||
// @flow
|
|||
|
|||
import React, { PureComponent } from 'react' |
|||
import { connect } from 'react-redux' |
|||
import styled from 'styled-components' |
|||
import moment from 'moment' |
|||
import noop from 'lodash/noop' |
|||
import { getIconByCoinType } from '@ledgerhq/currencies/react' |
|||
|
|||
import type { Account, Operation as OperationType } from '@ledgerhq/wallet-common/lib/types' |
|||
|
|||
import type { T } from 'types/common' |
|||
|
|||
import { currencySettingsSelector, marketIndicatorSelector } from 'reducers/settings' |
|||
import { rgba, getMarketColor } from 'styles/helpers' |
|||
|
|||
import Box from 'components/base/Box' |
|||
import Text from 'components/base/Text' |
|||
import CounterValue from 'components/CounterValue' |
|||
import FormattedVal from 'components/base/FormattedVal' |
|||
|
|||
import ConfirmationCheck from './ConfirmationCheck' |
|||
|
|||
const mapStateToProps = (state, props) => ({ |
|||
minConfirmations: currencySettingsSelector(state, props.account.currency).confirmationsNb, |
|||
marketIndicator: marketIndicatorSelector(state), |
|||
}) |
|||
|
|||
const DATE_COL_SIZE = 100 |
|||
const ACCOUNT_COL_SIZE = 150 |
|||
const AMOUNT_COL_SIZE = 150 |
|||
const CONFIRMATION_COL_SIZE = 44 |
|||
|
|||
const OperationRaw = styled(Box).attrs({ |
|||
horizontal: true, |
|||
alignItems: 'center', |
|||
})` |
|||
cursor: pointer; |
|||
border-bottom: 1px solid ${p => p.theme.colors.lightGrey}; |
|||
height: 68px; |
|||
|
|||
&:last-child { |
|||
border-bottom: 0; |
|||
} |
|||
|
|||
&:hover { |
|||
background: ${p => rgba(p.theme.colors.wallet, 0.04)}; |
|||
} |
|||
` |
|||
|
|||
const Address = ({ value }: { value: string }) => { |
|||
const addrSize = value.length / 2 |
|||
|
|||
const left = value.slice(0, 10) |
|||
const right = value.slice(-addrSize) |
|||
const middle = value.slice(10, -addrSize) |
|||
|
|||
return ( |
|||
<Box horizontal color="smoke" ff="Open Sans" fontSize={3}> |
|||
<div>{left}</div> |
|||
<AddressEllipsis>{middle}</AddressEllipsis> |
|||
<div>{right}</div> |
|||
</Box> |
|||
) |
|||
} |
|||
|
|||
const AddressEllipsis = styled.div` |
|||
display: block; |
|||
flex-shrink: 1; |
|||
min-width: 20px; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
white-space: nowrap; |
|||
` |
|||
|
|||
const Day = styled(Text).attrs({ |
|||
color: 'dark', |
|||
fontSize: 3, |
|||
ff: 'Open Sans', |
|||
})` |
|||
letter-spacing: 0.3px; |
|||
text-transform: uppercase; |
|||
` |
|||
|
|||
const Hour = styled(Day).attrs({ |
|||
color: 'grey', |
|||
})`` |
|||
|
|||
const Cell = styled(Box).attrs({ |
|||
px: 4, |
|||
horizontal: true, |
|||
alignItems: 'center', |
|||
})` |
|||
width: ${p => (p.size ? `${p.size}px` : '')}; |
|||
overflow: ${p => (p.noOverflow ? 'hidden' : '')}; |
|||
` |
|||
|
|||
type Props = { |
|||
account: Account, |
|||
minConfirmations: number, |
|||
onAccountClick: Function, |
|||
onOperationClick: Function, |
|||
marketIndicator: string, |
|||
t: T, |
|||
op: OperationType, |
|||
withAccount?: boolean, |
|||
} |
|||
|
|||
class Operation extends PureComponent<Props> { |
|||
static defaultProps = { |
|||
onAccountClick: noop, |
|||
onOperationClick: noop, |
|||
withAccount: false, |
|||
} |
|||
|
|||
render() { |
|||
const { |
|||
account, |
|||
minConfirmations, |
|||
onAccountClick, |
|||
onOperationClick, |
|||
t, |
|||
op, |
|||
withAccount, |
|||
marketIndicator, |
|||
} = this.props |
|||
const { unit, currency } = account |
|||
const time = moment(op.date) |
|||
const Icon = getIconByCoinType(account.currency.coinType) |
|||
const isNegative = op.amount < 0 |
|||
const type = !isNegative ? 'from' : 'to' |
|||
|
|||
const marketColor = getMarketColor({ |
|||
marketIndicator, |
|||
isNegative, |
|||
}) |
|||
|
|||
return ( |
|||
<OperationRaw onClick={() => onOperationClick({ operation: op, account, type, marketColor })}> |
|||
<Cell size={CONFIRMATION_COL_SIZE} align="center" justify="flex-start"> |
|||
<ConfirmationCheck |
|||
type={type} |
|||
minConfirmations={minConfirmations} |
|||
confirmations={account.blockHeight - op.blockHeight} |
|||
marketColor={marketColor} |
|||
t={t} |
|||
/> |
|||
</Cell> |
|||
<Cell size={DATE_COL_SIZE} justifyContent="space-between" px={3}> |
|||
<Box> |
|||
<Box ff="Open Sans|SemiBold" fontSize={3} color="smoke"> |
|||
{t(`operationsList:${type}`)} |
|||
</Box> |
|||
<Hour>{time.format('HH:mm')}</Hour> |
|||
</Box> |
|||
</Cell> |
|||
{withAccount && |
|||
account && ( |
|||
<Cell |
|||
noOverflow |
|||
size={ACCOUNT_COL_SIZE} |
|||
horizontal |
|||
flow={2} |
|||
style={{ cursor: 'pointer' }} |
|||
onClick={e => { |
|||
e.stopPropagation() |
|||
onAccountClick(account) |
|||
}} |
|||
> |
|||
<Box |
|||
alignItems="center" |
|||
justifyContent="center" |
|||
style={{ color: account.currency.color }} |
|||
> |
|||
{Icon && <Icon size={16} />} |
|||
</Box> |
|||
<Box ff="Open Sans|SemiBold" fontSize={3} color="dark"> |
|||
{account.name} |
|||
</Box> |
|||
</Cell> |
|||
)} |
|||
<Cell grow shrink style={{ display: 'block' }}> |
|||
<Address value={op.address} /> |
|||
</Cell> |
|||
<Cell size={AMOUNT_COL_SIZE} justify="flex-end"> |
|||
<Box alignItems="flex-end"> |
|||
<FormattedVal |
|||
val={op.amount} |
|||
unit={unit} |
|||
showCode |
|||
fontSize={4} |
|||
alwaysShowSign |
|||
color={op.amount < 0 ? 'smoke' : undefined} |
|||
/> |
|||
<CounterValue |
|||
color="grey" |
|||
fontSize={3} |
|||
date={time.toDate()} |
|||
ticker={currency.units[0].code} |
|||
value={op.amount} |
|||
/> |
|||
</Box> |
|||
</Cell> |
|||
</OperationRaw> |
|||
) |
|||
} |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(Operation) |
Loading…
Reference in new issue