From 1f00fd74146f6c15ec4991bc84f5c04f8ca1aab9 Mon Sep 17 00:00:00 2001 From: PolariTOON <36267812+PolariTOON@users.noreply.github.com> Date: Wed, 9 Nov 2022 19:08:02 +0100 Subject: [PATCH] refactor: Split `AccountSwitch` in multiple modules --- src/ducks/account/AccountSwitch.jsx | 262 +----------------- src/ducks/account/AccountSwitchListItem.jsx | 18 ++ .../account/AccountSwitchListItemText.jsx | 20 ++ src/ducks/account/AccountSwitchMenu.jsx | 163 +++++++++++ src/ducks/account/AccountSwitchSelect.jsx | 66 +++++ src/ducks/account/AccountSwitchWrapper.jsx | 10 + 6 files changed, 284 insertions(+), 255 deletions(-) create mode 100644 src/ducks/account/AccountSwitchListItem.jsx create mode 100644 src/ducks/account/AccountSwitchListItemText.jsx create mode 100644 src/ducks/account/AccountSwitchMenu.jsx create mode 100644 src/ducks/account/AccountSwitchSelect.jsx create mode 100644 src/ducks/account/AccountSwitchWrapper.jsx diff --git a/src/ducks/account/AccountSwitch.jsx b/src/ducks/account/AccountSwitch.jsx index bad34c6b64..19324e5fad 100644 --- a/src/ducks/account/AccountSwitch.jsx +++ b/src/ducks/account/AccountSwitch.jsx @@ -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' @@ -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 ( -
- - {getFilterLabel(filteredAccounts, filteringDoc, accounts, t)} - -
- ) -} - -AccountSwitchSelect.propTypes = { - t: PropTypes.func.isRequired -} - -const accountListItemTextTypo2Props = { - variant: 'caption', - color: 'textSecondary' -} - -const AccountListItemText = ({ primary, secondary }) => { - return ( - - ) -} - -const AccountSwitchListItem = props => { - return ( - - {props.children} - - - - - ) -} - -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 ( - - - {t('AccountSwitch.groups')} - - {t('AccountSwitch.account-counter', accounts.length)} - } - /> - - {sortedGroups.map(group => ( - { - filterByDoc(group) - }} - > - - {t( - 'AccountSwitch.account-counter', - group.accounts.data.filter( - account => account && accountExists(account.id) - ).length - )} - - } - /> - - ))} - - - - - {t('AccountSwitch.accounts')} - {sortedAccounts.map((account, index) => ( - { - filterByDoc(account) - }} - selected={filteringDoc && account._id === filteringDoc._id} - > - - - - - - - - - ))} - - - - ) -} - -AccountSwitchMenu.propTypes = { - filterByDoc: PropTypes.func.isRequired, - resetFilterByDoc: PropTypes.func.isRequired, - filteringDoc: filteringDocPropType -} - -const AccountSwitchWrapper = ({ children }) => { - return
{children}
-} +import AccountSwitchMenu from 'ducks/account/AccountSwitchMenu' +import AccountSwitchSelect from 'ducks/account/AccountSwitchSelect' +import AccountSwitchWrapper from 'ducks/account/AccountSwitchWrapper' const barItemStyle = { overflow: 'hidden', paddingRight: '1rem' } @@ -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() diff --git a/src/ducks/account/AccountSwitchListItem.jsx b/src/ducks/account/AccountSwitchListItem.jsx new file mode 100644 index 0000000000..fdf756cfa6 --- /dev/null +++ b/src/ducks/account/AccountSwitchListItem.jsx @@ -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 ( + + {props.children} + + + + + ) +} + +export default AccountSwitchListItem diff --git a/src/ducks/account/AccountSwitchListItemText.jsx b/src/ducks/account/AccountSwitchListItemText.jsx new file mode 100644 index 0000000000..6c4c648d13 --- /dev/null +++ b/src/ducks/account/AccountSwitchListItemText.jsx @@ -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 ( + + ) +} + +export default AccountSwitchListItemText diff --git a/src/ducks/account/AccountSwitchMenu.jsx b/src/ducks/account/AccountSwitchMenu.jsx new file mode 100644 index 0000000000..31f82f6323 --- /dev/null +++ b/src/ducks/account/AccountSwitchMenu.jsx @@ -0,0 +1,163 @@ +import React, { useCallback, useMemo } from 'react' +import PropTypes from 'prop-types' +import sortBy from 'lodash/sortBy' + +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import Button from 'cozy-ui/transpiled/react/MuiCozyTheme/Buttons' +import List from 'cozy-ui/transpiled/react/MuiCozyTheme/List' +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 CozyTheme from 'cozy-ui/transpiled/react/CozyTheme' + +import { AccountRowIcon } from 'ducks/balance/AccountRow' +import AccountSharingStatus from 'components/AccountSharingStatus' +import { getGroupLabel } from 'ducks/groups/helpers' +import AccountSwitchListItem from 'ducks/account/AccountSwitchListItem' +import AccountSwitchListItemText from 'ducks/account/AccountSwitchListItemText' + +import { + getAccountInstitutionLabel, + getAccountLabel +} from 'ducks/account/helpers.js' + +const filteringDocPropType = PropTypes.oneOfType([ + PropTypes.array, + PropTypes.object +]) + +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 ( + + + {t('AccountSwitch.groups')} + + {t('AccountSwitch.account-counter', accounts.length)} + } + /> + + {sortedGroups.map(group => ( + { + filterByDoc(group) + }} + > + + {t( + 'AccountSwitch.account-counter', + group.accounts.data.filter( + account => account && accountExists(account.id) + ).length + )} + + } + /> + + ))} + + + + + {t('AccountSwitch.accounts')} + {sortedAccounts.map((account, index) => ( + { + filterByDoc(account) + }} + selected={filteringDoc && account._id === filteringDoc._id} + > + + + + + + + + + ))} + + + + ) +} + +AccountSwitchMenu.propTypes = { + filterByDoc: PropTypes.func.isRequired, + resetFilterByDoc: PropTypes.func.isRequired, + filteringDoc: filteringDocPropType +} + +export default AccountSwitchMenu diff --git a/src/ducks/account/AccountSwitchSelect.jsx b/src/ducks/account/AccountSwitchSelect.jsx new file mode 100644 index 0000000000..62cb2c5e19 --- /dev/null +++ b/src/ducks/account/AccountSwitchSelect.jsx @@ -0,0 +1,66 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import DropdownText from 'cozy-ui/transpiled/react/DropdownText' + +import { ACCOUNT_DOCTYPE, GROUP_DOCTYPE } from 'doctypes' +import { getGroupLabel } from 'ducks/groups/helpers' + +import { getAccountLabel } from 'ducks/account/helpers.js' +import styles from 'ducks/account/AccountSwitch.styl' + +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 ( +
+ + {getFilterLabel(filteredAccounts, filteringDoc, accounts, t)} + +
+ ) +} + +AccountSwitchSelect.propTypes = { + t: PropTypes.func.isRequired +} + +export default AccountSwitchSelect diff --git a/src/ducks/account/AccountSwitchWrapper.jsx b/src/ducks/account/AccountSwitchWrapper.jsx new file mode 100644 index 0000000000..fb4347b4f7 --- /dev/null +++ b/src/ducks/account/AccountSwitchWrapper.jsx @@ -0,0 +1,10 @@ +import React from 'react' +import cx from 'classnames' + +import styles from 'ducks/account/AccountSwitch.styl' + +const AccountSwitchWrapper = ({ children }) => { + return
{children}
+} + +export default AccountSwitchWrapper