Skip to content

Commit

Permalink
EmployeeWebClient - create mapQueryParamsBeforeRender hook
Browse files Browse the repository at this point in the history
  • Loading branch information
bartstc committed Nov 2, 2022
1 parent 1719ba9 commit d8dc899
Show file tree
Hide file tree
Showing 22 changed files with 139 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DEFAULT_PARAMS } from 'utils/constant';

import { IEmployeeCollectionQueryParams } from './types';

export const EMPLOYEE_COLLECTION_DEFAULT_PARAMS: IEmployeeCollectionQueryParams = {
order: 'status',
...DEFAULT_PARAMS,
};
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { useAddEmployeeValidationSchema } from './useAddEmployeeValidationSchema';
export { useCreateOwnerEmployeeValidationSchema } from './useCreateOwnerEmployeeValidationSchema';
export { EMPLOYEE_COLLECTION_DEFAULT_PARAMS } from './employeeCollectionDefaultParams';
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ import { SubmitButton } from 'shared/Form';
import { Button } from 'shared/Button';
import { SectionContainer } from 'shared/DescriptionList';

import { buildUrl } from 'utils';
import { DEFAULT_PARAMS } from 'utils/constant';

import { ContactPersonInputs, AddressInputs, WorkingHoursInputs, MetaInputs, ContactsInputs, FacilityForm } from '../FacilityForm';
import { useCreateFacilityNotification } from './useCreateFacilityNotification';

Expand All @@ -37,7 +34,7 @@ const CreateFacilityForm = ({ enterpriseId, employeeId }: IProps) => {
try {
await handler(model);
showCreateSuccessNotification();
navigate(buildUrl(`/dashboard/facilities`, DEFAULT_PARAMS));
navigate(`/dashboard/facilities`);
} catch {
showCreateFailureNotification();
}
Expand All @@ -57,7 +54,7 @@ const CreateFacilityForm = ({ enterpriseId, employeeId }: IProps) => {
</SectionContainer>
<HStack justify='flex-end'>
<SubmitButton form='create-facility' isLoading={isLoading} />
<Button colorScheme='gray' ml={3} onClick={() => navigate(buildUrl(`/dashboard/facilities`, DEFAULT_PARAMS))}>
<Button colorScheme='gray' ml={3} onClick={() => navigate(`/dashboard/facilities`)}>
<FormattedMessage id='cancel' defaultMessage='Cancel' />
</Button>
</HStack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { HStack, Divider, VStack } from '@chakra-ui/react';

import { useFacilityQuery } from 'modules/facility/infrastructure/query';
import { useUpdateFacility } from 'modules/facility/infrastructure/command';
import { buildUrl } from 'utils';
import { DEFAULT_PARAMS } from 'utils/constant';
import { SubmitButton } from 'shared/Form';
import { Button } from 'shared/Button';
import { SectionContainer } from 'shared/DescriptionList';
Expand All @@ -30,7 +28,7 @@ const EditFacilityForm = () => {
try {
await handler(model);
showEditSuccessNotification();
navigate(buildUrl(`/dashboard/facilities`, DEFAULT_PARAMS));
navigate(`/dashboard/facilities`);
} catch {
showEditFailureNotification();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { useOffersCollectionCheckboxStore } from './offersCollectionCheckboxStore';
export { OFFER_COLLECTION_DEFAULT_PARAMS } from './offerCollectionDefaultParams';
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DEFAULT_PARAMS } from 'utils/constant';

import { IOfferCollectionQueryParams } from './types';

export const OFFER_COLLECTION_DEFAULT_PARAMS: IOfferCollectionQueryParams = {
order: 'status',
...DEFAULT_PARAMS,
};
3 changes: 2 additions & 1 deletion employee-web-client/src/pages/AddBooking/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { Box } from '@chakra-ui/react';

import { PageContainer } from 'shared/Layout/Page';
import { withErrorBoundary } from 'shared/ErrorBoundary';

import { AddBookingForm, useAddBookingNotification } from 'modules/booking/presentation';
import { useAddBooking } from 'modules/booking/infrastructure/command';
Expand Down Expand Up @@ -35,4 +36,4 @@ const AddBooking = () => {
);
};

export default AddBooking;
export default withErrorBoundary(AddBooking);
6 changes: 5 additions & 1 deletion employee-web-client/src/pages/Customers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import React from 'react';

import { DEFAULT_PARAMS } from 'utils/constant';
import { compose } from 'utils';

import { withPaginationParamsCorrector } from 'shared/Params';
import { PageContainer } from 'shared/Layout';
import { withErrorBoundary } from 'shared/ErrorBoundary';
import { CustomersCollection } from 'modules/customers/presentation';
Expand All @@ -20,4 +24,4 @@ const Customers = () => {
);
};

export default withErrorBoundary(Customers);
export default compose(withErrorBoundary, withPaginationParamsCorrector(DEFAULT_PARAMS))(Customers);
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { useNavigate } from 'react-router-dom';
import { useEmployeeContextSelector, useEnterpriseContextSelector } from 'modules/context';
import { CreateFacilityForm } from 'modules/facility/presentation';

import { buildUrl } from 'utils';
import { DEFAULT_PARAMS } from 'utils/constant';
import { IconButton } from 'shared/Button';
import { Icon } from 'shared/Icon';

Expand All @@ -25,9 +23,9 @@ const CreateFacilityTab = () => {
<DashboardTabs>
<HStack mb={{ base: 6, md: 10 }} m='0 auto' w='100%'>
<IconButton
onClick={() => navigate(buildUrl(`/dashboard/facilities`, DEFAULT_PARAMS))}
onClick={() => navigate(`/dashboard/facilities`)}
variant='ghost'
title={formatMessage({ id: 'bask-to-list', defaultMessage: 'Back to list' })}
title={formatMessage({ id: 'back-to-list', defaultMessage: 'Back to list' })}
icon={<Icon path={mdiArrowLeft} />}
/>
<Heading pl={3} as='h2' fontWeight='500' fontSize={{ base: 'xl', md: '2xl' }}>
Expand Down
6 changes: 2 additions & 4 deletions employee-web-client/src/pages/Dashboard/DashboardTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import React, { ReactNode } from 'react';
import { FormattedMessage } from 'react-intl';
import { TabList, TabPanel, TabPanels, Tabs as ChakraTabs, useBreakpointValue } from '@chakra-ui/react';
import { useLocation } from "react-router-dom";
import { useLocation } from 'react-router-dom';

import { TabLink } from 'shared/TabLink';
import { buildUrl } from 'utils';
import { DEFAULT_PARAMS } from 'utils/constant';

interface IProps {
children: ReactNode;
Expand All @@ -21,7 +19,7 @@ const DashboardTabs = ({ children }: IProps) => {
<TabLink isActive={pathname.includes('dashboard/enterprise')} to={`/dashboard/enterprise`} fontWeight='500'>
<FormattedMessage id='enterprise' defaultMessage='Enterprise' />
</TabLink>
<TabLink isActive={pathname.includes('dashboard/facilities')} to={buildUrl(`/dashboard/facilities`, DEFAULT_PARAMS)} fontWeight='500'>
<TabLink isActive={pathname.includes('dashboard/facilities')} to={`/dashboard/facilities`} fontWeight='500'>
<FormattedMessage id='facilities' defaultMessage='Facilities' />
</TabLink>
<TabLink isActive={pathname.includes('dashboard/new-facility')} to={'/dashboard/new-facility'} fontWeight='500'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React from 'react';
import { VStack } from '@chakra-ui/react';

import { withPaginationParamsCorrector } from 'shared/Params';

import { FacilitiesCollection } from 'modules/facility/presentation';
import { DEFAULT_PARAMS } from 'utils/constant';

import { DashboardTabs } from '../DashboardTabs';
import { Panel } from './Panel';
Expand All @@ -17,4 +20,4 @@ const FacilitiesTab = () => {
);
};

export default FacilitiesTab;
export default withPaginationParamsCorrector(DEFAULT_PARAMS)(FacilitiesTab);
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { useNavigate } from 'react-router-dom';
import { isMobileOnly } from 'react-device-detect';
import { mdiArrowLeft, mdiContentSaveEdit } from '@mdi/js';

import { buildUrl } from 'utils';
import { DEFAULT_PARAMS } from 'utils/constant';
import { Button, IconButton } from 'shared/Button';
import { Icon } from 'shared/Icon';
import { IFacility } from 'modules/facility/application/types';
Expand All @@ -29,9 +27,9 @@ const FacilityPanel = ({ facility }: IProps) => {
return (
<HStack w='100%' justify='space-between'>
<IconButton
onClick={() => navigate(buildUrl(`/dashboard/facilities`, DEFAULT_PARAMS))}
onClick={() => navigate(`/dashboard/facilities`)}
variant='ghost'
title={formatMessage({ id: 'bask-to-list', defaultMessage: 'Back to list' })}
title={formatMessage({ id: 'back-to-list', defaultMessage: 'Back to list' })}
icon={<Icon path={mdiArrowLeft} />}
/>
<HStack>
Expand Down
6 changes: 5 additions & 1 deletion employee-web-client/src/pages/Employees/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React from 'react';

import { compose } from 'utils';

import { withPaginationParamsCorrector } from 'shared/Params';
import { PageContainer } from 'shared/Layout/Page';
import { withErrorBoundary } from 'shared/ErrorBoundary';
import { CollectionContainer } from 'shared/Collection';

import { EmployeesCollection } from 'modules/employees/presentation';
import { EMPLOYEE_COLLECTION_DEFAULT_PARAMS } from 'modules/employees/application';

import { Header } from './Header';
import { Panel } from './Panel';
Expand All @@ -21,4 +25,4 @@ const Employees = () => {
);
};

export default withErrorBoundary(Employees);
export default compose(withErrorBoundary, withPaginationParamsCorrector(EMPLOYEE_COLLECTION_DEFAULT_PARAMS))(Employees);
12 changes: 9 additions & 3 deletions employee-web-client/src/pages/Offers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import React from 'react';

import { compose } from 'utils';

import { CollectionContainer } from 'shared/Collection';
import { withErrorBoundary } from 'shared/ErrorBoundary';
import { withPaginationParamsCorrector } from 'shared/Params';
import { PageContainer } from 'shared/Layout/Page';

import { OffersCollection } from 'modules/offers/presentation';
import { OFFER_COLLECTION_DEFAULT_PARAMS } from 'modules/offers/application';
import { OffersCollectionToolbox } from 'modules/offers/presentation/OffersCollection/OffersCollectionToolbox';

import { Header } from './Header';
import { OffersCollectionToolbox } from '../../modules/offers/presentation/OffersCollection/OffersCollectionToolbox';
import { CollectionContainer } from '../../shared/Collection';

const Offers = () => {
return (
Expand All @@ -19,4 +25,4 @@ const Offers = () => {
);
};

export default Offers;
export default compose(withErrorBoundary, withPaginationParamsCorrector(OFFER_COLLECTION_DEFAULT_PARAMS))(Offers);
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { GridItem, HStack } from '@chakra-ui/react';
import { mdiArrowLeft } from '@mdi/js';
import { DateInput } from 'react-hook-form-chakra-fields';

import { buildUrl } from 'utils';
import { DEFAULT_PARAMS } from 'utils/constant';
import { dayjs } from 'utils/dayjs';

import { IconButton } from 'shared/Button';
Expand All @@ -28,9 +26,9 @@ const ScheduleDatePicker = ({ setWeek, trackedDay, endDate, startDate }: IProps)
<GridItem display={{ base: 'none', lg: 'block' }} colSpan={1} mt={2}>
<HStack spacing={4} maxW='300px'>
<IconButton
onClick={() => navigate(buildUrl(`/schedules`, DEFAULT_PARAMS))}
onClick={() => navigate(`/schedules`)}
variant='ghost'
title={formatMessage({ id: 'bask-to-list', defaultMessage: 'Back to list' })}
title={formatMessage({ id: 'back-to-list', defaultMessage: 'Back to list' })}
icon={<Icon path={mdiArrowLeft} />}
/>
<DateInput
Expand Down
8 changes: 7 additions & 1 deletion employee-web-client/src/pages/Schedules/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import React from 'react';
import { PageContainer } from 'shared/Layout/Page';
import { CollectionContainer } from 'shared/Collection';

import { compose } from 'utils';
import { DEFAULT_PARAMS } from 'utils/constant';

import { withErrorBoundary } from 'shared/ErrorBoundary';
import { withPaginationParamsCorrector } from 'shared/Params';

import { SchedulesCollection } from 'modules/schedules/presentation';

import { Header } from './Header';
Expand All @@ -17,4 +23,4 @@ const Schedules = () => {
);
};

export default Schedules;
export default compose(withErrorBoundary, withPaginationParamsCorrector(DEFAULT_PARAMS))(Schedules);
11 changes: 4 additions & 7 deletions employee-web-client/src/shared/Layout/Navigation/useGetLinks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { useIntl } from 'react-intl';
import { mdiAccountMultiple, mdiBookMultiple, mdiCalendarCheck, mdiClipboardTextSearch, mdiCalendarWeek, mdiLan } from '@mdi/js';

import { buildUrl } from 'utils';
import { DEFAULT_PARAMS } from 'utils/constant';

export const useGetLinks = () => {
const { formatMessage } = useIntl();

Expand All @@ -23,7 +20,7 @@ export const useGetLinks = () => {
id: 'schedules',
defaultMessage: 'Schedules',
}),
to: buildUrl('schedules', DEFAULT_PARAMS),
to: 'schedules',
signature: 'schedules',
},
{
Expand All @@ -41,7 +38,7 @@ export const useGetLinks = () => {
id: 'customers',
defaultMessage: 'Customers',
}),
to: buildUrl('customers', DEFAULT_PARAMS),
to: 'customers',
signature: 'customers',
},
{
Expand All @@ -50,7 +47,7 @@ export const useGetLinks = () => {
id: 'employees',
defaultMessage: 'Employees',
}),
to: buildUrl('employees', DEFAULT_PARAMS),
to: 'employees',
signature: 'employees',
},
{
Expand All @@ -59,7 +56,7 @@ export const useGetLinks = () => {
id: 'offers',
defaultMessage: 'Offers',
}),
to: buildUrl('offers', DEFAULT_PARAMS),
to: 'offers',
signature: 'offers',
},
];
Expand Down
1 change: 1 addition & 0 deletions employee-web-client/src/shared/Params/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { useQueryParams } from './useQueryParams';
export { QueryParamsProvider, useQueryParamsConsumer } from './QueryParamsProvider';
export { filtersAreApplied } from './filtersAreApplied';
export { withPaginationParamsCorrector } from './withPaginationParamsCorrector';
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { Component, ComponentType } from 'react';

import { stringify } from './queryString';
import { ShareContext, Values } from './QueryParamsProvider';
import { LocationManager } from './LocationManager';

type MapFn<Params> = (routeProps: Values & { params: Params }) => Params;

export const mapQueryParamsBeforeRender =
<Params extends object>(mapFn: MapFn<Params>) =>
(Wrapper: ComponentType) =>
// eslint-disable-next-line react/display-name
class extends Component {
static contextType = ShareContext;

state = {
canRender: false,
};

componentDidMount() {
const { history, location } = this.context;

if (!history || !location) {
throw new Error(`Missing QueryParamsProvider`);
}

const { params } = LocationManager<Params>(location);

history.replace(stringify(location.pathname)(mapFn({ history, location, params })));
this.setState({ canRender: true });
}

render() {
if (!this.state.canRender) return null;

return <Wrapper {...this.props} />;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { mapQueryParamsBeforeRender } from './mapQueryParamsBeforeRender';

import { IQueryParams } from 'types';

const withPaginationParamsCorrector = (defaults: IQueryParams) =>
mapQueryParamsBeforeRender<IQueryParams>(({ params, location }) => {
if (location.search === '') {
return defaults;
}

if ([isNaN(params.limit), isNaN(params.offset)].some(val => val)) {
return defaults;
}

return params;
});

export { withPaginationParamsCorrector };
16 changes: 16 additions & 0 deletions employee-web-client/src/utils/compose.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ComponentClass, ComponentType } from 'react';

interface ComponentEnhancer<TInner, TOutter> {
(component: ComponentType<TInner>): ComponentClass<TOutter>;
}

function compose<TInner, TOutter>(...funcs: Function[]): ComponentEnhancer<TInner, TOutter> {
return funcs.reduce(
(a, b) =>
(...args: Function[]) =>
a(b(...args)),
(arg: unknown) => arg,
) as ComponentEnhancer<TInner, TOutter>;
}

export { compose };
Loading

0 comments on commit d8dc899

Please sign in to comment.