summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eug-vs@keemail.me>2021-04-17 16:42:30 +0300
committereug-vs <eug-vs@keemail.me>2021-04-17 16:42:30 +0300
commitf3d3471e697d6ebede4fa584c8671fb686028381 (patch)
tree3df451176c8c9be81c6fe812d2a0a6be4aa918b0
parent944996544868f403dbe807f4b8183ee482d31811 (diff)
downloadcommercel-ui-f3d3471e697d6ebede4fa584c8671fb686028381.tar.gz
refactor: move move filters to ServiceFilters
-rw-r--r--src/containers/Page.tsx62
-rw-r--r--src/lib/ServiceFilters.tsx74
-rw-r--r--src/lib/ServiceList.tsx44
3 files changed, 92 insertions, 88 deletions
diff --git a/src/containers/Page.tsx b/src/containers/Page.tsx
index 69f3513..887e839 100644
--- a/src/containers/Page.tsx
+++ b/src/containers/Page.tsx
@@ -1,62 +1,30 @@
import React from 'react';
-import { useLocation } from 'react-router-dom';
import Paper from '../components/Paper';
import Button from '../components/Button';
-import { Action, Filter } from '../lib/ServiceContext';
-import { SelectBase } from '../components/Select';
+import { Action } from '../lib/ServiceContext';
interface Props {
title?: string;
actions?: Action[];
- filters?: Filter[];
- applyFilter?: (key: string, value: string) => void;
- resetFilters?: () => void;
+ filters?: JSX.Element;
className?: string;
}
const style = 'mb-2 flex justify-between md:flex-row md:items-center';
-const Page: React.FC<Props> = ({ title, actions, filters, applyFilter, resetFilters, className, children }) => {
- const location = useLocation();
-
- const handleFilterChange = (key: string) => (event: React.ChangeEvent<HTMLSelectElement>) => {
- if (applyFilter) applyFilter(key, event.target.value);
- };
-
- return (
- <Paper className="xl:m-5">
- <div className={`${style} ${(actions?.length || 0) > 1 ? 'flex-col items-start' : 'flex-row items-center'}`}>
- <span className="text-2xl font-bold">{title}</span>
- <div className="flex">
- <div className="mr-6 flex items-center">
- {filters && location.search && (
- <span
- onClick={resetFilters}
- role="presentation"
- className="underline mr-2 cursor-pointer"
- >
- Сбросить фильтры
- </span>
- )}
- {filters?.map(filter => (
- <SelectBase
- key={filter.key}
- options={filter.options || []}
- value={filter.value}
- onChange={handleFilterChange(filter.key)}
- />
- ))}
- </div>
- <div>
- {actions?.map(action => (<Button {...action} key={action.name} size="sm">{action.name}</Button>))}
- </div>
- </div>
- </div>
- <div className={className}>
- {children}
+const Page: React.FC<Props> = ({ title, actions, filters, className, children }) => (
+ <Paper className="xl:m-5">
+ <div className={`${style} ${(actions?.length || 0) > 1 ? 'flex-col items-start' : 'flex-row items-center'}`}>
+ <span className="text-2xl font-bold">{title}</span>
+ <div className="flex">
+ {filters}
+ {actions?.map(action => (<Button {...action} key={action.name} size="sm">{action.name}</Button>))}
</div>
- </Paper>
- );
-};
+ </div>
+ <div className={className}>
+ {children}
+ </div>
+ </Paper>
+);
export default Page;
diff --git a/src/lib/ServiceFilters.tsx b/src/lib/ServiceFilters.tsx
new file mode 100644
index 0000000..4a7f166
--- /dev/null
+++ b/src/lib/ServiceFilters.tsx
@@ -0,0 +1,74 @@
+import React, { useContext } from 'react';
+import { useHistory } from 'react-router-dom';
+import _ from 'lodash';
+import hooks from '../hooks/useAPIClient';
+import useQuery from '../hooks/useQuery';
+import ServiceContext, { Filter } from './ServiceContext';
+import { SelectBase } from '../components/Select';
+
+const getOptionLabel = (item: any, filter: Filter) => {
+ const value = _.get(item, filter.as || filter.key);
+ return filter.transform ? filter.transform(value) : value;
+};
+
+
+const ServiceFilters: React.FC = () => {
+ const service = useContext(ServiceContext);
+ const query = useQuery();
+ const history = useHistory();
+ const { data } = hooks[service.route].useList('', { revalidateOnMount: !_.isEmpty(query) });
+
+ const filters = service.filters?.map(filter => {
+ const options = _
+ .uniqBy(data, filter.key)
+ .map((item: any) => ({
+ key: _.get(item, filter.key),
+ label: getOptionLabel(item, filter),
+ }));
+
+ // Add default option
+ options?.unshift({
+ key: '-',
+ label: filter.label,
+ });
+
+ const value = _.get(query, filter.key) || '-';
+
+ return { ...filter, options, value };
+ });
+
+ const handleFilterChange = (key: string) => (event: React.ChangeEvent<HTMLSelectElement>) => {
+ const { value } = event.target;
+ const updatedQuery = { ...query, [key]: value };
+ if (value === '-') delete updatedQuery[key];
+
+ const queryString = new URLSearchParams(updatedQuery);
+ history.push(`${service.route}?${queryString}`);
+ };
+
+ const resetFilters = () => history.push(service.route);
+
+ return (
+ <div className="mr-6 flex items-center">
+ {filters && !_.isEmpty(query) && (
+ <span
+ onClick={resetFilters}
+ role="presentation"
+ className="underline mr-2 cursor-pointer"
+ >
+ Сбросить фильтры
+ </span>
+ )}
+ {filters?.map(filter => (
+ <SelectBase
+ key={filter.key}
+ options={filter.options || []}
+ value={filter.value}
+ onChange={handleFilterChange(filter.key)}
+ />
+ ))}
+ </div>
+ );
+};
+
+export default ServiceFilters;
diff --git a/src/lib/ServiceList.tsx b/src/lib/ServiceList.tsx
index 9f6835a..ae17a9c 100644
--- a/src/lib/ServiceList.tsx
+++ b/src/lib/ServiceList.tsx
@@ -4,46 +4,20 @@ import _ from 'lodash';
import Page from '../containers/Page';
import ListTable from '../components/ListTable';
import hooks from '../hooks/useAPIClient';
-import ServiceContext, { Filter } from './ServiceContext';
-import useQuery from '../hooks/useQuery';
-
-const getOptionLabel = (item: any, filter: Filter) => {
- const value = _.get(item, filter.as || filter.key);
- return filter.transform ? filter.transform(value) : value;
-};
+import ServiceContext from './ServiceContext';
+import ServiceFilters from './ServiceFilters';
const ServiceList: React.FC = () => {
const service = useContext(ServiceContext);
const history = useHistory();
const location = useLocation();
- const query = useQuery();
const { data } = hooks[service.route].useList(location.search);
- const { data: unfilteredData } = hooks[service.route].useList('', { revalidateOnMount: !!location.search });
const actions = service.actions || [{
name: 'Добавить',
route: `/${service.route}/add${location.search}`,
}];
- const filters = service.filters?.map(filter => {
- const options = _
- .uniqBy(unfilteredData, filter.key)
- .map((item: any) => ({
- key: _.get(item, filter.key),
- label: getOptionLabel(item, filter),
- }));
-
- // Add default option
- options?.unshift({
- key: '-',
- label: filter.label,
- });
-
- const value = _.get(query, filter.key);
-
- return { ...filter, options, value };
- });
-
const handleRowClick = (item: any) => {
const route = service.rowLink
? service.rowLink(item)
@@ -52,23 +26,11 @@ const ServiceList: React.FC = () => {
history.push(route);
};
- const applyFilter = (key: string, value: string) => {
- const updatedQuery = { ...query, [key]: value };
- if (value === '-') delete updatedQuery[key];
-
- const queryString = new URLSearchParams(updatedQuery);
- history.push(`${service.route}?${queryString}`);
- };
-
- const resetFilters = () => history.push(service.route);
-
return (
<Page
title={service.name}
actions={actions}
- filters={filters}
- applyFilter={applyFilter}
- resetFilters={resetFilters}
+ filters={<ServiceFilters />}
>
<ListTable items={data} fields={service.tableFields} handleRowClick={handleRowClick} />
</Page>