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,29 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import '@/style/pages/Preferences/warehousesList.scss';
import WarehousesGrid from './WarehousesGrid';
import withDashboardActions from '@/containers/Dashboard/withDashboardActions';
import { compose } from '@/utils';
/**
* Warehouses.
* @returns
*/
function Warehouses({
// #withDashboardActions
changePreferencesPageTitle,
}) {
React.useEffect(() => {
changePreferencesPageTitle(intl.get('warehouses.label'));
}, [changePreferencesPageTitle]);
return (
<React.Fragment>
<WarehousesGrid />
</React.Fragment>
);
}
export default compose(withDashboardActions)(Warehouses);

View File

@@ -0,0 +1,36 @@
// @ts-nocheck
import React from 'react';
import { Button, Intent } from '@blueprintjs/core';
import { Features } from '@/constants';
import { FeatureCan, FormattedMessage as T, Icon } from '@/components';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import { compose } from '@/utils';
/**
* Warehouse actions.
*/
function WarehousesActions({
//#ownProps
openDialog,
}) {
const handleClickNewWarehouse = () => {
openDialog('warehouse-form');
};
return (
<React.Fragment>
<FeatureCan feature={Features.Warehouses}>
<Button
icon={<Icon icon="plus" iconSize={12} />}
onClick={handleClickNewWarehouse}
intent={Intent.PRIMARY}
>
<T id={'warehouses.label.new_warehouse'} />
</Button>
</FeatureCan>
</React.Fragment>
);
}
export default compose(withDialogActions)(WarehousesActions);

View File

@@ -0,0 +1,11 @@
// @ts-nocheck
import React from 'react';
const WarehouseDeleteAlert = React.lazy(
() => import('@/containers/Alerts/Warehouses/WarehouseDeleteAlert'),
);
/**
* Warehouses alerts.
*/
export default [{ name: 'warehouse-delete', component: WarehouseDeleteAlert }];

View File

@@ -0,0 +1,41 @@
// @ts-nocheck
import React from 'react';
import { Button, Intent } from '@blueprintjs/core';
import { FormattedMessage as T, EmptyStatus } from '@/components';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import { compose } from '@/utils';
function WarehousesEmptyStatus({
// #withDialogActions
openDialog,
}) {
// Handle activate action warehouse.
const handleActivateWarehouse = () => {
openDialog('warehouse-activate', {});
};
return (
<EmptyStatus
title={<T id={'warehouses.empty_status.title'} />}
description={
<p>
<T id={'warehouses.empty_status.description'} />
</p>
}
action={
<React.Fragment>
<Button
intent={Intent.PRIMARY}
large={true}
onClick={handleActivateWarehouse}
>
<T id={'warehouses.activate_button'} />
</Button>
</React.Fragment>
}
/>
);
}
export default compose(withDialogActions)(WarehousesEmptyStatus);

View File

@@ -0,0 +1,32 @@
// @ts-nocheck
import React from 'react';
import WarehousesEmptyStatus from './WarehousesEmptyStatus';
import { useWarehousesContext } from './WarehousesProvider';
import { WarehousesList, WarehousesSkeleton } from './components';
import WarehousesGridItems from './WarehousesGridItems';
/**
* Warehouses grid.
*/
export default function WarehousesGrid() {
// Retrieve list context.
const {
warehouses,
isWarehouesLoading,
isEmptyStatus,
} = useWarehousesContext();
return (
<React.Fragment>
<WarehousesList>
{isWarehouesLoading ? (
<WarehousesSkeleton />
) : isEmptyStatus ? (
<WarehousesEmptyStatus />
) : (
<WarehousesGridItems warehouses={warehouses} />
)}
</WarehousesList>
</React.Fragment>
);
}

View File

@@ -0,0 +1,84 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import { Intent } from '@blueprintjs/core';
import { ContextMenu2 } from '@blueprintjs/popover2';
import { AppToaster } from '@/components';
import { WarehouseContextMenu, WarehousesGridItemBox } from './components';
import { useMarkWarehouseAsPrimary } from '@/hooks/query';
import withAlertsActions from '@/containers/Alert/withAlertActions';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import { compose } from '@/utils';
/**
* warehouse grid item.
*/
function WarehouseGridItem({
// #withAlertsActions
openAlert,
// #withDialogActions
openDialog,
warehouse,
}) {
const { mutateAsync: markWarehouseAsPrimaryMutate } =
useMarkWarehouseAsPrimary();
// Handle edit warehouse.
const handleEditWarehouse = () => {
openDialog('warehouse-form', { warehouseId: warehouse.id, action: 'edit' });
};
// Handle delete warehouse.
const handleDeleteWarehouse = () => {
openAlert('warehouse-delete', { warehouseId: warehouse.id });
};
// Handle mark primary warehouse.
const handleMarkWarehouseAsPrimary = () => {
markWarehouseAsPrimaryMutate(warehouse.id).then(() => {
AppToaster.show({
message: intl.get('warehouse.alert.mark_primary_message'),
intent: Intent.SUCCESS,
});
});
};
return (
<ContextMenu2
content={
<WarehouseContextMenu
warehouse={warehouse}
onEditClick={handleEditWarehouse}
onDeleteClick={handleDeleteWarehouse}
onMarkPrimary={handleMarkWarehouseAsPrimary}
/>
}
>
<WarehousesGridItemBox
title={warehouse.name}
code={warehouse.code}
city={warehouse.city}
country={warehouse.country}
email={warehouse.email}
phoneNumber={warehouse.phone_number}
primary={warehouse.primary}
/>
</ContextMenu2>
);
}
const WarehousesGridItem = compose(
withAlertsActions,
withDialogActions,
)(WarehouseGridItem);
/**
* warehouses grid items,
*/
export default function WarehousesGridItems({ warehouses }) {
return warehouses.map((warehouse) => (
<WarehousesGridItem warehouse={warehouse} />
));
}

View File

@@ -0,0 +1,56 @@
// @ts-nocheck
import React from 'react';
import styled from 'styled-components';
import classNames from 'classnames';
import { CLASSES } from '@/constants/classes';
import { useWarehouses } from '@/hooks/query';
import { isEmpty } from 'lodash';
import { Features } from '@/constants';
import { useFeatureCan } from '@/hooks/state';
const WarehousesContext = React.createContext();
/**
* Warehouses data provider.
*/
function WarehousesProvider({ query, ...props }) {
// Features guard.
const { featureCan } = useFeatureCan();
const isWarehouseFeatureCan = featureCan(Features.Warehouses);
// Fetch warehouses list.
const { data: warehouses, isLoading: isWarehouesLoading } = useWarehouses(
query,
{ enabled: isWarehouseFeatureCan },
);
// Detarmines the datatable empty status.
const isEmptyStatus = isEmpty(warehouses) || !isWarehouseFeatureCan;
// Provider state.
const provider = {
warehouses,
isWarehouesLoading,
isEmptyStatus,
};
return (
<div
className={classNames(
CLASSES.PREFERENCES_PAGE_INSIDE_CONTENT,
CLASSES.PREFERENCES_PAGE_INSIDE_CONTENT_WAREHOUSES,
)}
>
<React.Fragment>
<WarehousesContext.Provider value={provider} {...props} />
</React.Fragment>
</div>
);
}
const useWarehousesContext = () => React.useContext(WarehousesContext);
export { WarehousesProvider, useWarehousesContext };
const WarehousePreference = styled.div``;

View File

@@ -0,0 +1,189 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import styled from 'styled-components';
import {
Menu,
MenuItem,
MenuDivider,
Intent,
Classes,
} from '@blueprintjs/core';
import { Icon, If } from '@/components';
import { safeCallback } from '@/utils';
const WAREHOUSES_SKELETON_N = 4;
/**
* Warehouse grid item box context menu.
* @returns {JSX.Element}
*/
export function WarehouseContextMenu({
onEditClick,
onDeleteClick,
onMarkPrimary,
warehouse,
}) {
return (
<Menu>
<MenuItem
icon={<Icon icon="pen-18" />}
text={intl.get('warehouses.action.edit_warehouse')}
onClick={safeCallback(onEditClick)}
/>
<If condition={!warehouse.primary}>
<MenuItem
icon={<Icon icon={'check'} iconSize={18} />}
text={intl.get('warehouses.action.make_as_parimary')}
onClick={safeCallback(onMarkPrimary)}
/>
</If>
<MenuDivider />
<MenuItem
text={intl.get('warehouses.action.delete_warehouse')}
icon={<Icon icon="trash-16" iconSize={16} />}
intent={Intent.DANGER}
onClick={safeCallback(onDeleteClick)}
/>
</Menu>
);
}
/**
* Warehouse grid item box skeleton.
* @returns {JSX.Element}
*/
function WarehouseGridItemSkeletonBox() {
return (
<WarehouseBoxRoot>
<WarehouseHeader>
<WarehouseTitle className={Classes.SKELETON}>X</WarehouseTitle>
<WarehouseCode className={Classes.SKELETON}>X</WarehouseCode>
</WarehouseHeader>
<WarehouseContent>
<WarehouseItem className={Classes.SKELETON}>X</WarehouseItem>
<WarehouseItem className={Classes.SKELETON}>X</WarehouseItem>
</WarehouseContent>
</WarehouseBoxRoot>
);
}
/**
* Warehouse grid item box.
* @returns {JSX.Element}
*/
export function WarehousesGridItemBox({
title,
code,
city,
country,
email,
phoneNumber,
primary,
}) {
return (
<WarehouseBoxRoot>
<WarehouseHeader>
<WarehouseTitle>
{title} {primary && <Icon icon={'star-18dp'} iconSize={16} />}
</WarehouseTitle>
<WarehouseCode>{code}</WarehouseCode>
<WarehouseIcon>
<Icon icon="warehouse-16" iconSize={20} />
</WarehouseIcon>
</WarehouseHeader>
<WarehouseContent>
{city && <WarehouseItem>{city}</WarehouseItem>}
{country && <WarehouseItem>{country}</WarehouseItem>}
{email && <WarehouseItem>{email}</WarehouseItem>}
{phoneNumber && <WarehouseItem>{phoneNumber}</WarehouseItem>}
</WarehouseContent>
</WarehouseBoxRoot>
);
}
export function WarehousesSkeleton() {
return [...Array(WAREHOUSES_SKELETON_N)].map((key, value) => (
<WarehouseGridItemSkeletonBox />
));
}
export const WarehousesList = styled.div`
display: flex;
flex-wrap: wrap;
margin: 15px;
height: 100%;
`;
export const WarehouseBoxRoot = styled.div`
display: flex;
flex-direction: column;
flex-shrink: 0;
border-radius: 5px;
border: 1px solid #c8cad0;
background: #fff;
margin: 5px 5px 8px;
width: 200px;
height: 160px;
transition: all 0.1s ease-in-out;
padding: 12px;
position: relative;
&:hover {
border-color: #0153cc;
}
`;
export const WarehouseHeader = styled.div`
position: relative;
padding-right: 24px;
padding-top: 2px;
`;
export const WarehouseTitle = styled.div`
font-size: 14px;
font-style: inherit;
color: #000;
white-space: nowrap;
font-weight: 500;
line-height: 1;
.bp3-icon {
margin: 0;
margin-left: 2px;
vertical-align: top;
color: #e1b31d;
}
`;
const WarehouseCode = styled.div`
display: block;
font-size: 11px;
color: #6b7176;
margin-top: 4px;
`;
const WarehouseIcon = styled.div`
position: absolute;
top: 0;
color: #abb3bb;
right: 0;
`;
const WarehouseContent = styled.div`
width: 100%;
margin-top: auto;
`;
const WarehouseItem = styled.div`
font-size: 11px;
color: #000;
text-overflow: ellipsis;
overflow: hidden;
&:not(:last-of-type) {
margin-bottom: 5px;
}
`;

View File

@@ -0,0 +1,16 @@
// @ts-nocheck
import React from 'react';
import { WarehousesProvider } from './WarehousesProvider';
import Warehouses from './Warehouses';
/**
* Warehouses Preferences.
* @returns
*/
export default function WarehousesPerences() {
return (
<WarehousesProvider>
<Warehouses />
</WarehousesProvider>
);
}

View File

@@ -0,0 +1,26 @@
// @ts-nocheck
import intl from 'react-intl-universal';
import { Intent } from '@blueprintjs/core';
import { AppToaster } from '@/components';
/**
* Handle delete errors.
*/
export const handleDeleteErrors = (errors) => {
if (
errors.find((error) => error.type === 'COULD_NOT_DELETE_ONLY_WAERHOUSE')
) {
AppToaster.show({
message: intl.get('warehouse.error.could_not_delete_only_waerhouse'),
intent: Intent.DANGER,
});
}
if (errors.some((e) => e.type === 'WAREHOUSE_HAS_ASSOCIATED_TRANSACTIONS')) {
AppToaster.show({
message: intl.get(
'warehouse.error.warehouse_has_associated_transactions',
),
intent: Intent.DANGER,
});
}
};