Browse Source

More modular portfolio split into components

master
Gaëtan Renaudeau 7 years ago
parent
commit
ddce9589c5
  1. 66
      src/components/DashboardPage/AccountCardList.js
  2. 33
      src/components/DashboardPage/AccountCardListHeader.js
  3. 64
      src/components/DashboardPage/AccountCardPlaceholder.js
  4. 31
      src/components/DashboardPage/CurrentGreetings.js
  5. 22
      src/components/DashboardPage/SummaryDesc.js
  6. 186
      src/components/DashboardPage/index.js

66
src/components/DashboardPage/AccountCardList.js

@ -0,0 +1,66 @@
// @flow
import React, { Component } from 'react'
import type { Account, Currency } from '@ledgerhq/live-common/lib/types'
import Box from 'components/base/Box'
import AccountCard from './AccountCard'
import AccountCardListHeader from './AccountCardListHeader'
import AccountCardPlaceholder from './AccountCardPlaceholder'
type Props = {
accounts: Account[],
onAccountClick: Account => void,
counterValue: Currency,
daysCount: number,
}
class AccountCardList extends Component<Props> {
render() {
const { accounts, counterValue, daysCount, onAccountClick } = this.props
return (
<Box flow={4}>
<AccountCardListHeader accountsLength={accounts.length} />
<Box
horizontal
flexWrap="wrap"
justifyContent="flex-start"
alignItems="center"
style={{ margin: '0 -16px' }}
>
{accounts
.map(account => ({
key: account.id,
account,
}))
.concat(
Array(3 - (accounts.length % 3))
.fill(null)
.map((_, i) => ({
key: `placeholder_${i}`,
withPlaceholder: i === 0,
})),
)
.map(item => (
<Box key={item.key} flex="33%" p={16}>
{item.account ? (
<AccountCard
key={item.account.id}
counterValue={counterValue}
account={item.account}
daysCount={daysCount}
onClick={onAccountClick}
/>
) : item.withPlaceholder ? (
<AccountCardPlaceholder />
) : null}
</Box>
))}
</Box>
</Box>
)
}
}
export default AccountCardList

33
src/components/DashboardPage/AccountCardListHeader.js

@ -0,0 +1,33 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import type { T } from 'types/common'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import AccountsOrder from './AccountsOrder'
type Props = {
t: T,
accountsLength: number,
}
class AccountCardListHeader extends PureComponent<Props> {
render() {
const { accountsLength, t } = this.props
return (
<Box horizontal alignItems="flex-end">
<Text color="dark" ff="Museo Sans" fontSize={6}>
{t('app:dashboard.accounts.title', { count: accountsLength })}
</Text>
<Box ml="auto" horizontal flow={1}>
<AccountsOrder />
</Box>
</Box>
)
}
}
export default translate()(AccountCardListHeader)

64
src/components/DashboardPage/AccountCardPlaceholder.js

@ -0,0 +1,64 @@
// @flow
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import { openModal } from 'reducers/modals'
import { MODAL_ADD_ACCOUNTS } from 'config/constants'
import type { T } from 'types/common'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
const Wrapper = styled(Box).attrs({
p: 4,
flex: 1,
alignItems: 'center',
})`
border: 1px dashed ${p => p.theme.colors.fog};
border-radius: 4px;
height: 215px;
`
class AccountCardPlaceholder extends PureComponent<{
t: T,
openModal: string => void,
}> {
onAddAccounts = () => this.props.openModal(MODAL_ADD_ACCOUNTS)
render() {
const { t } = this.props
return (
<Wrapper>
<Box mt={2}>
<img alt="" src={i('empty-account-tile.svg')} />
</Box>
<Box
ff="Open Sans"
fontSize={3}
color="grey"
pb={2}
mt={3}
textAlign="center"
style={{ maxWidth: 150 }}
>
{t('app:dashboard.emptyAccountTile.desc')}
</Box>
<Button primary onClick={this.onAddAccounts}>
{t('app:dashboard.emptyAccountTile.createAccount')}
</Button>
</Wrapper>
)
}
}
export default translate()(
connect(
null,
{
openModal,
},
)(AccountCardPlaceholder),
)

31
src/components/DashboardPage/CurrentGreetings.js

@ -0,0 +1,31 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import type { T } from 'types/common'
import Text from 'components/base/Text'
const getCurrentGreetings = () => {
const localTimeHour = new Date().getHours()
const afternoon_breakpoint = 12
const evening_breakpoint = 17
if (localTimeHour >= afternoon_breakpoint && localTimeHour < evening_breakpoint) {
return 'app:dashboard.greeting.afternoon'
} else if (localTimeHour >= evening_breakpoint) {
return 'app:dashboard.greeting.evening'
}
return 'app:dashboard.greeting.morning'
}
class CurrentGettings extends PureComponent<{ t: T }> {
render() {
const { t } = this.props
return (
<Text color="dark" ff="Museo Sans" fontSize={7}>
{t(getCurrentGreetings())}
</Text>
)
}
}
export default translate()(CurrentGettings)

22
src/components/DashboardPage/SummaryDesc.js

@ -0,0 +1,22 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import type { T } from 'types/common'
import Text from 'components/base/Text'
class SummaryDesc extends PureComponent<{
t: T,
totalAccounts: number,
}> {
render() {
const { totalAccounts, t } = this.props
return (
<Text color="grey" fontSize={5} ff="Museo Sans|Light">
{t('app:dashboard.summary', { count: totalAccounts })}
</Text>
)
}
}
export default translate()(SummaryDesc)

186
src/components/DashboardPage/index.js

@ -5,7 +5,6 @@ import uniq from 'lodash/uniq'
import { compose } from 'redux'
import { translate } from 'react-i18next'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { push } from 'react-router-redux'
import { createStructuredSelector } from 'reselect'
import type { Account, Currency } from '@ledgerhq/live-common/lib/types'
@ -14,11 +13,8 @@ import type { T } from 'types/common'
import { colors } from 'styles/theme'
import { accountsSelector } from 'reducers/accounts'
import { openModal } from 'reducers/modals'
import { MODAL_ADD_ACCOUNTS } from 'config/constants'
import {
counterValueCurrencySelector,
localeSelector,
selectedTimeRangeSelector,
timeRangeDaysByKey,
} from 'reducers/settings'
@ -32,27 +28,23 @@ import UpdateNotifier from 'components/UpdateNotifier'
import BalanceInfos from 'components/BalanceSummary/BalanceInfos'
import BalanceSummary from 'components/BalanceSummary'
import Box from 'components/base/Box'
import { i } from 'helpers/staticPath'
import PillsDaysCount from 'components/PillsDaysCount'
import Text from 'components/base/Text'
import OperationsList from 'components/OperationsList'
import StickyBackToTop from 'components/StickyBackToTop'
import Button from 'components/base/Button'
import AccountCard from './AccountCard'
import AccountsOrder from './AccountsOrder'
import EmptyState from './EmptyState'
import CurrentGreetings from './CurrentGreetings'
import SummaryDesc from './SummaryDesc'
import AccountCardList from './AccountCardList'
const mapStateToProps = createStructuredSelector({
accounts: accountsSelector,
counterValue: counterValueCurrencySelector,
locale: localeSelector,
selectedTimeRange: selectedTimeRangeSelector,
})
const mapDispatchToProps = {
push,
saveSettings,
openModal,
}
type Props = {
@ -62,41 +54,33 @@ type Props = {
counterValue: Currency,
selectedTimeRange: TimeRange,
saveSettings: ({ selectedTimeRange: TimeRange }) => *,
openModal: string => void,
}
class DashboardPage extends PureComponent<Props> {
onAccountClick = account => this.props.push(`/account/${account.id}`)
handleGreeting = () => {
const localTimeHour = new Date().getHours()
const afternoon_breakpoint = 12
const evening_breakpoint = 17
if (localTimeHour >= afternoon_breakpoint && localTimeHour < evening_breakpoint) {
return 'app:dashboard.greeting.afternoon'
} else if (localTimeHour >= evening_breakpoint) {
return 'app:dashboard.greeting.evening'
}
return 'app:dashboard.greeting.morning'
}
handleChangeSelectedTime = item => {
this.props.saveSettings({ selectedTimeRange: item.key })
}
_cacheBalance = null
renderHeader = ({ isAvailable, totalBalance, selectedTimeRange, sinceBalance, refBalance }) => (
<BalanceInfos
t={this.props.t}
counterValue={this.props.counterValue}
isAvailable={isAvailable}
totalBalance={totalBalance}
since={selectedTimeRange}
sinceBalance={sinceBalance}
refBalance={refBalance}
/>
)
render() {
const { accounts, t, counterValue, selectedTimeRange, openModal } = this.props
const { accounts, t, counterValue, selectedTimeRange } = this.props
const daysCount = timeRangeDaysByKey[selectedTimeRange]
const timeFrame = this.handleGreeting()
const imagePath = i('empty-account-tile.svg')
const totalAccounts = accounts.length
const totalCurrencies = uniq(accounts.map(a => a.currency.id)).length
const totalOperations = accounts.reduce((sum, a) => sum + a.operations.length, 0)
const displayOperationsHelper = (account: Account) => account.operations.length > 0
const displayOperations = accounts.some(displayOperationsHelper)
return (
<Fragment>
@ -113,12 +97,8 @@ class DashboardPage extends PureComponent<Props> {
<Fragment>
<Box horizontal alignItems="flex-end">
<Box grow>
<Text color="dark" ff="Museo Sans" fontSize={7}>
{t(timeFrame)}
</Text>
<Text color="grey" fontSize={5} ff="Museo Sans|Light">
{t('app:dashboard.summary', { count: totalAccounts })}
</Text>
<CurrentGreetings />
<SummaryDesc totalAccounts={totalAccounts} />
</Box>
<Box>
<PillsDaysCount
@ -127,105 +107,33 @@ class DashboardPage extends PureComponent<Props> {
/>
</Box>
</Box>
<Fragment>
<BalanceSummary
counterValue={counterValue}
chartId="dashboard-chart"
chartColor={colors.wallet}
<BalanceSummary
counterValue={counterValue}
chartId="dashboard-chart"
chartColor={colors.wallet}
accounts={accounts}
selectedTimeRange={selectedTimeRange}
daysCount={daysCount}
renderHeader={this.renderHeader}
/>
<AccountCardList
onAccountClick={this.onAccountClick}
accounts={accounts}
daysCount={daysCount}
counterValue={counterValue}
/>
{totalOperations > 0 && (
<OperationsList
onAccountClick={this.onAccountClick}
accounts={accounts}
selectedTimeRange={selectedTimeRange}
daysCount={daysCount}
renderHeader={({
isAvailable,
totalBalance,
selectedTimeRange,
sinceBalance,
refBalance,
}) => (
<BalanceInfos
t={t}
counterValue={counterValue}
isAvailable={isAvailable}
totalBalance={totalBalance}
since={selectedTimeRange}
sinceBalance={sinceBalance}
refBalance={refBalance}
/>
)}
title={t('app:dashboard.recentActivity')}
withAccount
/>
<Box flow={4}>
<Box horizontal alignItems="flex-end">
<Text color="dark" ff="Museo Sans" fontSize={6}>
{t('app:dashboard.accounts.title', { count: accounts.length })}
</Text>
<Box ml="auto" horizontal flow={1}>
<AccountsOrder />
</Box>
</Box>
<Box
horizontal
flexWrap="wrap"
justifyContent="flex-start"
alignItems="center"
style={{ margin: '0 -16px' }}
>
{accounts
.concat(
Array(3 - (accounts.length % 3))
.fill(null)
.map((_, i) => i === 0),
)
.map((account, i) => (
<Box
key={typeof account === 'object' ? account.id : `placeholder_${i}`}
flex="33%"
p={16}
>
{account ? (
typeof account === 'object' ? (
<AccountCard
key={account.id}
counterValue={counterValue}
account={account}
daysCount={daysCount}
onClick={this.onAccountClick}
/>
) : (
<Wrapper>
<Box mt={2}>
<img alt="" src={imagePath} />
</Box>
<Box
ff="Open Sans"
fontSize={3}
color="grey"
pb={2}
mt={3}
textAlign="center"
style={{ maxWidth: 150 }}
>
{t('app:dashboard.emptyAccountTile.desc')}
</Box>
<Button primary onClick={() => openModal(MODAL_ADD_ACCOUNTS)}>
{t('app:dashboard.emptyAccountTile.createAccount')}
</Button>
</Wrapper>
)
) : null}
</Box>
))}
</Box>
</Box>
{displayOperations && (
<OperationsList
onAccountClick={this.onAccountClick}
accounts={accounts}
title={t('app:dashboard.recentActivity')}
withAccount
/>
)}
<StickyBackToTop />
</Fragment>
)}
<StickyBackToTop />
</Fragment>
) : (
<EmptyState />
@ -243,13 +151,3 @@ export default compose(
),
translate(),
)(DashboardPage)
const Wrapper = styled(Box).attrs({
p: 4,
flex: 1,
alignItems: 'center',
})`
border: 1px dashed ${p => p.theme.colors.fog};
border-radius: 4px;
height: 215px;
`

Loading…
Cancel
Save