fix: style matching bank transactions

This commit is contained in:
Ahmed Bouhuolia
2024-07-03 19:41:43 +02:00
parent a5eb42edaf
commit b8a0a5509d
14 changed files with 104 additions and 104 deletions

View File

@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { AppShellProvider, useAppShellContext } from './AppContentShellProvider'; import { AppShellProvider, useAppShellContext } from './AppContentShellProvider';
import { Box, BoxProps } from '../../Layout'; import { Box, BoxProps } from '../../Layout';
import styles from './AppShell.module.scss'; import styles from './AppContentShell.module.scss';
interface AppContentShellProps { interface AppContentShellProps {
topbarOffset?: number; topbarOffset?: number;

View File

@@ -0,0 +1,19 @@
.root{
display: flex;
flex-direction: row;
gap: 10px;
margin-bottom: 14px;
}
.tag{
min-height: 26px;
&:global(.bp4-minimal:not([class*='bp4-intent-'])) {
background: #fff;
border: 1px solid #e1e2e8;
&:global(.bp4-interactive:hover) {
background-color: rgba(143, 153, 168, 0.05);
}
}
}

View File

@@ -0,0 +1,42 @@
import { Tag } from '@blueprintjs/core';
import { useUncontrolled } from '@/hooks/useUncontrolled';
import { Box } from '../Layout';
import styles from './TagsControl.module.scss';
interface TagsControProps {
options: Array<{ label: string; value: string }>;
initialValue?: string;
value?: string;
onValueChange?: (value: string) => void;
}
export function TagsControl({
options,
initialValue,
value,
onValueChange,
}: TagsControProps) {
const [_value, handleChange] = useUncontrolled<string>({
initialValue,
value,
onChange: onValueChange,
finalValue: '',
});
return (
<Box className={styles.root}>
{options.map((option, index) => (
<Tag
key={index}
round
interactive
onClick={() => handleChange(option.value)}
minimal={option.value !== _value}
className={styles.tag}
>
{option.label}
</Tag>
))}
</Box>
);
}

View File

@@ -0,0 +1 @@
export * from './TagsControl';

View File

@@ -3,9 +3,11 @@ import { DashboardPageContent } from '@/components';
import { RulesListBoot } from './RulesListBoot'; import { RulesListBoot } from './RulesListBoot';
import { RulesListActionsBar } from './RulesListActionsBar'; import { RulesListActionsBar } from './RulesListActionsBar';
import { BankRulesTable } from './RulesTable'; import { BankRulesTable } from './RulesTable';
import React from 'react';
/** /**
* * Renders the rules landing page.
* @returns {React.ReactNode}
*/ */
export function RulesList() { export function RulesList() {
return ( return (

View File

@@ -17,7 +17,8 @@ import { useRulesListBoot } from './RulesListBoot';
import { DialogsName } from '@/constants/dialogs'; import { DialogsName } from '@/constants/dialogs';
/** /**
* Invoices datatable. * Retrieves the rules table.
* @returns {React.ReactNode}
*/ */
function RulesTable({ function RulesTable({
// #withAlertsActions // #withAlertsActions

View File

@@ -1,30 +1,8 @@
// @ts-nocheck // @ts-nocheck
import styled from 'styled-components';
import { Tag } from '@blueprintjs/core';
import { useAppQueryString } from '@/hooks'; import { useAppQueryString } from '@/hooks';
import { useUncontrolled } from '@/hooks/useUncontrolled';
import { Group } from '@/components'; import { Group } from '@/components';
import { useAccountTransactionsContext } from './AccountTransactionsProvider'; import { useAccountTransactionsContext } from './AccountTransactionsProvider';
import { TagsControl } from '@/components/TagsControl';
const Root = styled.div`
display: flex;
flex-direction: row;
gap: 10px;
margin-bottom: 14px;
`;
const FilterTag = styled(Tag)`
min-height: 26px;
&.bp4-minimal:not([class*='bp4-intent-']) {
background: #fff;
border: 1px solid #e1e2e8;
&.bp4-interactive:hover {
background-color: rgba(143, 153, 168, 0.05);
}
}
`;
export function AccountTransactionsUncategorizeFilter() { export function AccountTransactionsUncategorizeFilter() {
const { bankAccountMetaSummary } = useAccountTransactionsContext(); const { bankAccountMetaSummary } = useAccountTransactionsContext();
@@ -40,7 +18,7 @@ export function AccountTransactionsUncategorizeFilter() {
return ( return (
<Group position={'apart'}> <Group position={'apart'}>
<SegmentedTabs <TagsControl
options={[ options={[
{ {
value: 'all', value: 'all',
@@ -62,7 +40,7 @@ export function AccountTransactionsUncategorizeFilter() {
value={locationQuery?.uncategorizedFilter || 'all'} value={locationQuery?.uncategorizedFilter || 'all'}
onValueChange={handleTabsChange} onValueChange={handleTabsChange}
/> />
<SegmentedTabs <TagsControl
options={[{ value: 'excluded', label: 'Excluded' }]} options={[{ value: 'excluded', label: 'Excluded' }]}
value={locationQuery?.uncategorizedFilter || 'all'} value={locationQuery?.uncategorizedFilter || 'all'}
onValueChange={handleTabsChange} onValueChange={handleTabsChange}
@@ -70,33 +48,3 @@ export function AccountTransactionsUncategorizeFilter() {
</Group> </Group>
); );
} }
interface SegmentedTabs {
options: Array<{ label: string; value: string }>;
initialValue?: string;
value?: string;
onValueChange?: (value: string) => void;
}
function SegmentedTabs({ options, initialValue, value, onValueChange }) {
const [_value, handleChange] = useUncontrolled({
initialValue,
value,
onChange: onValueChange,
});
return (
<Root>
{options.map((option, index) => (
<FilterTag
key={index}
round
interactive
onClick={() => handleChange(option.value)}
minimal={option.value !== _value}
>
{option.label}
</FilterTag>
))}
</Root>
);
}

View File

@@ -1,6 +1,7 @@
// @ts-nocheck // @ts-nocheck
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { Intent } from '@blueprintjs/core';
import { import {
DataTable, DataTable,
@@ -12,21 +13,17 @@ import {
} from '@/components'; } from '@/components';
import { TABLES } from '@/constants/tables'; import { TABLES } from '@/constants/tables';
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
import { useMemorizedColumnsWidths } from '@/hooks'; import { useMemorizedColumnsWidths } from '@/hooks';
import { useExcludedTransactionsColumns } from './_utils'; import { useExcludedTransactionsColumns } from './_utils';
import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot'; import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot';
import { compose } from '@/utils';
import { ActionsMenu } from './_components'; import { ActionsMenu } from './_components';
import { useUnexcludeUncategorizedTransaction } from '@/hooks/query/bank-rules'; import { useUnexcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
import { Intent } from '@blueprintjs/core';
/** /**
* Renders the recognized account transactions datatable. * Renders the recognized account transactions datatable.
*/ */
function ExcludedTransactionsTableRoot() { export function ExcludedTransactionsTable() {
const { excludedBankTransactions } = useExcludedTransactionsBoot(); const { excludedBankTransactions } = useExcludedTransactionsBoot();
const { mutateAsync: unexcludeBankTransaction } = const { mutateAsync: unexcludeBankTransaction } =
useUnexcludeUncategorizedTransaction(); useUnexcludeUncategorizedTransaction();
@@ -54,7 +51,7 @@ function ExcludedTransactionsTableRoot() {
AppToaster.show({ AppToaster.show({
message: 'Something went wrong.', message: 'Something went wrong.',
intent: Intent.DANGER, intent: Intent.DANGER,
}); });
}); });
}; };
@@ -90,10 +87,6 @@ function ExcludedTransactionsTableRoot() {
); );
} }
export const ExcludedTransactionsTable = compose(withDrawerActions)(
ExcludedTransactionsTableRoot,
);
const DashboardConstrantTable = styled(DataTable)` const DashboardConstrantTable = styled(DataTable)`
.table { .table {
.thead { .thead {

View File

@@ -1,6 +1,7 @@
// @ts-nocheck // @ts-nocheck
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { Intent, Text } from '@blueprintjs/core';
import { import {
DataTable, DataTable,
@@ -8,15 +9,11 @@ import {
TableSkeletonRows, TableSkeletonRows,
TableSkeletonHeader, TableSkeletonHeader,
TableVirtualizedListRows, TableVirtualizedListRows,
FormattedMessage as T,
AppToaster, AppToaster,
Stack, Stack,
} from '@/components'; } from '@/components';
import { TABLES } from '@/constants/tables'; import { TABLES } from '@/constants/tables';
import withAlertsActions from '@/containers/Alert/withAlertActions';
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
import { useMemorizedColumnsWidths } from '@/hooks'; import { useMemorizedColumnsWidths } from '@/hooks';
import { useUncategorizedTransactionsColumns } from './_utils'; import { useUncategorizedTransactionsColumns } from './_utils';
import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot'; import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot';
@@ -24,7 +21,6 @@ import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot
import { ActionsMenu } from './_components'; import { ActionsMenu } from './_components';
import { compose } from '@/utils'; import { compose } from '@/utils';
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules'; import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
import { Intent, Text } from '@blueprintjs/core';
import { import {
WithBankingActionsProps, WithBankingActionsProps,
withBankingActions, withBankingActions,
@@ -37,15 +33,6 @@ interface RecognizedTransactionsTableProps extends WithBankingActionsProps {}
* Renders the recognized account transactions datatable. * Renders the recognized account transactions datatable.
*/ */
function RecognizedTransactionsTableRoot({ function RecognizedTransactionsTableRoot({
// #withSettings
cashflowTansactionsTableSize,
// #withAlertsActions
openAlert,
// #withDrawerActions
openDrawer,
// #withBanking // #withBanking
setUncategorizedTransactionIdForMatching, setUncategorizedTransactionIdForMatching,
}: RecognizedTransactionsTableProps) { }: RecognizedTransactionsTableProps) {
@@ -125,11 +112,9 @@ function RecognizedTransactionsTableRoot({
); );
} }
export const RecognizedTransactionsTable = compose( export const RecognizedTransactionsTable = compose(withBankingActions)(
withAlertsActions, RecognizedTransactionsTableRoot,
withDrawerActions, );
withBankingActions,
)(RecognizedTransactionsTableRoot);
const DashboardConstrantTable = styled(DataTable)` const DashboardConstrantTable = styled(DataTable)`
.table { .table {

View File

@@ -72,7 +72,8 @@ function CategorizeTransactionBoot({
recognizedTranasction, recognizedTranasction,
isRecognizedTransactionLoading, isRecognizedTransactionLoading,
}; };
const isLoading = isBranchesLoading || isAccountsLoading; const isLoading =
isBranchesLoading || isAccountsLoading || isRecognizedTransactionLoading;
if (isLoading) { if (isLoading) {
<Spinner size={30} />; <Spinner size={30} />;

View File

@@ -1,11 +1,11 @@
// @ts-nocheck // @ts-nocheck
import clsx from 'classnames'; import clsx from 'classnames';
import { Group, Stack } from '@/components';
import { Checkbox, Text } from '@blueprintjs/core'; import { Checkbox, Text } from '@blueprintjs/core';
import styles from './MatchTransaction.module.scss';
import { useUncontrolled } from '@/hooks/useUncontrolled'; import { useUncontrolled } from '@/hooks/useUncontrolled';
import { Group, Stack } from '@/components';
import styles from './MatchTransactionCheckbox.module.scss';
export interface MatchTransactionProps { export interface MatchTransactionCheckboxProps {
active?: boolean; active?: boolean;
initialActive?: boolean; initialActive?: boolean;
onChange?: (state: boolean) => void; onChange?: (state: boolean) => void;
@@ -13,13 +13,13 @@ export interface MatchTransactionProps {
date: string; date: string;
} }
export function MatchTransaction({ export function MatchTransactionCheckbox({
active, active,
initialActive, initialActive,
onChange, onChange,
label, label,
date, date,
}: MatchTransactionProps) { }: MatchTransactionCheckboxProps) {
const [_active, handleChange] = useUncontrolled<boolean>({ const [_active, handleChange] = useUncontrolled<boolean>({
value: active, value: active,
initialValue: initialActive, initialValue: initialActive,

View File

@@ -8,7 +8,10 @@ import {
MatchingTransactionBoot, MatchingTransactionBoot,
useMatchingTransactionBoot, useMatchingTransactionBoot,
} from './MatchingTransactionBoot'; } from './MatchingTransactionBoot';
import { MatchTransaction, MatchTransactionProps } from './MatchTransaction'; import {
MatchTransactionCheckbox,
MatchTransactionCheckboxProps,
} from './MatchTransactionCheckbox';
import { useMatchUncategorizedTransaction } from '@/hooks/query/bank-rules'; import { useMatchUncategorizedTransaction } from '@/hooks/query/bank-rules';
import { MatchingTransactionFormValues } from './types'; import { MatchingTransactionFormValues } from './types';
import { import {
@@ -27,6 +30,10 @@ const initialValues = {
matched: {}, matched: {},
}; };
/**
* Renders the bank transaction matching form.
* @returns {React.ReactNode}
*/
function MatchingBankTransactionRoot({ function MatchingBankTransactionRoot({
// #withBankingActions // #withBankingActions
closeMatchingTransactionAside, closeMatchingTransactionAside,
@@ -89,7 +96,7 @@ function MatchingBankTransactionContent() {
return ( return (
<Box className={styles.root}> <Box className={styles.root}>
<PerfectMatchingTransactions /> <PerfectMatchingTransactions />
<GoodMatchingTransactions /> <PossibleMatchingTransactions />
</Box> </Box>
); );
} }
@@ -135,7 +142,7 @@ function PerfectMatchingTransactions() {
* Renders the possible match transactions. * Renders the possible match transactions.
* @returns {React.ReactNode} * @returns {React.ReactNode}
*/ */
function GoodMatchingTransactions() { function PossibleMatchingTransactions() {
const { possibleMatches } = useMatchingTransactionBoot(); const { possibleMatches } = useMatchingTransactionBoot();
// Can't continue if the possible matches is emoty. // Can't continue if the possible matches is emoty.
@@ -168,7 +175,10 @@ function GoodMatchingTransactions() {
); );
} }
interface MatchTransactionFieldProps interface MatchTransactionFieldProps
extends Omit<MatchTransactionProps, 'onChange' | 'active' | 'initialActive'> { extends Omit<
MatchTransactionCheckboxProps,
'onChange' | 'active' | 'initialActive'
> {
transactionId: number; transactionId: number;
transactionType: string; transactionType: string;
} }
@@ -183,7 +193,7 @@ function MatchTransactionField({
return ( return (
<FastField name={name}> <FastField name={name}>
{({ form, field: { value } }: FastFieldProps) => ( {({ form, field: { value } }: FastFieldProps) => (
<MatchTransaction <MatchTransactionCheckbox
{...props} {...props}
active={!!value} active={!!value}
onChange={(state) => { onChange={(state) => {
@@ -195,10 +205,6 @@ function MatchTransactionField({
); );
} }
export function CategorizeBankTransactionContent() {
return <h1>Categorizing</h1>;
}
interface MatchTransctionFooterProps extends WithBankingActionsProps {} interface MatchTransctionFooterProps extends WithBankingActionsProps {}
/** /**
@@ -210,6 +216,7 @@ const MatchTransactionFooter = R.compose(withBankingActions)(
const { submitForm, isSubmitting } = useFormikContext(); const { submitForm, isSubmitting } = useFormikContext();
const totalPending = useGetPendingAmountMatched(); const totalPending = useGetPendingAmountMatched();
const showReconcileLink = useIsShowReconcileTransactionLink(); const showReconcileLink = useIsShowReconcileTransactionLink();
const submitDisabled = totalPending !== 0;
const handleCancelBtnClick = () => { const handleCancelBtnClick = () => {
closeMatchingTransactionAside(); closeMatchingTransactionAside();
@@ -243,6 +250,7 @@ const MatchTransactionFooter = R.compose(withBankingActions)(
style={{ minWidth: 85 }} style={{ minWidth: 85 }}
onClick={handleSubmitBtnClick} onClick={handleSubmitBtnClick}
loading={isSubmitting} loading={isSubmitting}
disabled={submitDisabled}
> >
Match Match
</Button> </Button>

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react'; import { useState } from 'react';
interface UseUncontrolledInput<T> { interface UseUncontrolledInput<T> {
/** Value for controlled state */ /** Value for controlled state */
@@ -19,7 +19,7 @@ export function useUncontrolled<T>({
initialValue, initialValue,
finalValue, finalValue,
onChange = () => {}, onChange = () => {},
}: UseUncontrolledInput<T>) { }: UseUncontrolledInput<T>): [T, (value: T) => void, boolean] {
const [uncontrolledValue, setUncontrolledValue] = useState( const [uncontrolledValue, setUncontrolledValue] = useState(
initialValue !== undefined ? initialValue : finalValue, initialValue !== undefined ? initialValue : finalValue,
); );