diff --git a/packages/webapp/src/components/AppShell/AppContentShell/AppContentShell.tsx b/packages/webapp/src/components/AppShell/AppContentShell/AppContentShell.tsx index 6ebbfb8b1..da442eb6e 100644 --- a/packages/webapp/src/components/AppShell/AppContentShell/AppContentShell.tsx +++ b/packages/webapp/src/components/AppShell/AppContentShell/AppContentShell.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { AppShellProvider, useAppShellContext } from './AppContentShellProvider'; import { Box, BoxProps } from '../../Layout'; -import styles from './AppShell.module.scss'; +import styles from './AppContentShell.module.scss'; interface AppContentShellProps { topbarOffset?: number; diff --git a/packages/webapp/src/components/TagsControl/TagsControl.module.scss b/packages/webapp/src/components/TagsControl/TagsControl.module.scss new file mode 100644 index 000000000..e548e2ced --- /dev/null +++ b/packages/webapp/src/components/TagsControl/TagsControl.module.scss @@ -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); + } + } +} diff --git a/packages/webapp/src/components/TagsControl/TagsControl.tsx b/packages/webapp/src/components/TagsControl/TagsControl.tsx new file mode 100644 index 000000000..2c4091601 --- /dev/null +++ b/packages/webapp/src/components/TagsControl/TagsControl.tsx @@ -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({ + initialValue, + value, + onChange: onValueChange, + finalValue: '', + }); + + return ( + + {options.map((option, index) => ( + handleChange(option.value)} + minimal={option.value !== _value} + className={styles.tag} + > + {option.label} + + ))} + + ); +} diff --git a/packages/webapp/src/components/TagsControl/index.ts b/packages/webapp/src/components/TagsControl/index.ts new file mode 100644 index 000000000..cb79364f4 --- /dev/null +++ b/packages/webapp/src/components/TagsControl/index.ts @@ -0,0 +1 @@ +export * from './TagsControl'; \ No newline at end of file diff --git a/packages/webapp/src/containers/Banking/Rules/RulesList/RulesList.tsx b/packages/webapp/src/containers/Banking/Rules/RulesList/RulesList.tsx index e241f2923..338178182 100644 --- a/packages/webapp/src/containers/Banking/Rules/RulesList/RulesList.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RulesList/RulesList.tsx @@ -3,9 +3,11 @@ import { DashboardPageContent } from '@/components'; import { RulesListBoot } from './RulesListBoot'; import { RulesListActionsBar } from './RulesListActionsBar'; import { BankRulesTable } from './RulesTable'; +import React from 'react'; /** - * + * Renders the rules landing page. + * @returns {React.ReactNode} */ export function RulesList() { return ( diff --git a/packages/webapp/src/containers/Banking/Rules/RulesList/RulesTable.tsx b/packages/webapp/src/containers/Banking/Rules/RulesList/RulesTable.tsx index 771c5ae16..5228ad1c9 100644 --- a/packages/webapp/src/containers/Banking/Rules/RulesList/RulesTable.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RulesList/RulesTable.tsx @@ -17,7 +17,8 @@ import { useRulesListBoot } from './RulesListBoot'; import { DialogsName } from '@/constants/dialogs'; /** - * Invoices datatable. + * Retrieves the rules table. + * @returns {React.ReactNode} */ function RulesTable({ // #withAlertsActions diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsUncategorizeFilter.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsUncategorizeFilter.tsx index ca42a0b4d..2272c7e54 100644 --- a/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsUncategorizeFilter.tsx +++ b/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsUncategorizeFilter.tsx @@ -1,30 +1,8 @@ // @ts-nocheck -import styled from 'styled-components'; -import { Tag } from '@blueprintjs/core'; import { useAppQueryString } from '@/hooks'; -import { useUncontrolled } from '@/hooks/useUncontrolled'; import { Group } from '@/components'; import { useAccountTransactionsContext } from './AccountTransactionsProvider'; - -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); - } - } -`; +import { TagsControl } from '@/components/TagsControl'; export function AccountTransactionsUncategorizeFilter() { const { bankAccountMetaSummary } = useAccountTransactionsContext(); @@ -40,7 +18,7 @@ export function AccountTransactionsUncategorizeFilter() { return ( - - ); } - -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 ( - - {options.map((option, index) => ( - handleChange(option.value)} - minimal={option.value !== _value} - > - {option.label} - - ))} - - ); -} diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/ExcludedTransactions/ExcludedTransactionsTable.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/ExcludedTransactions/ExcludedTransactionsTable.tsx index 14e959dfa..73c7b8f08 100644 --- a/packages/webapp/src/containers/CashFlow/AccountTransactions/ExcludedTransactions/ExcludedTransactionsTable.tsx +++ b/packages/webapp/src/containers/CashFlow/AccountTransactions/ExcludedTransactions/ExcludedTransactionsTable.tsx @@ -1,6 +1,7 @@ // @ts-nocheck import React from 'react'; import styled from 'styled-components'; +import { Intent } from '@blueprintjs/core'; import { DataTable, @@ -12,21 +13,17 @@ import { } from '@/components'; import { TABLES } from '@/constants/tables'; -import withDrawerActions from '@/containers/Drawer/withDrawerActions'; - import { useMemorizedColumnsWidths } from '@/hooks'; import { useExcludedTransactionsColumns } from './_utils'; import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot'; -import { compose } from '@/utils'; import { ActionsMenu } from './_components'; import { useUnexcludeUncategorizedTransaction } from '@/hooks/query/bank-rules'; -import { Intent } from '@blueprintjs/core'; /** * Renders the recognized account transactions datatable. */ -function ExcludedTransactionsTableRoot() { +export function ExcludedTransactionsTable() { const { excludedBankTransactions } = useExcludedTransactionsBoot(); const { mutateAsync: unexcludeBankTransaction } = useUnexcludeUncategorizedTransaction(); @@ -54,7 +51,7 @@ function ExcludedTransactionsTableRoot() { AppToaster.show({ message: 'Something went wrong.', intent: Intent.DANGER, - }); + }); }); }; @@ -90,10 +87,6 @@ function ExcludedTransactionsTableRoot() { ); } -export const ExcludedTransactionsTable = compose(withDrawerActions)( - ExcludedTransactionsTableRoot, -); - const DashboardConstrantTable = styled(DataTable)` .table { .thead { diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/RecognizedTransactions/RecognizedTransactionsTable.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/RecognizedTransactions/RecognizedTransactionsTable.tsx index 162da1b69..a3732eb6e 100644 --- a/packages/webapp/src/containers/CashFlow/AccountTransactions/RecognizedTransactions/RecognizedTransactionsTable.tsx +++ b/packages/webapp/src/containers/CashFlow/AccountTransactions/RecognizedTransactions/RecognizedTransactionsTable.tsx @@ -1,6 +1,7 @@ // @ts-nocheck import React from 'react'; import styled from 'styled-components'; +import { Intent, Text } from '@blueprintjs/core'; import { DataTable, @@ -8,15 +9,11 @@ import { TableSkeletonRows, TableSkeletonHeader, TableVirtualizedListRows, - FormattedMessage as T, AppToaster, Stack, } from '@/components'; import { TABLES } from '@/constants/tables'; -import withAlertsActions from '@/containers/Alert/withAlertActions'; -import withDrawerActions from '@/containers/Drawer/withDrawerActions'; - import { useMemorizedColumnsWidths } from '@/hooks'; import { useUncategorizedTransactionsColumns } from './_utils'; import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot'; @@ -24,7 +21,6 @@ import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot import { ActionsMenu } from './_components'; import { compose } from '@/utils'; import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules'; -import { Intent, Text } from '@blueprintjs/core'; import { WithBankingActionsProps, withBankingActions, @@ -37,15 +33,6 @@ interface RecognizedTransactionsTableProps extends WithBankingActionsProps {} * Renders the recognized account transactions datatable. */ function RecognizedTransactionsTableRoot({ - // #withSettings - cashflowTansactionsTableSize, - - // #withAlertsActions - openAlert, - - // #withDrawerActions - openDrawer, - // #withBanking setUncategorizedTransactionIdForMatching, }: RecognizedTransactionsTableProps) { @@ -125,11 +112,9 @@ function RecognizedTransactionsTableRoot({ ); } -export const RecognizedTransactionsTable = compose( - withAlertsActions, - withDrawerActions, - withBankingActions, -)(RecognizedTransactionsTableRoot); +export const RecognizedTransactionsTable = compose(withBankingActions)( + RecognizedTransactionsTableRoot, +); const DashboardConstrantTable = styled(DataTable)` .table { diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/CategorizeTransactionBoot.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/CategorizeTransactionBoot.tsx index e528386b4..00729183d 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/CategorizeTransactionBoot.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/CategorizeTransactionBoot.tsx @@ -72,7 +72,8 @@ function CategorizeTransactionBoot({ recognizedTranasction, isRecognizedTransactionLoading, }; - const isLoading = isBranchesLoading || isAccountsLoading; + const isLoading = + isBranchesLoading || isAccountsLoading || isRecognizedTransactionLoading; if (isLoading) { ; diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransaction.module.scss b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransactionCheckbox.module.scss similarity index 100% rename from packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransaction.module.scss rename to packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransactionCheckbox.module.scss diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransaction.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransactionCheckbox.tsx similarity index 86% rename from packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransaction.tsx rename to packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransactionCheckbox.tsx index 18a0729cd..29fcd294c 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransaction.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchTransactionCheckbox.tsx @@ -1,11 +1,11 @@ // @ts-nocheck import clsx from 'classnames'; -import { Group, Stack } from '@/components'; import { Checkbox, Text } from '@blueprintjs/core'; -import styles from './MatchTransaction.module.scss'; import { useUncontrolled } from '@/hooks/useUncontrolled'; +import { Group, Stack } from '@/components'; +import styles from './MatchTransactionCheckbox.module.scss'; -export interface MatchTransactionProps { +export interface MatchTransactionCheckboxProps { active?: boolean; initialActive?: boolean; onChange?: (state: boolean) => void; @@ -13,13 +13,13 @@ export interface MatchTransactionProps { date: string; } -export function MatchTransaction({ +export function MatchTransactionCheckbox({ active, initialActive, onChange, label, date, -}: MatchTransactionProps) { +}: MatchTransactionCheckboxProps) { const [_active, handleChange] = useUncontrolled({ value: active, initialValue: initialActive, diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingTransaction.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingTransaction.tsx index 685659677..8aef55e8e 100644 --- a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingTransaction.tsx +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/MatchingTransaction.tsx @@ -8,7 +8,10 @@ import { MatchingTransactionBoot, useMatchingTransactionBoot, } from './MatchingTransactionBoot'; -import { MatchTransaction, MatchTransactionProps } from './MatchTransaction'; +import { + MatchTransactionCheckbox, + MatchTransactionCheckboxProps, +} from './MatchTransactionCheckbox'; import { useMatchUncategorizedTransaction } from '@/hooks/query/bank-rules'; import { MatchingTransactionFormValues } from './types'; import { @@ -27,6 +30,10 @@ const initialValues = { matched: {}, }; +/** + * Renders the bank transaction matching form. + * @returns {React.ReactNode} + */ function MatchingBankTransactionRoot({ // #withBankingActions closeMatchingTransactionAside, @@ -89,7 +96,7 @@ function MatchingBankTransactionContent() { return ( - + ); } @@ -135,7 +142,7 @@ function PerfectMatchingTransactions() { * Renders the possible match transactions. * @returns {React.ReactNode} */ -function GoodMatchingTransactions() { +function PossibleMatchingTransactions() { const { possibleMatches } = useMatchingTransactionBoot(); // Can't continue if the possible matches is emoty. @@ -168,7 +175,10 @@ function GoodMatchingTransactions() { ); } interface MatchTransactionFieldProps - extends Omit { + extends Omit< + MatchTransactionCheckboxProps, + 'onChange' | 'active' | 'initialActive' + > { transactionId: number; transactionType: string; } @@ -183,7 +193,7 @@ function MatchTransactionField({ return ( {({ form, field: { value } }: FastFieldProps) => ( - { @@ -195,10 +205,6 @@ function MatchTransactionField({ ); } -export function CategorizeBankTransactionContent() { - return

Categorizing

; -} - interface MatchTransctionFooterProps extends WithBankingActionsProps {} /** @@ -210,6 +216,7 @@ const MatchTransactionFooter = R.compose(withBankingActions)( const { submitForm, isSubmitting } = useFormikContext(); const totalPending = useGetPendingAmountMatched(); const showReconcileLink = useIsShowReconcileTransactionLink(); + const submitDisabled = totalPending !== 0; const handleCancelBtnClick = () => { closeMatchingTransactionAside(); @@ -243,6 +250,7 @@ const MatchTransactionFooter = R.compose(withBankingActions)( style={{ minWidth: 85 }} onClick={handleSubmitBtnClick} loading={isSubmitting} + disabled={submitDisabled} > Match diff --git a/packages/webapp/src/hooks/useUncontrolled.ts b/packages/webapp/src/hooks/useUncontrolled.ts index 6d441fb8b..74659b236 100644 --- a/packages/webapp/src/hooks/useUncontrolled.ts +++ b/packages/webapp/src/hooks/useUncontrolled.ts @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import { useState } from 'react'; interface UseUncontrolledInput { /** Value for controlled state */ @@ -19,7 +19,7 @@ export function useUncontrolled({ initialValue, finalValue, onChange = () => {}, -}: UseUncontrolledInput) { +}: UseUncontrolledInput): [T, (value: T) => void, boolean] { const [uncontrolledValue, setUncontrolledValue] = useState( initialValue !== undefined ? initialValue : finalValue, );