Merge pull request #658 from bigcapitalhq/banking-layout-breaking

feat: Bank pages layout breaking
This commit is contained in:
Ahmed Bouhuolia
2024-09-04 09:52:35 +02:00
committed by GitHub
3 changed files with 142 additions and 28 deletions

View File

@@ -34,21 +34,23 @@ import {
} from '@/constants/cashflowOptions'; } from '@/constants/cashflowOptions';
import { useRefreshCashflowTransactions } from '@/hooks/query'; import { useRefreshCashflowTransactions } from '@/hooks/query';
import { useAccountTransactionsContext } from './AccountTransactionsProvider'; import { useAccountTransactionsContext } from './AccountTransactionsProvider';
import { useMediaQuery } from '@/hooks/useMediaQuery';
import { useAppShellContext } from '@/components/AppShell/AppContentShell/AppContentShellProvider';
import withDialogActions from '@/containers/Dialog/withDialogActions'; import withDialogActions from '@/containers/Dialog/withDialogActions';
import withSettings from '@/containers/Settings/withSettings'; import withSettings from '@/containers/Settings/withSettings';
import withSettingsActions from '@/containers/Settings/withSettingsActions'; import withSettingsActions from '@/containers/Settings/withSettingsActions';
import { withBankingActions } from '../withBankingActions';
import { compose } from '@/utils'; import { withBanking } from '../withBanking';
import withAlertActions from '@/containers/Alert/withAlertActions';
import { import {
useUpdateBankAccount, useUpdateBankAccount,
useExcludeUncategorizedTransactions, useExcludeUncategorizedTransactions,
useUnexcludeUncategorizedTransactions, useUnexcludeUncategorizedTransactions,
} from '@/hooks/query/bank-rules'; } from '@/hooks/query/bank-rules';
import { withBankingActions } from '../withBankingActions';
import { withBanking } from '../withBanking';
import withAlertActions from '@/containers/Alert/withAlertActions';
import { DialogsName } from '@/constants/dialogs'; import { DialogsName } from '@/constants/dialogs';
import { compose } from '@/utils';
function AccountTransactionsActionsBar({ function AccountTransactionsActionsBar({
// #withDialogActions // #withDialogActions
@@ -221,6 +223,13 @@ function AccountTransactionsActionsBar({
}); });
}; };
const { hideAside } = useAppShellContext();
const isMin1350Query = useMediaQuery('(min-width: 1350px)');
// Shrink actions to dropdown if the aside is open and matched the media query,
// To avoid actions overflow in small screens.
const shrinkActions = !hideAside && !isMin1350Query;
return ( return (
<DashboardActionsBar> <DashboardActionsBar>
<NavbarGroup> <NavbarGroup>
@@ -241,23 +250,27 @@ function AccountTransactionsActionsBar({
}} }}
/> />
<NavbarDivider /> <NavbarDivider />
<Button
className={Classes.MINIMAL} <If condition={!shrinkActions}>
icon={<Icon icon="print-16" iconSize={16} />} <Button
text={<T id={'print'} />} className={Classes.MINIMAL}
/> icon={<Icon icon="print-16" iconSize={16} />}
<Button text={<T id={'print'} />}
className={Classes.MINIMAL} />
icon={<Icon icon="file-export-16" iconSize={16} />} <Button
text={<T id={'export'} />} className={Classes.MINIMAL}
/> icon={<Icon icon="file-export-16" iconSize={16} />}
<Button text={<T id={'export'} />}
className={Classes.MINIMAL} />
icon={<Icon icon="file-import-16" iconSize={16} />} <Button
text={<T id={'import'} />} className={Classes.MINIMAL}
onClick={handleImportBtnClick} icon={<Icon icon="file-import-16" iconSize={16} />}
/> text={<T id={'import'} />}
<NavbarDivider /> onClick={handleImportBtnClick}
/>
<NavbarDivider />
</If>
<DashboardRowsHeightButton <DashboardRowsHeightButton
initialValue={cashflowTansactionsTableSize} initialValue={cashflowTansactionsTableSize}
onChange={handleTableRowSizeChange} onChange={handleTableRowSizeChange}
@@ -290,6 +303,40 @@ function AccountTransactionsActionsBar({
</Tooltip> </Tooltip>
</If> </If>
<If condition={shrinkActions}>
<NavbarDivider />
<Popover
minimal={true}
interactionKind={PopoverInteractionKind.CLICK}
position={Position.BOTTOM_LEFT}
modifiers={{
offset: { offset: '0, 4' },
}}
content={
<Menu>
<MenuItem
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<MenuItem
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<MenuItem
icon={<Icon icon="file-import-16" iconSize={16} />}
text={<T id={'import'} />}
onClick={handleImportBtnClick}
/>
</Menu>
}
>
<Button
icon={<Icon icon="more-h-16" iconSize={16} />}
minimal={true}
/>
</Popover>
</If>
{!isEmpty(uncategorizedTransationsIdsSelected) && ( {!isEmpty(uncategorizedTransationsIdsSelected) && (
<Button <Button
icon={<Icon icon="disable" iconSize={16} />} icon={<Icon icon="disable" iconSize={16} />}
@@ -368,7 +415,6 @@ function AccountTransactionsActionsBar({
</If> </If>
<MenuItem onClick={handleBankRulesClick} text={'Bank rules'} /> <MenuItem onClick={handleBankRulesClick} text={'Bank rules'} />
<MenuDivider /> <MenuDivider />
<If condition={isSyncingOwner && isFeedsActive}> <If condition={isSyncingOwner && isFeedsActive}>
<MenuItem <MenuItem

View File

@@ -2,6 +2,8 @@
import React from 'react'; import React from 'react';
import intl from 'react-intl-universal'; import intl from 'react-intl-universal';
import styled from 'styled-components'; import styled from 'styled-components';
import { curry } from 'lodash/fp';
import { useHistory } from 'react-router-dom';
import { import {
Popover, Popover,
Menu, Menu,
@@ -11,10 +13,9 @@ import {
Classes, Classes,
} from '@blueprintjs/core'; } from '@blueprintjs/core';
import { Icon } from '@/components'; import { Icon } from '@/components';
import { useHistory } from 'react-router-dom';
import { curry } from 'lodash/fp';
import { useAccountTransactionsContext } from './AccountTransactionsProvider'; import { useAccountTransactionsContext } from './AccountTransactionsProvider';
import { useAppShellContext } from '@/components/AppShell/AppContentShell/AppContentShellProvider';
function AccountSwitchButton() { function AccountSwitchButton() {
const { currentAccount } = useAccountTransactionsContext(); const { currentAccount } = useAccountTransactionsContext();
@@ -22,7 +23,7 @@ function AccountSwitchButton() {
return ( return (
<AccountSwitchButtonBase <AccountSwitchButtonBase
minimal={true} minimal={true}
rightIcon={<Icon icon={'arrow-drop-down'} iconSize={24} />} rightIcon={<Icon icon={'caret-down-16'} iconSize={16} />}
> >
<AccountSwitchText>{currentAccount.name}</AccountSwitchText> <AccountSwitchText>{currentAccount.name}</AccountSwitchText>
</AccountSwitchButtonBase> </AccountSwitchButtonBase>
@@ -110,12 +111,16 @@ function AccountTransactionsDetailsBarSkeleton() {
} }
function AccountTransactionsDetailsContent() { function AccountTransactionsDetailsContent() {
const { hideAside } = useAppShellContext();
return ( return (
<React.Fragment> <React.Fragment>
<AccountSwitchItem /> <AccountSwitchItem />
<AccountNumberItem />
{/** Hide some details once the aside opens to preserve space on details bar. */}
{hideAside && <AccountNumberItem />}
<AccountBalanceItem /> <AccountBalanceItem />
<AccountBankBalanceItem /> {hideAside && <AccountBankBalanceItem />}
</React.Fragment> </React.Fragment>
); );
} }

View File

@@ -0,0 +1,63 @@
import { useEffect, useRef, useState } from 'react';
export interface UseMediaQueryOptions {
getInitialValueInEffect: boolean;
}
type MediaQueryCallback = (event: { matches: boolean; media: string }) => void;
/**
* Older versions of Safari (shipped withCatalina and before) do not support addEventListener on matchMedia
* https://stackoverflow.com/questions/56466261/matchmedia-addlistener-marked-as-deprecated-addeventlistener-equivalent
* */
function attachMediaListener(
query: MediaQueryList,
callback: MediaQueryCallback,
) {
try {
query.addEventListener('change', callback);
return () => query.removeEventListener('change', callback);
} catch (e) {
query.addListener(callback);
return () => query.removeListener(callback);
}
}
function getInitialValue(query: string, initialValue?: boolean) {
if (typeof initialValue === 'boolean') {
return initialValue;
}
if (typeof window !== 'undefined' && 'matchMedia' in window) {
return window.matchMedia(query).matches;
}
return false;
}
export function useMediaQuery(
query: string,
initialValue?: boolean,
{ getInitialValueInEffect }: UseMediaQueryOptions = {
getInitialValueInEffect: true,
},
) {
const [matches, setMatches] = useState(
getInitialValueInEffect ? initialValue : getInitialValue(query),
);
const queryRef = useRef<MediaQueryList>();
useEffect(() => {
if ('matchMedia' in window) {
queryRef.current = window.matchMedia(query);
setMatches(queryRef.current.matches);
return attachMediaListener(queryRef.current, (event) =>
setMatches(event.matches),
);
}
return undefined;
}, [query]);
return matches;
}