Skip to content

Commit

Permalink
Update sidebar scrolling (#3554)
Browse files Browse the repository at this point in the history
  • Loading branch information
tlesicka authored Oct 9, 2024
1 parent e455369 commit 21cb684
Show file tree
Hide file tree
Showing 110 changed files with 194 additions and 155 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
227 changes: 125 additions & 102 deletions packages/desktop-client/src/components/sidebar/Accounts.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,32 @@
// @ts-strict-ignore
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';

import { moveAccount } from 'loot-core/src/client/actions';
import * as queries from 'loot-core/src/client/queries';
import { type State } from 'loot-core/src/client/state-types';
import { type AccountEntity } from 'loot-core/types/models';

import { useAccounts } from '../../hooks/useAccounts';
import { useBudgetedAccounts } from '../../hooks/useBudgetedAccounts';
import { useClosedAccounts } from '../../hooks/useClosedAccounts';
import { useFailedAccounts } from '../../hooks/useFailedAccounts';
import { useLocalPref } from '../../hooks/useLocalPref';
import { useOffBudgetAccounts } from '../../hooks/useOffBudgetAccounts';
import { useUpdatedAccounts } from '../../hooks/useUpdatedAccounts';
import { SvgAdd } from '../../icons/v1';
import { theme } from '../../style';
import { View } from '../common/View';
import { type OnDropCallback } from '../sort';

import { Account } from './Account';
import { SecondaryItem } from './SecondaryItem';

const fontWeight = 600;

type AccountsProps = {
onAddAccount: () => void;
onToggleClosedAccounts: () => void;
onReorder: OnDropCallback;
};

export function Accounts({
onAddAccount,
onToggleClosedAccounts,
onReorder,
}: AccountsProps) {
export function Accounts() {
const { t } = useTranslation();
const dispatch = useDispatch();
const [isDragging, setIsDragging] = useState(false);
const accounts = useAccounts();
const failedAccounts = useFailedAccounts();
const updatedAccounts = useUpdatedAccounts();
const offbudgetAccounts = useOffBudgetAccounts();
Expand All @@ -43,126 +36,156 @@ export function Accounts({
(state: State) => state.account.accountsSyncing,
);

const getAccountPath = account => `/accounts/${account.id}`;
const getAccountPath = (account: AccountEntity) => `/accounts/${account.id}`;

const [showClosedAccounts] = useLocalPref('ui.showClosedAccounts');
const [showClosedAccounts, setShowClosedAccountsPref] = useLocalPref(
'ui.showClosedAccounts',
);

function onDragChange(drag) {
function onDragChange(drag: { state: string }) {
setIsDragging(drag.state === 'start');
}

const makeDropPadding = i => {
const makeDropPadding = (i: number) => {
if (i === 0) {
return {
paddingTop: isDragging ? 15 : 0,
marginTop: isDragging ? -15 : 0,
};
}
return null;
return undefined;
};

async function onReorder(
id: string,
dropPos: 'top' | 'bottom',
targetId: unknown,
) {
let targetIdToMove = targetId;
if (dropPos === 'bottom') {
const idx = accounts.findIndex(a => a.id === targetId) + 1;
targetIdToMove = idx < accounts.length ? accounts[idx].id : null;
}

dispatch(moveAccount(id, targetIdToMove));
}

const onToggleClosedAccounts = () => {
setShowClosedAccountsPref(!showClosedAccounts);
};

return (
<View>
<Account
name={t('All accounts')}
to="/accounts"
query={queries.allAccountBalance()}
style={{ fontWeight, marginTop: 15 }}
<View
style={{
flexGrow: 1,
'@media screen and (max-height: 480px)': {
minHeight: 'auto',
},
}}
>
<View
style={{
height: 1,
backgroundColor: theme.sidebarItemBackgroundHover,
marginTop: 15,
flexShrink: 0,
}}
/>

{budgetedAccounts.length > 0 && (
<View style={{ overflow: 'auto' }}>
<Account
name={t('For budget')}
to="/accounts/budgeted"
query={queries.budgetedAccountBalance()}
style={{
fontWeight,
marginTop: 13,
marginBottom: 5,
}}
name={t('All accounts')}
to="/accounts"
query={queries.allAccountBalance()}
style={{ fontWeight, marginTop: 15 }}
/>
)}

{budgetedAccounts.map((account, i) => (
<Account
key={account.id}
name={account.name}
account={account}
connected={!!account.bank}
pending={syncingAccountIds.includes(account.id)}
failed={failedAccounts && failedAccounts.has(account.id)}
updated={updatedAccounts && updatedAccounts.includes(account.id)}
to={getAccountPath(account)}
query={queries.accountBalance(account)}
onDragChange={onDragChange}
onDrop={onReorder}
outerStyle={makeDropPadding(i)}
/>
))}
{budgetedAccounts.length > 0 && (
<Account
name={t('For budget')}
to="/accounts/budgeted"
query={queries.budgetedAccountBalance()}
style={{
fontWeight,
marginTop: 13,
marginBottom: 5,
}}
/>
)}

{offbudgetAccounts.length > 0 && (
<Account
name={t('Off budget')}
to="/accounts/offbudget"
query={queries.offbudgetAccountBalance()}
style={{
fontWeight,
marginTop: 13,
marginBottom: 5,
}}
/>
)}
{budgetedAccounts.map((account, i) => (
<Account
key={account.id}
name={account.name}
account={account}
connected={!!account.bank}
pending={syncingAccountIds.includes(account.id)}
failed={failedAccounts?.has(account.id)}
updated={updatedAccounts?.includes(account.id)}
to={getAccountPath(account)}
query={queries.accountBalance(account)}
onDragChange={onDragChange}
onDrop={onReorder}
outerStyle={makeDropPadding(i)}
/>
))}

{offbudgetAccounts.map((account, i) => (
<Account
key={account.id}
name={account.name}
account={account}
connected={!!account.bank}
pending={syncingAccountIds.includes(account.id)}
failed={failedAccounts && failedAccounts.has(account.id)}
updated={updatedAccounts && updatedAccounts.includes(account.id)}
to={getAccountPath(account)}
query={queries.accountBalance(account)}
onDragChange={onDragChange}
onDrop={onReorder}
outerStyle={makeDropPadding(i)}
/>
))}

{closedAccounts.length > 0 && (
<SecondaryItem
style={{ marginTop: 15 }}
title={
showClosedAccounts ? t('Closed accounts') : t('Closed accounts...')
}
onClick={onToggleClosedAccounts}
bold
/>
)}
{offbudgetAccounts.length > 0 && (
<Account
name={t('Off budget')}
to="/accounts/offbudget"
query={queries.offbudgetAccountBalance()}
style={{
fontWeight,
marginTop: 13,
marginBottom: 5,
}}
/>
)}

{showClosedAccounts &&
closedAccounts.map(account => (
{offbudgetAccounts.map((account, i) => (
<Account
key={account.id}
name={account.name}
account={account}
connected={!!account.bank}
pending={syncingAccountIds.includes(account.id)}
failed={failedAccounts?.has(account.id)}
updated={updatedAccounts?.includes(account.id)}
to={getAccountPath(account)}
query={queries.accountBalance(account)}
onDragChange={onDragChange}
onDrop={onReorder}
outerStyle={makeDropPadding(i)}
/>
))}

<SecondaryItem
style={{
marginTop: 15,
marginBottom: 9,
}}
onClick={onAddAccount}
Icon={SvgAdd}
title={t('Add account')}
/>
{closedAccounts.length > 0 && (
<SecondaryItem
style={{ marginTop: 15 }}
title={
showClosedAccounts
? t('Closed accounts')
: t('Closed accounts...')
}
onClick={onToggleClosedAccounts}
bold
/>
)}

{showClosedAccounts &&
closedAccounts.map(account => (
<Account
key={account.id}
name={account.name}
account={account}
to={getAccountPath(account)}
query={queries.accountBalance(account)}
onDragChange={onDragChange}
onDrop={onReorder}
/>
))}
</View>
</View>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ import {
SvgCheveronDown,
SvgCheveronRight,
SvgCog,
SvgReports,
SvgStoreFront,
SvgTuning,
SvgWallet,
} from '../../icons/v1';
import { SvgCalendar } from '../../icons/v2';
import { View } from '../common/View';

import { Item } from './Item';
import { SecondaryItem } from './SecondaryItem';

export function Tools() {
export function PrimaryButtons() {
const { t } = useTranslation();
const [isOpen, setOpen] = useState(false);
const onToggle = useCallback(() => setOpen(open => !open), []);
Expand All @@ -28,10 +31,13 @@ export function Tools() {
if (isActive) {
setOpen(true);
}
}, [location.pathname]);
}, [isActive, location.pathname]);

return (
<View style={{ flexShrink: 0 }}>
<Item title={t('Budget')} Icon={SvgWallet} to="/budget" />
<Item title={t('Reports')} Icon={SvgReports} to="/reports" />
<Item title={t('Schedules')} Icon={SvgCalendar} to="/schedules" />
<Item
title="More"
Icon={isOpen ? SvgCheveronDown : SvgCheveronRight}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { type ComponentType, type SVGProps } from 'react';

import { View } from '../common/View';

import { SecondaryItem } from './SecondaryItem';

type SecondaryButtonItems = {
title: string;
Icon:
| ComponentType<SVGProps<SVGElement>>
| ComponentType<SVGProps<SVGSVGElement>>;
onClick: () => void;
};

type SecondaryButtonsProps = {
buttons: Array<SecondaryButtonItems>;
};

export function SecondaryButtons({ buttons }: SecondaryButtonsProps) {
return (
<View
style={{
flexShrink: 0,
padding: '5px 0',
}}
>
{buttons.map(item => (
<SecondaryItem
key={item.title}
title={item.title}
Icon={item.Icon}
onClick={item.onClick}
/>
))}
</View>
);
}
Loading

0 comments on commit 21cb684

Please sign in to comment.