Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split AccountSwitch in multiple modules #2535

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 7 additions & 255 deletions src/ducks/account/AccountSwitch.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
import React, { useCallback, useState, useMemo, memo } from 'react'
import React, { useCallback, useState, memo } from 'react'
import PropTypes from 'prop-types'
import { useDispatch, useSelector } from 'react-redux'
import sortBy from 'lodash/sortBy'
import cx from 'classnames'

import { useQuery } from 'cozy-client'
import { useI18n } from 'cozy-ui/transpiled/react/I18n'
import useBreakpoints from 'cozy-ui/transpiled/react/hooks/useBreakpoints'
import Button from 'cozy-ui/transpiled/react/MuiCozyTheme/Buttons'
import List from 'cozy-ui/transpiled/react/MuiCozyTheme/List'
import ListItem from 'cozy-ui/transpiled/react/MuiCozyTheme/ListItem'
import ListItemIcon from 'cozy-ui/transpiled/react/MuiCozyTheme/ListItemIcon'
import ListSubheader from 'cozy-ui/transpiled/react/MuiCozyTheme/ListSubheader'
import ListItemSecondaryAction from 'cozy-ui/transpiled/react/MuiCozyTheme/ListItemSecondaryAction'
import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
import Radio from 'cozy-ui/transpiled/react/Radios'
import CozyTheme from 'cozy-ui/transpiled/react/CozyTheme'
import DropdownText from 'cozy-ui/transpiled/react/DropdownText'

import { AccountRowIcon } from 'ducks/balance/AccountRow'
import { groupsConn, accountsConn } from 'doctypes'
import { getVirtualAccounts, getVirtualGroups } from 'selectors'
import RawContentDialog from 'components/RawContentDialog'
import AccountSharingStatus from 'components/AccountSharingStatus'
import BarItem from 'components/BarItem'
import { BarCenter } from 'components/Bar'

Expand All @@ -30,244 +19,9 @@ import {
resetFilterByDoc,
getFilteredAccounts
} from 'ducks/filters'

import styles from 'ducks/account/AccountSwitch.styl'
import {
ACCOUNT_DOCTYPE,
GROUP_DOCTYPE,
groupsConn,
accountsConn
} from 'doctypes'
import { getGroupLabel } from 'ducks/groups/helpers'

import { getVirtualAccounts, getVirtualGroups } from 'selectors'
import {
getAccountInstitutionLabel,
getAccountLabel
} from 'ducks/account/helpers.js'

const filteringDocPropType = PropTypes.oneOfType([
PropTypes.array,
PropTypes.object
])

const getFilteringDocLabel = (filteringDoc, t) => {
if (filteringDoc._type === ACCOUNT_DOCTYPE) {
return getAccountLabel(filteringDoc, t)
} else if (filteringDoc._type === GROUP_DOCTYPE) {
return getGroupLabel(filteringDoc, t)
}
}

const getFilteredAccountsLabel = (filteredAccounts, accounts, t) => {
return t('AccountSwitch.some-accounts', {
count: filteredAccounts.length,
smart_count: accounts.length
})
}

const getFilterLabel = (filteredAccounts, filteringDoc, accounts, t) => {
if (accounts == null || accounts.length === 0) {
return t('Categories.noAccount')
}
if (filteringDoc == null) {
return t('AccountSwitch.all-accounts')
}
if (!Array.isArray(filteringDoc)) {
return getFilteringDocLabel(filteringDoc, t)
}
return getFilteredAccountsLabel(filteredAccounts, accounts, t)
}

// t is passed from above and not through useI18n() since AccountSwitchSelect can be
// rendered in the Bar and in this case it has a different context
const AccountSwitchSelect = ({
accounts,
filteredAccounts,
filteringDoc,
onClick,
t,
typographyProps
}) => {
return (
<div className={styles.AccountSwitch__Select} onClick={onClick}>
<DropdownText
noWrap
innerTextProps={{ variant: 'h1', ...typographyProps }}
>
{getFilterLabel(filteredAccounts, filteringDoc, accounts, t)}
</DropdownText>
</div>
)
}

AccountSwitchSelect.propTypes = {
t: PropTypes.func.isRequired
}

const accountListItemTextTypo2Props = {
variant: 'caption',
color: 'textSecondary'
}

const AccountListItemText = ({ primary, secondary }) => {
return (
<ListItemText
primary={primary}
secondary={secondary}
secondaryTypographyProps={accountListItemTextTypo2Props}
/>
)
}

const AccountSwitchListItem = props => {
return (
<ListItem {...props}>
{props.children}
<ListItemSecondaryAction className="u-pr-1">
<Radio onClick={props.onClick} checked={props.selected} readOnly />
</ListItemSecondaryAction>
</ListItem>
)
}

const AccountSwitchMenu = ({
accounts,
virtualAccounts,
groups,
virtualGroups,
filteringDoc,
filterByDoc,
resetFilterByDoc
}) => {
const { t } = useI18n()

const handleReset = () => {
resetFilterByDoc()
}

const accountExists = useCallback(
accountId => {
return accounts.find(account => account.id === accountId)
},
[accounts]
)

const sortedGroups = useMemo(() => {
return sortBy([...groups, ...virtualGroups], g =>
getGroupLabel(g, t).toLowerCase()
)
}, [groups, virtualGroups, t])

const sortedAccounts = useMemo(() => {
return sortBy(
[...accounts, ...virtualAccounts],
['institutionLabel', a => getAccountLabel(a, t).toLowerCase()]
)
}, [accounts, virtualAccounts, t])

return (
<CozyTheme theme="normal">
<List>
<ListSubheader>{t('AccountSwitch.groups')}</ListSubheader>
<AccountSwitchListItem
dense
button
disableRipple
divider
onClick={handleReset}
selected={!filteringDoc}
>
<AccountListItemText
primary={t('AccountSwitch.all-accounts')}
secondary={
<>{t('AccountSwitch.account-counter', accounts.length)}</>
}
/>
</AccountSwitchListItem>
{sortedGroups.map(group => (
<AccountSwitchListItem
dense
key={group._id}
button
disableRipple
selected={filteringDoc && group._id === filteringDoc._id}
onClick={() => {
filterByDoc(group)
}}
>
<AccountListItemText
primary={getGroupLabel(group, t)}
secondary={
<>
{t(
'AccountSwitch.account-counter',
group.accounts.data.filter(
account => account && accountExists(account.id)
).length
)}
</>
}
/>
</AccountSwitchListItem>
))}
</List>
<Button
component="a"
href="#/settings/groups"
className="u-m-half"
color="primary"
>
{t('Groups.manage-groups')}
</Button>

<List>
<ListSubheader>{t('AccountSwitch.accounts')}</ListSubheader>
{sortedAccounts.map((account, index) => (
<AccountSwitchListItem
key={index}
button
disableRipple
dense
onClick={() => {
filterByDoc(account)
}}
selected={filteringDoc && account._id === filteringDoc._id}
>
<ListItemIcon>
<AccountRowIcon account={account} />
</ListItemIcon>
<AccountListItemText
primary={getAccountLabel(account, t)}
secondary={getAccountInstitutionLabel(account)}
/>
<ListItemSecondaryAction>
<AccountSharingStatus tooltip account={account} />
</ListItemSecondaryAction>
</AccountSwitchListItem>
))}
</List>
<Button
component="a"
href="#/settings/accounts"
className="u-m-half"
color="primary"
>
{t('Accounts.manage-accounts')}
</Button>
</CozyTheme>
)
}

AccountSwitchMenu.propTypes = {
filterByDoc: PropTypes.func.isRequired,
resetFilterByDoc: PropTypes.func.isRequired,
filteringDoc: filteringDocPropType
}

const AccountSwitchWrapper = ({ children }) => {
return <div className={cx(styles['account-switch'])}>{children}</div>
}
import AccountSwitchMenu from 'ducks/account/AccountSwitchMenu'
import AccountSwitchSelect from 'ducks/account/AccountSwitchSelect'
import AccountSwitchWrapper from 'ducks/account/AccountSwitchWrapper'

const barItemStyle = { overflow: 'hidden', paddingRight: '1rem' }

Expand Down Expand Up @@ -299,9 +53,7 @@ const selectPropsBySize = {
* @returns {JSX.Element}
*
*/
const AccountSwitch = props => {
const { size, insideBar } = props

const AccountSwitch = ({ size, insideBar }) => {
const accountsCollection = useQuery(accountsConn.query, accountsConn)
const groupsCollection = useQuery(groupsConn.query, groupsConn)
const [open, setOpen] = useState()
Expand Down
18 changes: 18 additions & 0 deletions src/ducks/account/AccountSwitchListItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react'

import ListItem from 'cozy-ui/transpiled/react/MuiCozyTheme/ListItem'
import ListItemSecondaryAction from 'cozy-ui/transpiled/react/MuiCozyTheme/ListItemSecondaryAction'
import Radio from 'cozy-ui/transpiled/react/Radios'

const AccountSwitchListItem = props => {
return (
<ListItem {...props}>
{props.children}
<ListItemSecondaryAction className="u-pr-1">
<Radio onClick={props.onClick} checked={props.selected} readOnly />
</ListItemSecondaryAction>
</ListItem>
)
}

export default AccountSwitchListItem
20 changes: 20 additions & 0 deletions src/ducks/account/AccountSwitchListItemText.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react'

import ListItemText from 'cozy-ui/transpiled/react/ListItemText'

const accountSwitchListItemTextTypo2Props = {
variant: 'caption',
color: 'textSecondary'
}

const AccountSwitchListItemText = ({ primary, secondary }) => {
return (
<ListItemText
primary={primary}
secondary={secondary}
secondaryTypographyProps={accountSwitchListItemTextTypo2Props}
/>
)
}

export default AccountSwitchListItemText
Loading