mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +00:00
feat(webapp): bank rule
This commit is contained in:
14
packages/webapp/src/components/AppShell/AppShell.module.scss
Normal file
14
packages/webapp/src/components/AppShell/AppShell.module.scss
Normal file
@@ -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;
|
||||||
|
}
|
||||||
39
packages/webapp/src/components/AppShell/AppShell.tsx
Normal file
39
packages/webapp/src/components/AppShell/AppShell.tsx
Normal file
@@ -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 (
|
||||||
|
<AppShellProvider mainProps={mainProps} asideProps={asideProps} topbarOffset={topbarOffset}>
|
||||||
|
<Box {...restProps} className={styles.root} />
|
||||||
|
</AppShellProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppShell.Main = AppShellMain;
|
||||||
|
AppShell.Aside = AppShellAside;
|
||||||
|
|
||||||
|
function AppShellMain({ ...props }) {
|
||||||
|
return <Box {...props} className={styles.main} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AppShellAsideProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function AppShellAside({ ...props }: AppShellAsideProps) {
|
||||||
|
return <Box {...props} className={styles.aside} />;
|
||||||
|
}
|
||||||
25
packages/webapp/src/components/AppShell/AppShellProvider.tsx
Normal file
25
packages/webapp/src/components/AppShell/AppShellProvider.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import React, { createContext } from 'react';
|
||||||
|
|
||||||
|
interface AppShellContextValue {
|
||||||
|
topbarOffset: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppShellContext = createContext<AppShellContextValue>(
|
||||||
|
{} 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 <AppShellContext.Provider value={provider} {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAppShellContext = () =>
|
||||||
|
React.useContext<AppShellContextValue>(AppShellContext);
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Classes } from '@blueprintjs/core';
|
||||||
import { RuleFormBoot } from './RuleFormBoot';
|
import { RuleFormBoot } from './RuleFormBoot';
|
||||||
import { RuleFormContentForm } from './RuleFormContentForm';
|
import { RuleFormContentForm } from './RuleFormContentForm';
|
||||||
|
|
||||||
@@ -12,7 +13,9 @@ export default function RuleFormContent({
|
|||||||
}: RuleFormContentProps) {
|
}: RuleFormContentProps) {
|
||||||
return (
|
return (
|
||||||
<RuleFormBoot bankRuleId={bankRuleId}>
|
<RuleFormBoot bankRuleId={bankRuleId}>
|
||||||
<RuleFormContentForm />
|
<div className={Classes.DIALOG_BODY}>
|
||||||
|
<RuleFormContentForm />
|
||||||
|
</div>
|
||||||
</RuleFormBoot>
|
</RuleFormBoot>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,20 @@ import * as Yup from 'yup';
|
|||||||
|
|
||||||
const Schema = Yup.object().shape({
|
const Schema = Yup.object().shape({
|
||||||
name: Yup.string().required().label('Rule name'),
|
name: Yup.string().required().label('Rule name'),
|
||||||
applyIfAccountId: Yup.number().required().label(''),
|
applyIfAccountId: Yup.number().required().label('Apply to account'),
|
||||||
applyIfTransactionType: Yup.string().required().label(''),
|
applyIfTransactionType: Yup.string()
|
||||||
conditionsType: Yup.string().required(),
|
.required()
|
||||||
assignCategory: Yup.string().required(),
|
.label('Apply to transaction type'),
|
||||||
assignAccountId: Yup.string().required(),
|
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;
|
export const CreateRuleFormSchema = Schema;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
FRadioGroup,
|
FRadioGroup,
|
||||||
FSelect,
|
FSelect,
|
||||||
Group,
|
Group,
|
||||||
|
Stack,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { useCreateBankRule } from '@/hooks/query/bank-rules';
|
import { useCreateBankRule } from '@/hooks/query/bank-rules';
|
||||||
import {
|
import {
|
||||||
@@ -72,13 +73,14 @@ function RuleFormContentFormRoot({
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<Form>
|
<Form>
|
||||||
<FFormGroup name={'name'} label={'Rule Name'}>
|
<FFormGroup name={'name'} label={'Rule Name'} style={{ maxWidth: 300 }}>
|
||||||
<FInputGroup name={'name'} />
|
<FInputGroup name={'name'} />
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
<FFormGroup
|
<FFormGroup
|
||||||
name={'applyIfAccountId'}
|
name={'applyIfAccountId'}
|
||||||
label={'Apply the rule to account'}
|
label={'Apply the rule to account'}
|
||||||
|
style={{ maxWidth: 350 }}
|
||||||
>
|
>
|
||||||
<AccountsSelect name={'applyIfAccountId'} items={accounts} />
|
<AccountsSelect name={'applyIfAccountId'} items={accounts} />
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
@@ -86,10 +88,12 @@ function RuleFormContentFormRoot({
|
|||||||
<FFormGroup
|
<FFormGroup
|
||||||
name={'applyIfTransactionType'}
|
name={'applyIfTransactionType'}
|
||||||
label={'Apply to transactions are'}
|
label={'Apply to transactions are'}
|
||||||
|
style={{ maxWidth: 350 }}
|
||||||
>
|
>
|
||||||
<FSelect
|
<FSelect
|
||||||
name={'applyIfTransactionType'}
|
name={'applyIfTransactionType'}
|
||||||
items={TransactionTypeOptions}
|
items={TransactionTypeOptions}
|
||||||
|
popoverProps={{ minimal: true, inline: false }}
|
||||||
/>
|
/>
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
@@ -107,20 +111,35 @@ function RuleFormContentFormRoot({
|
|||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
<RuleFormConditions />
|
<RuleFormConditions />
|
||||||
<h3>Then Assign</h3>
|
<h3 style={{ fontSize: 14, fontWeight: 600, marginBottom: '0.8rem' }}>
|
||||||
|
Then Assign
|
||||||
|
</h3>
|
||||||
|
|
||||||
<FFormGroup name={'assignCategory'} label={'Transaction type'}>
|
<FFormGroup
|
||||||
|
name={'assignCategory'}
|
||||||
|
label={'Transaction type'}
|
||||||
|
style={{ maxWidth: 300 }}
|
||||||
|
>
|
||||||
<FSelect
|
<FSelect
|
||||||
name={'assignCategory'}
|
name={'assignCategory'}
|
||||||
items={AssignTransactionTypeOptions}
|
items={AssignTransactionTypeOptions}
|
||||||
|
popoverProps={{ minimal: true, inline: false }}
|
||||||
/>
|
/>
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
<FFormGroup name={'assignAccountId'} label={'Account category'}>
|
<FFormGroup
|
||||||
|
name={'assignAccountId'}
|
||||||
|
label={'Account category'}
|
||||||
|
style={{ maxWidth: 300 }}
|
||||||
|
>
|
||||||
<AccountsSelect name={'assignAccountId'} items={accounts} />
|
<AccountsSelect name={'assignAccountId'} items={accounts} />
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
<FFormGroup name={'assignRef'} label={'Reference'}>
|
<FFormGroup
|
||||||
|
name={'assignRef'}
|
||||||
|
label={'Reference'}
|
||||||
|
style={{ maxWidth: 300 }}
|
||||||
|
>
|
||||||
<FInputGroup name={'assignRef'} />
|
<FInputGroup name={'assignRef'} />
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
@@ -146,54 +165,87 @@ function RuleFormConditions() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box style={{ marginBottom: 15 }}>
|
||||||
{values?.conditions?.map((condition, index) => (
|
<Stack spacing={15}>
|
||||||
<Group>
|
{values?.conditions?.map((condition, index) => (
|
||||||
<FFormGroup name={`conditions[${index}].field`} label={'Field'}>
|
<Group key={index} style={{ width: 500 }}>
|
||||||
<FSelect name={`conditions[${index}].field`} items={Fields} />
|
<FFormGroup
|
||||||
</FFormGroup>
|
name={`conditions[${index}].field`}
|
||||||
|
label={'Field'}
|
||||||
|
style={{ marginBottom: 0, flex: '1 0' }}
|
||||||
|
>
|
||||||
|
<FSelect
|
||||||
|
name={`conditions[${index}].field`}
|
||||||
|
items={Fields}
|
||||||
|
popoverProps={{ minimal: true, inline: false }}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
|
||||||
<FFormGroup
|
<FFormGroup
|
||||||
name={`conditions[${index}].comparator`}
|
|
||||||
label={'Condition'}
|
|
||||||
>
|
|
||||||
<FSelect
|
|
||||||
name={`conditions[${index}].comparator`}
|
name={`conditions[${index}].comparator`}
|
||||||
items={FieldCondition}
|
label={'Condition'}
|
||||||
/>
|
style={{ marginBottom: 0, flex: '1 0' }}
|
||||||
</FFormGroup>
|
>
|
||||||
|
<FSelect
|
||||||
|
name={`conditions[${index}].comparator`}
|
||||||
|
items={FieldCondition}
|
||||||
|
popoverProps={{ minimal: true, inline: false }}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
|
||||||
<FFormGroup name={`conditions[${index}].value`} label={'Condition'}>
|
<FFormGroup
|
||||||
<FInputGroup name={`conditions[${index}].value`} />
|
name={`conditions[${index}].value`}
|
||||||
</FFormGroup>
|
label={'Value'}
|
||||||
</Group>
|
style={{ marginBottom: 0, flex: '1 0 ', width: '40%' }}
|
||||||
))}
|
>
|
||||||
|
<FInputGroup name={`conditions[${index}].value`} />
|
||||||
|
</FFormGroup>
|
||||||
|
</Group>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<Button type={'button'} onClick={handleAddConditionBtnClick}>
|
<Button
|
||||||
|
minimal
|
||||||
|
small
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type={'button'}
|
||||||
|
onClick={handleAddConditionBtnClick}
|
||||||
|
style={{ marginTop: 8 }}
|
||||||
|
>
|
||||||
Add Condition
|
Add Condition
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function RuleFormActions() {
|
function RuleFormActionsRoot({
|
||||||
|
// #withDialogActions
|
||||||
|
closeDialog,
|
||||||
|
}) {
|
||||||
const { isSubmitting, submitForm } = useFormikContext<RuleFormValues>();
|
const { isSubmitting, submitForm } = useFormikContext<RuleFormValues>();
|
||||||
|
|
||||||
const handleSaveBtnClick = () => {
|
const handleSaveBtnClick = () => {
|
||||||
submitForm();
|
submitForm();
|
||||||
};
|
};
|
||||||
const handleCancelBtnClick = () => {};
|
const handleCancelBtnClick = () => {
|
||||||
|
closeDialog(DialogsName.BankRuleForm);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box className={Classes.DIALOG_FOOTER}>
|
<Box className={Classes.DIALOG_FOOTER}>
|
||||||
<Button
|
<Box className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||||
intent={Intent.PRIMARY}
|
<Button onClick={handleCancelBtnClick}>Cancel</Button>
|
||||||
loading={isSubmitting}
|
<Button
|
||||||
onClick={handleSaveBtnClick}
|
intent={Intent.PRIMARY}
|
||||||
>
|
loading={isSubmitting}
|
||||||
Save
|
onClick={handleSaveBtnClick}
|
||||||
</Button>
|
style={{ minWidth: 100 }}
|
||||||
<Button onClick={handleCancelBtnClick}>Cancel</Button>
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RuleFormActions = R.compose(withDialogActions)(RuleFormActionsRoot);
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ export const initialValues = {
|
|||||||
order: 0,
|
order: 0,
|
||||||
applyIfAccountId: '',
|
applyIfAccountId: '',
|
||||||
applyIfTransactionType: '',
|
applyIfTransactionType: '',
|
||||||
conditionsType: '',
|
conditionsType: 'and',
|
||||||
conditions: [
|
conditions: [
|
||||||
{
|
{
|
||||||
field: 'description',
|
field: 'description',
|
||||||
comparator: 'contains',
|
comparator: 'contains',
|
||||||
value: 'payment',
|
value: '',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
assignCategory: '',
|
assignCategory: '',
|
||||||
@@ -41,7 +41,7 @@ export const Fields = [
|
|||||||
];
|
];
|
||||||
export const FieldCondition = [
|
export const FieldCondition = [
|
||||||
{ value: 'contains', text: 'Contains' },
|
{ value: 'contains', text: 'Contains' },
|
||||||
{ value: 'equals', text: 'equals' },
|
{ value: 'equals', text: 'Equals' },
|
||||||
{ value: 'not_contains', text: 'Not Contains' },
|
{ value: 'not_contains', text: 'Not Contains' },
|
||||||
];
|
];
|
||||||
export const AssignTransactionTypeOptions = [
|
export const AssignTransactionTypeOptions = [
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import {
|
|||||||
import { AccountTransactionsDetailsBar } from './AccountTransactionsDetailsBar';
|
import { AccountTransactionsDetailsBar } from './AccountTransactionsDetailsBar';
|
||||||
import { AccountTransactionsProgressBar } from './components';
|
import { AccountTransactionsProgressBar } from './components';
|
||||||
import { AccountTransactionsFilterTabs } from './AccountTransactionsFilterTabs';
|
import { AccountTransactionsFilterTabs } from './AccountTransactionsFilterTabs';
|
||||||
|
import { AppShell } from '@/components/AppShell/AppShell';
|
||||||
|
import { CategorizeTransactionAside } from '../CategorizeTransactionAside/CategorizeTransactionAside';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account transactions list.
|
* Account transactions list.
|
||||||
@@ -21,17 +23,25 @@ import { AccountTransactionsFilterTabs } from './AccountTransactionsFilterTabs';
|
|||||||
function AccountTransactionsList() {
|
function AccountTransactionsList() {
|
||||||
return (
|
return (
|
||||||
<AccountTransactionsProvider>
|
<AccountTransactionsProvider>
|
||||||
<AccountTransactionsActionsBar />
|
<AppShell>
|
||||||
<AccountTransactionsDetailsBar />
|
<AppShell.Main>
|
||||||
<AccountTransactionsProgressBar />
|
<AccountTransactionsActionsBar />
|
||||||
|
<AccountTransactionsDetailsBar />
|
||||||
|
<AccountTransactionsProgressBar />
|
||||||
|
|
||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
<AccountTransactionsFilterTabs />
|
<AccountTransactionsFilterTabs />
|
||||||
|
|
||||||
<Suspense fallback={<Spinner size={30} />}>
|
<Suspense fallback={<Spinner size={30} />}>
|
||||||
<AccountTransactionsContent />
|
<AccountTransactionsContent />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</DashboardPageContent>
|
</DashboardPageContent>
|
||||||
|
</AppShell.Main>
|
||||||
|
|
||||||
|
<AppShell.Aside>
|
||||||
|
<CategorizeTransactionAside />
|
||||||
|
</AppShell.Aside>
|
||||||
|
</AppShell>
|
||||||
</AccountTransactionsProvider>
|
</AccountTransactionsProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 (
|
||||||
|
<Box>
|
||||||
|
<Group position="apart" className={styles.asideHeader}>
|
||||||
|
{title}
|
||||||
|
<Button
|
||||||
|
aria-label="Close"
|
||||||
|
className={Classes.DIALOG_CLOSE_BUTTON}
|
||||||
|
icon={<Icon icon={'smallCross'} color={'#000'} />}
|
||||||
|
minimal={true}
|
||||||
|
onClick={handleClose}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<Box>{children}</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CategorizeTransactionAside() {
|
||||||
|
return (
|
||||||
|
<Aside title={'Categorize Bank Transaction'}>
|
||||||
|
<Tabs large className={styles.tabs}>
|
||||||
|
<Tab
|
||||||
|
id="categorize"
|
||||||
|
title="Categorize Transaction"
|
||||||
|
panel={<CategorizeBankTransactionContent />}
|
||||||
|
/>
|
||||||
|
<Tab
|
||||||
|
id="matching"
|
||||||
|
title="Matching Transaction"
|
||||||
|
panel={<MatchingBankTransactionContent />}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
|
</Aside>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MatchingBankTransactionContent() {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box className={styles.matchBar}>
|
||||||
|
<Group spacing={6}>
|
||||||
|
<h2 className={styles.matchBarTitle}>Perfect Matchines</h2>
|
||||||
|
<Tag minimal intent={Intent.SUCCESS}>
|
||||||
|
2
|
||||||
|
</Tag>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Stack spacing={9} style={{ padding: 15 }}>
|
||||||
|
<MatchTransaction label={''} date={''} />
|
||||||
|
<MatchTransaction label={''} date={''} />
|
||||||
|
<MatchTransaction label={''} date={''} />
|
||||||
|
<MatchTransaction label={''} date={''} />
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Box className={styles.matchBar}>
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<h2 className={styles.matchBarTitle}>Perfect Matches</h2>
|
||||||
|
<Text style={{ fontSize: 12, color: '#5C7080' }}>
|
||||||
|
Transactions up to 20 Aug 2019
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Stack spacing={9} style={{ padding: 15 }}>
|
||||||
|
<MatchTransaction label={''} date={''} />
|
||||||
|
<MatchTransaction label={''} date={''} />
|
||||||
|
<MatchTransaction label={''} date={''} />
|
||||||
|
<MatchTransaction label={''} date={''} />
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<MatchTransactionFooter />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CategorizeBankTransactionContent() {
|
||||||
|
return <h1>Categorizing</h1>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MatchTransactionProps {
|
||||||
|
label: string;
|
||||||
|
date: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MatchTransaction({ label, date }: MatchTransactionProps) {
|
||||||
|
return (
|
||||||
|
<Group className={styles.transaction} position="apart">
|
||||||
|
<Stack spacing={3}>
|
||||||
|
<span>Expense for $10,000</span>
|
||||||
|
<Text style={{ fontSize: 12, color: '#5C7080' }}>
|
||||||
|
Date: 02/02/2020{' '}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Checkbox className={styles.checkbox} />
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MatchTransactionFooter() {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box className={styles.footerTotal}>
|
||||||
|
<Group>
|
||||||
|
<AnchorButton small minimal intent={Intent.PRIMARY}>
|
||||||
|
Add Reconcile Transaction +
|
||||||
|
</AnchorButton>
|
||||||
|
<Text>Pending $10,000</Text>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box className={styles.footerActions}>
|
||||||
|
<Group>
|
||||||
|
<Button intent={Intent.PRIMARY}>Match</Button>
|
||||||
|
<Button>Cancel</Button>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -605,4 +605,10 @@ export default {
|
|||||||
],
|
],
|
||||||
viewBox: '0 0 16 16',
|
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',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user