re-structure to monorepo.

This commit is contained in:
a.bouhuolia
2023-02-03 01:02:31 +02:00
parent 8242ec64ba
commit 7a0a13f9d5
10400 changed files with 46966 additions and 17223 deletions

View File

@@ -0,0 +1,80 @@
// @ts-nocheck
import React from 'react';
import { useHistory } from 'react-router-dom';
import {
Button,
Classes,
NavbarGroup,
Intent,
NavbarDivider,
} from '@blueprintjs/core';
import {
Icon,
DrawerActionsBar,
Can,
FormattedMessage as T,
} from '@/components';
import { ExpenseAction, AbilitySubject } from '@/constants/abilityOption';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
import withAlertsActions from '@/containers/Alert/withAlertActions';
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
import { compose } from '@/utils';
/**
* Expense drawer action bar.
*/
function ExpenseDrawerActionBar({
// #withAlertsDialog
openAlert,
// #withDrawerActions
closeDrawer,
}) {
const history = useHistory();
// Expense drawer context.
const { expense } = useExpenseDrawerContext();
// Handle the expense edit action.
const handleEditExpense = () => {
history.push(`/expenses/${expense.id}/edit`);
closeDrawer('expense-drawer');
};
// Handle the expense delete action.
const handleDeleteExpense = () => {
openAlert('expense-delete', { expenseId: expense.id });
};
return (
<DrawerActionsBar>
<NavbarGroup>
<Can I={ExpenseAction.Edit} a={AbilitySubject.Expense}>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="pen-18" />}
text={<T id={'edit_expense'} />}
onClick={handleEditExpense}
/>
</Can>
<Can I={ExpenseAction.Delete} a={AbilitySubject.Expense}>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon icon="trash-16" iconSize={16} />}
text={<T id={'delete'} />}
intent={Intent.DANGER}
onClick={handleDeleteExpense}
/>
</Can>
</NavbarGroup>
</DrawerActionsBar>
);
}
export default compose(
withAlertsActions,
withDrawerActions,
)(ExpenseDrawerActionBar);

View File

@@ -0,0 +1,23 @@
// @ts-nocheck
import React from 'react';
import { DrawerBody } from '@/components';
import { ExpenseDrawerProvider } from './ExpenseDrawerProvider';
import ExpenseDrawerDetails from './ExpenseDrawerDetails';
/**
* Expense drawer content.
*/
export default function ExpenseDrawerContent({
// #ownProp
expenseId,
}) {
return (
<ExpenseDrawerProvider expenseId={expenseId}>
<DrawerBody>
<ExpenseDrawerDetails />
</DrawerBody>
</ExpenseDrawerProvider>
);
}

View File

@@ -0,0 +1,29 @@
// @ts-nocheck
import React from 'react';
import styled from 'styled-components';
import { CommercialDocBox } from '@/components';
import ExpenseDrawerActionBar from './ExpenseDrawerActionBar';
import ExpenseDrawerHeader from './ExpenseDrawerHeader';
import ExpenseDrawerTable from './ExpenseDrawerTable';
import ExpenseDrawerFooter from './ExpenseDrawerFooter';
/**
* Expense view details.
*/
export default function ExpenseDrawerDetails() {
return (
<ExpenseDetailsRoot>
<ExpenseDrawerActionBar />
<CommercialDocBox>
<ExpenseDrawerHeader />
<ExpenseDrawerTable />
<ExpenseDrawerFooter />
</CommercialDocBox>
</ExpenseDetailsRoot>
);
}
const ExpenseDetailsRoot = styled.div``;

View File

@@ -0,0 +1,43 @@
// @ts-nocheck
import React from 'react';
import styled from 'styled-components';
import {
T,
TotalLines,
TotalLineBorderStyle,
TotalLineTextStyle,
} from '@/components';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
import { FormatNumber, TotalLine } from '@/components';
/**
* Footer details of expense readonly details.
*/
export default function ExpenseDrawerFooter() {
const { expense } = useExpenseDrawerContext();
return (
<ExpenseDetailsFooterRoot>
<ExpenseTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
<TotalLine
title={<T id={'expense.details.subtotal'} />}
value={<FormatNumber value={expense.total_amount} />}
borderStyle={TotalLineBorderStyle.SingleDark}
/>
<TotalLine
title={<T id={'expense.details.total'} />}
value={<FormatNumber value={expense.formatted_amount} />}
borderStyle={TotalLineBorderStyle.DoubleDark}
textStyle={TotalLineTextStyle.Bold}
/>
</ExpenseTotalLines>
</ExpenseDetailsFooterRoot>
);
}
export const ExpenseDetailsFooterRoot = styled.div``;
export const ExpenseTotalLines = styled(TotalLines)`
margin-left: auto;
`;

View File

@@ -0,0 +1,87 @@
// @ts-nocheck
import React from 'react';
import moment from 'moment';
import styled from 'styled-components';
import { defaultTo } from 'lodash';
import {
CommercialDocHeader,
CommercialDocTopHeader,
Row,
Col,
DetailItem,
DetailsMenu,
FormatDate,
ExchangeRateDetailItem,
FormattedMessage as T,
} from '@/components';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
import { ExpenseDetailsStatus } from './components';
/**
* Expense drawer content.
*/
export default function ExpenseDrawerHeader() {
const { expense } = useExpenseDrawerContext();
return (
<CommercialDocHeader>
<CommercialDocTopHeader>
<DetailsMenu>
<DetailItem name={'amount'} label={<T id={'full_amount'} />}>
<h3 class="big-number">{expense.formatted_amount}</h3>
</DetailItem>
<StatusDetailItem>
<ExpenseDetailsStatus expense={expense} />
</StatusDetailItem>
</DetailsMenu>
</CommercialDocTopHeader>
<Row>
<Col xs={6}>
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
<DetailItem name={'date'} label={<T id={'date'} />}>
{moment(expense.payment_date).format('YYYY MMM DD')}
</DetailItem>
<DetailItem name={'reference'} label={<T id={'reference_no'} />}>
{defaultTo(expense.reference_no, '-')}
</DetailItem>
<DetailItem label={<T id={'description'} />}>
{defaultTo(expense.description, '—')}
</DetailItem>
<ExchangeRateDetailItem
exchangeRate={expense?.exchange_rate}
toCurrency={expense?.currency_code}
/>
</DetailsMenu>
</Col>
<Col xs={6}>
<DetailsMenu
textAlign={'right'}
direction={'horizantal'}
minLabelSize={'180px'}
>
<DetailItem label={<T id={'published_at'} />}>
<FormatDate value={expense.published_at} />
</DetailItem>
<DetailItem label={<T id={'created_at'} />}>
<FormatDate value={expense.created_at} />
</DetailItem>
</DetailsMenu>
</Col>
</Row>
</CommercialDocHeader>
);
}
const StatusDetailItem = styled(DetailItem)`
width: 50%;
text-align: right;
position: relative;
top: -5px;
`;

View File

@@ -0,0 +1,56 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import { useExpense } from '@/hooks/query';
import { DrawerHeaderContent, DrawerLoading } from '@/components';
import { Features } from '@/constants';
import { useFeatureCan } from '@/hooks/state';
const ExpenseDrawerDrawerContext = React.createContext();
/**
* Expense drawer provider.
*/
function ExpenseDrawerProvider({ expenseId, ...props }) {
// Features guard.
const { featureCan } = useFeatureCan();
// Fetch the expense details.
const {
data: expense,
isLoading: isExpenseLoading,
isFetching: isExpenseFetching,
} = useExpense(expenseId, {
enabled: !!expenseId,
});
// Provider.
const provider = {
expenseId,
expense,
isExpenseFetching,
isExpenseLoading,
};
return (
<DrawerLoading loading={isExpenseLoading}>
<DrawerHeaderContent
name="expense-drawer"
title={intl.get('expense.drawer.title')}
subTitle={
featureCan(Features.Branches)
? intl.get('expense.drawer.subtitle', {
value: expense.branch?.name,
})
: null
}
/>
<ExpenseDrawerDrawerContext.Provider value={provider} {...props} />
</DrawerLoading>
);
}
const useExpenseDrawerContext = () =>
React.useContext(ExpenseDrawerDrawerContext);
export { ExpenseDrawerProvider, useExpenseDrawerContext };

View File

@@ -0,0 +1,28 @@
// @ts-nocheck
import React from 'react';
import { CommercialDocEntriesTable } from '@/components';
import { useExpenseReadEntriesColumns } from './utils';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
import { TableStyle } from '@/constants';
/**
* Expense details table.
*/
export default function ExpenseDrawerTable() {
// Expense readonly entries columns.
const columns = useExpenseReadEntriesColumns();
// Expense drawer context.
const { expense } = useExpenseDrawerContext();
return (
<CommercialDocEntriesTable
columns={columns}
data={expense.categories}
styleName={TableStyle.Constrant}
/>
);
}

View File

@@ -0,0 +1,21 @@
// @ts-nocheck
import React from 'react';
import { Tag, Intent } from '@blueprintjs/core';
import { T } from '@/components';
/**
* Expense details status.
* @returns {React.JSX}
*/
export function ExpenseDetailsStatus({ expense }) {
return expense.is_published ? (
<Tag round={true} minimal={true}>
<T id={'published'} />
</Tag>
) : (
<Tag round={true} intent={Intent.WARNING}>
<T id={'draft'} />
</Tag>
);
}

View File

@@ -0,0 +1,34 @@
// @ts-nocheck
import React, { lazy } from 'react';
import { Drawer, DrawerSuspense } from '@/components';
import withDrawers from '@/containers/Drawer/withDrawers';
import { compose } from '@/utils';
const ExpenseDrawerContent = lazy(() => import('./ExpenseDrawerContent'));
/**
* Expense drawer.
*/
function ExpenseDrawer({
name,
// #withDrawer
isOpen,
payload: { expenseId },
}) {
return (
<Drawer
isOpen={isOpen}
name={name}
size={'65%'}
style={{ minWidth: '700px', maxWidth: '900px' }}
>
<DrawerSuspense>
<ExpenseDrawerContent expenseId={expenseId} />
</DrawerSuspense>
</Drawer>
);
}
export default compose(withDrawers())(ExpenseDrawer);

View File

@@ -0,0 +1,52 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import { FormatNumberCell, TextOverviewTooltipCell } from '@/components';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
import { getColumnWidth } from '@/utils';
/**
* Retrieve expense readonly details entries table columns.
*/
export const useExpenseReadEntriesColumns = () => {
// Expense drawer context.
const {
expense: { categories },
} = useExpenseDrawerContext();
return React.useMemo(
() => [
{
Header: intl.get('expense_account'),
accessor: 'expense_account.name',
Cell: TextOverviewTooltipCell,
width: 110,
disableSortBy: true,
textOverview: true,
className: 'account',
},
{
Header: intl.get('description'),
accessor: 'description',
Cell: TextOverviewTooltipCell,
className: 'description',
disableSortBy: true,
textOverview: true,
},
{
Header: intl.get('amount'),
accessor: 'amount',
Cell: FormatNumberCell,
width: getColumnWidth(categories, 'amount', {
minWidth: 60,
magicSpacing: 5,
}),
disableSortBy: true,
className: 'amount',
align: 'right',
},
],
[],
);
};