summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authoreug-vs <eug-vs@keemail.me>2021-03-26 01:06:44 +0300
committereug-vs <eug-vs@keemail.me>2021-03-26 01:06:44 +0300
commit865b41114060765308d560181f4996c0aa7a3e74 (patch)
tree578d3089e05131445b0a8b6d5e69a3a76aaf7e73 /src/lib
parent91e1a3b4ccaa822097e4adfea5f51056b010fdd6 (diff)
downloadcommercel-ui-865b41114060765308d560181f4996c0aa7a3e74.tar.gz
refactor: move Service to lib/
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Service.tsx25
-rw-r--r--src/lib/ServiceContext.tsx37
-rw-r--r--src/lib/ServiceItem.tsx59
-rw-r--r--src/lib/ServiceList.tsx35
4 files changed, 156 insertions, 0 deletions
diff --git a/src/lib/Service.tsx b/src/lib/Service.tsx
new file mode 100644
index 0000000..b527531
--- /dev/null
+++ b/src/lib/Service.tsx
@@ -0,0 +1,25 @@
+import React, { useContext } from 'react';
+import { Route, Switch, useRouteMatch } from 'react-router-dom';
+import _ from 'lodash';
+import ServiceList from './ServiceList';
+import ServiceItem from './ServiceItem';
+import ServiceContext from './ServiceContext';
+
+
+const Service: React.FC = () => {
+ const { path } = useRouteMatch();
+ const service = useContext(ServiceContext);
+
+ return (
+ <Switch>
+ <Route exact path={path} component={ServiceList} />
+ <Route path={`${path}/add`} component={ServiceItem} />
+ {_.map(service.routes, (component, route) => (
+ <Route path={`${path}/${route}`} component={component} key={route} />
+ ))}
+ <Route path={`${path}/:id`} component={ServiceItem} />
+ </Switch>
+ );
+};
+
+export default Service;
diff --git a/src/lib/ServiceContext.tsx b/src/lib/ServiceContext.tsx
new file mode 100644
index 0000000..93cac4e
--- /dev/null
+++ b/src/lib/ServiceContext.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { FormikProps } from 'formik';
+import { Props as ButtonProps } from '../components/Button';
+import { Field } from '../components/ListTable';
+
+export interface Action extends ButtonProps {
+ name: string;
+}
+
+export interface PanelProps {
+ item: any;
+ mutate: (item: any) => void;
+}
+
+export interface ServiceParams {
+ route: string;
+ name: string;
+ tableFields: Field[];
+ nameSingular?: string;
+ default?: Record<string, any>;
+ routes?: Record<string, React.FC>;
+ actions?: Action[];
+ rowLink?: (item: any) => string;
+ Form?: React.FC<FormikProps<any>>;
+ Panel?: React.FC<PanelProps>;
+}
+
+const ServiceContext = React.createContext<ServiceParams>({
+ route: '',
+ name: '',
+ nameSingular: '',
+ tableFields: [],
+ default: {},
+});
+
+export const ServiceProvider = ServiceContext.Provider;
+export default ServiceContext;
diff --git a/src/lib/ServiceItem.tsx b/src/lib/ServiceItem.tsx
new file mode 100644
index 0000000..6a0a99b
--- /dev/null
+++ b/src/lib/ServiceItem.tsx
@@ -0,0 +1,59 @@
+import React, { useContext } from 'react';
+import { useParams, useHistory } from 'react-router-dom';
+import { Formik } from 'formik';
+import _ from 'lodash';
+import Page from '../containers/Page';
+import hooks from '../hooks/useAPIClient';
+import useQuery from '../hooks/useQuery';
+import { post, patch, del } from '../requests';
+import ServiceContext, { Action } from './ServiceContext';
+
+interface Params {
+ id: string;
+}
+
+const ServiceItem: React.FC = () => {
+ const service = useContext(ServiceContext);
+ const history = useHistory();
+ const query = useQuery();
+ const { id } = useParams<Params>();
+ const { data: item, mutate } = hooks[service.route].useItem(id);
+
+ const handleDelete = () => del(`/${service.route}/${id}`)
+ .then(() => history.push(`/${service.route}`));
+
+ const onSubmit = (values: any) => {
+ const promise = id
+ ? patch(`/${service.route}/${id}`, values)
+ : post(`/${service.route}`, values);
+ return promise.then(response => {
+ mutate(response.data);
+ history.push(`/${service.route}`);
+ });
+ };
+
+ const actions: Action[] = _.compact([
+ { name: 'Назад', variant: 'outlined', onClick: history.goBack },
+ id && { name: 'Удалить', variant: 'outlined', onClick: handleDelete },
+ { name: 'Сохранить', type: 'submit', form: 'form' },
+ ]);
+
+ return (
+ <Page
+ title={id ? item?.name : `Новый ${service.nameSingular}`}
+ actions={actions}
+ className="grid lg:grid-cols-2"
+ >
+ {(!id || item) && (
+ <Formik
+ initialValues={_.defaults(item, query, service.default)}
+ onSubmit={onSubmit}
+ children={service.Form}
+ />
+ )}
+ {item && service.Panel && <service.Panel item={item} mutate={mutate} />}
+ </Page>
+ );
+};
+
+export default ServiceItem;
diff --git a/src/lib/ServiceList.tsx b/src/lib/ServiceList.tsx
new file mode 100644
index 0000000..74ad10b
--- /dev/null
+++ b/src/lib/ServiceList.tsx
@@ -0,0 +1,35 @@
+import React, { useContext } from 'react';
+import { useHistory, useLocation } from 'react-router-dom';
+import Page from '../containers/Page';
+import ListTable from '../components/ListTable';
+import hooks from '../hooks/useAPIClient';
+import ServiceContext from './ServiceContext';
+
+const ServiceList: React.FC = () => {
+ const service = useContext(ServiceContext);
+ const history = useHistory();
+ const location = useLocation();
+ const { data } = hooks[service.route].useList(location.search);
+
+ const actions = service.actions || [{
+ name: 'Добавить',
+ route: `/${service.route}/add${location.search}`,
+ }];
+
+ const handleRowClick = (index: number) => {
+ const item = data && data[index];
+ const route = service.rowLink
+ ? service.rowLink(item)
+ : `/${service.route}/${item?._id}`;
+
+ history.push(route);
+ };
+
+ return (
+ <Page title={service.name} actions={actions}>
+ <ListTable items={data} fields={service.tableFields} handleRowClick={handleRowClick} />
+ </Page>
+ );
+};
+
+export default ServiceList;