diff --git a/packages/webapp/src/components/AppShell/AppShell.module.scss b/packages/webapp/src/components/AppShell/AppShell.module.scss new file mode 100644 index 000000000..51f813bcf --- /dev/null +++ b/packages/webapp/src/components/AppShell/AppShell.module.scss @@ -0,0 +1,14 @@ + +.main{ + flex: 1 0; +} + +.aside{ + width: 500px; + height: 100dvh; + border-left: 1px solid rgba(17, 20, 24, 0.15); +} + +.root { + display: flex; +} \ No newline at end of file diff --git a/packages/webapp/src/components/AppShell/AppShell.tsx b/packages/webapp/src/components/AppShell/AppShell.tsx new file mode 100644 index 000000000..8539117c2 --- /dev/null +++ b/packages/webapp/src/components/AppShell/AppShell.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { AppShellProvider } from './AppShellProvider'; +import { Box } from '../Layout'; +import styles from './AppShell.module.scss'; + +interface AppShellProps { + topbarOffset?: number; + mainProps: any; + asideProps: any; + children: React.ReactNode; +} + +export function AppShell({ + asideProps, + mainProps, + topbarOffset = 0, + ...restProps +}: AppShellProps) { + return ( + + + + ); +} + +AppShell.Main = AppShellMain; +AppShell.Aside = AppShellAside; + +function AppShellMain({ ...props }) { + return ; +} + +interface AppShellAsideProps { + children: React.ReactNode; +} + +function AppShellAside({ ...props }: AppShellAsideProps) { + return ; +} diff --git a/packages/webapp/src/components/AppShell/AppShellProvider.tsx b/packages/webapp/src/components/AppShell/AppShellProvider.tsx new file mode 100644 index 000000000..299f015f4 --- /dev/null +++ b/packages/webapp/src/components/AppShell/AppShellProvider.tsx @@ -0,0 +1,25 @@ +import React, { createContext } from 'react'; + +interface AppShellContextValue { + topbarOffset: number +} + +const AppShellContext = createContext( + {} as AppShellContextValue, +); + +interface AppShellProviderProps { + children: React.ReactNode; + mainProps: any; + asideProps: any; + topbarOffset: number; +} + +export function AppShellProvider({ topbarOffset, ...props }: AppShellProviderProps) { + const provider = { topbarOffset } as AppShellContextValue; + + return ; +} + +export const useAppShellContext = () => + React.useContext(AppShellContext); diff --git a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContent.tsx b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContent.tsx index ff0893a1e..fe7a8d216 100644 --- a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContent.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContent.tsx @@ -1,3 +1,4 @@ +import { Classes } from '@blueprintjs/core'; import { RuleFormBoot } from './RuleFormBoot'; import { RuleFormContentForm } from './RuleFormContentForm'; @@ -12,7 +13,9 @@ export default function RuleFormContent({ }: RuleFormContentProps) { return ( - +
+ +
); } diff --git a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.schema.ts b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.schema.ts index 3cde8f265..8247098df 100644 --- a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.schema.ts +++ b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.schema.ts @@ -3,11 +3,20 @@ import * as Yup from 'yup'; const Schema = Yup.object().shape({ name: Yup.string().required().label('Rule name'), - applyIfAccountId: Yup.number().required().label(''), - applyIfTransactionType: Yup.string().required().label(''), - conditionsType: Yup.string().required(), - assignCategory: Yup.string().required(), - assignAccountId: Yup.string().required(), + applyIfAccountId: Yup.number().required().label('Apply to account'), + applyIfTransactionType: Yup.string() + .required() + .label('Apply to transaction type'), + conditionsType: Yup.string().required().label('Condition type'), + assignCategory: Yup.string().required().label('Assign to category'), + assignAccountId: Yup.string().required().label('Assign to account'), + conditions: Yup.array().of( + Yup.object().shape({ + value: Yup.string().required().label('Value'), + comparator: Yup.string().required().label('Comparator'), + field: Yup.string().required().label('Field'), + }), + ), }); export const CreateRuleFormSchema = Schema; diff --git a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.tsx b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.tsx index b371e2a32..a97ce4c19 100644 --- a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.tsx @@ -12,6 +12,7 @@ import { FRadioGroup, FSelect, Group, + Stack, } from '@/components'; import { useCreateBankRule } from '@/hooks/query/bank-rules'; import { @@ -72,13 +73,14 @@ function RuleFormContentFormRoot({ onSubmit={handleSubmit} >
- + @@ -86,10 +88,12 @@ function RuleFormContentFormRoot({ @@ -107,20 +111,35 @@ function RuleFormContentFormRoot({ -

Then Assign

+

+ Then Assign +

- + - + - + @@ -146,54 +165,87 @@ function RuleFormConditions() { }; return ( - - {values?.conditions?.map((condition, index) => ( - - - - + + + {values?.conditions?.map((condition, index) => ( + + + + - - - + label={'Condition'} + style={{ marginBottom: 0, flex: '1 0' }} + > + + - - - - - ))} + + + + + ))} + - ); } -function RuleFormActions() { +function RuleFormActionsRoot({ + // #withDialogActions + closeDialog, +}) { const { isSubmitting, submitForm } = useFormikContext(); const handleSaveBtnClick = () => { submitForm(); }; - const handleCancelBtnClick = () => {}; + const handleCancelBtnClick = () => { + closeDialog(DialogsName.BankRuleForm); + }; return ( - - + + + + ); } + +const RuleFormActions = R.compose(withDialogActions)(RuleFormActionsRoot); diff --git a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/_utils.ts b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/_utils.ts index d88136c9b..696464b87 100644 --- a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/_utils.ts +++ b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/_utils.ts @@ -3,12 +3,12 @@ export const initialValues = { order: 0, applyIfAccountId: '', applyIfTransactionType: '', - conditionsType: '', + conditionsType: 'and', conditions: [ { field: 'description', comparator: 'contains', - value: 'payment', + value: '', }, ], assignCategory: '', @@ -41,7 +41,7 @@ export const Fields = [ ]; export const FieldCondition = [ { value: 'contains', text: 'Contains' }, - { value: 'equals', text: 'equals' }, + { value: 'equals', text: 'Equals' }, { value: 'not_contains', text: 'Not Contains' }, ]; export const AssignTransactionTypeOptions = [ diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsList.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsList.tsx index 43b4b706d..a6db2db7e 100644 --- a/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsList.tsx +++ b/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsList.tsx @@ -14,6 +14,8 @@ import { import { AccountTransactionsDetailsBar } from './AccountTransactionsDetailsBar'; import { AccountTransactionsProgressBar } from './components'; import { AccountTransactionsFilterTabs } from './AccountTransactionsFilterTabs'; +import { AppShell } from '@/components/AppShell/AppShell'; +import { CategorizeTransactionAside } from '../CategorizeTransactionAside/CategorizeTransactionAside'; /** * Account transactions list. @@ -21,17 +23,25 @@ import { AccountTransactionsFilterTabs } from './AccountTransactionsFilterTabs'; function AccountTransactionsList() { return ( - - - + + + + + - - + + - }> - - - + }> + + + + + + + + + ); } diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionAside.module.scss b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionAside.module.scss new file mode 100644 index 000000000..a52cd188c --- /dev/null +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionAside.module.scss @@ -0,0 +1,61 @@ + + +.transaction { + background: #fff; + border-radius: 5px; + border: 1px solid #D6DBE3; + padding: 12px 16px; +} + +.asideHeader { + align-items: center; + background: #fff; + border-bottom: 1px solid #E1E2E9; + display: flex; + flex: 0 0 auto; + min-height: 40px; + padding: 5px 5px 5px 15px; + z-index: 0; +} + +.tabs :global .bp4-tab-panel{ + margin-top: 0; +} +.tabs :global .bp4-tab-list{ + background: #fff; + border-bottom: 1px solid #c7d5db; + padding: 0 22px; +} + +.tabs :global .bp4-large > .bp4-tab{ + font-size: 14px; +} + +.matchBar{ + padding: 16px 18px; + background: #fff; + border-bottom: 1px solid #E1E2E9; + border-top: 1px solid #E1E2E9; +} +.matchBarTitle { + font-size: 14px; + font-weight: 500; +} + +.footerActions { + padding: 14px 16px; + border-top: 1px solid #E1E2E9; +} + +.footerTotal { + padding: 8px 16px; + border: 1px solid #E1E2E9; +} + +.checkbox:global(.bp4-control.bp4-checkbox){ + margin: 0; +} +.checkbox:global(.bp4-control.bp4-checkbox) :global .bp4-control-indicator{ + border-color: #CBCBCB; +} + diff --git a/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionAside.tsx b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionAside.tsx new file mode 100644 index 000000000..c4ef09a04 --- /dev/null +++ b/packages/webapp/src/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionAside.tsx @@ -0,0 +1,145 @@ +import { Box, Group, Icon, Stack } from '@/components'; +import { + AnchorButton, + Button, + Checkbox, + Classes, + Intent, + Tab, + Tabs, + Tag, + Text, +} from '@blueprintjs/core'; +import styles from './CategorizeTransactionAside.module.scss'; + +interface AsideProps { + title?: string; + onClose?: () => void; + children?: React.ReactNode; +} + +function Aside({ title, onClose, children }: AsideProps) { + const handleClose = () => { + onClose && onClose(); + }; + return ( + + + {title} + + + + + + ); +} diff --git a/packages/webapp/src/static/json/icons.tsx b/packages/webapp/src/static/json/icons.tsx index 0e6d27c62..26bef2707 100644 --- a/packages/webapp/src/static/json/icons.tsx +++ b/packages/webapp/src/static/json/icons.tsx @@ -605,4 +605,10 @@ export default { ], viewBox: '0 0 16 16', }, + smallCross: { + path: [ + 'M9.41,8l3.29-3.29C12.89,4.53,13,4.28,13,4c0-0.55-0.45-1-1-1c-0.28,0-0.53,0.11-0.71,0.29L8,6.59L4.71,3.29C4.53,3.11,4.28,3,4,3C3.45,3,3,3.45,3,4c0,0.28,0.11,0.53,0.29,0.71L6.59,8l-3.29,3.29C3.11,11.47,3,11.72,3,12c0,0.55,0.45,1,1,1c0.28,0,0.53-0.11,0.71-0.29L8,9.41l3.29,3.29C11.47,12.89,11.72,13,12,13c0.55,0,1-0.45,1-1c0-0.28-0.11-0.53-0.29-0.71L9.41,8z', + ], + viewBox: '0 0 16 16', + }, };