summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eug-vs@keemail.me>2021-03-14 06:30:22 +0300
committereug-vs <eug-vs@keemail.me>2021-03-14 06:30:22 +0300
commit610584c3ce986cdea431180f545e023cee14d5d2 (patch)
treea4c1b2a3de7b4ccf7cef8a4bdf5d366cc62492b5
parent790cb41dfe3283fea96789fbacc28a077c474e44 (diff)
downloadcommercel-ui-610584c3ce986cdea431180f545e023cee14d5d2.tar.gz
feat: implement Product Add/Edit
-rw-r--r--src/containers/Home.tsx2
-rw-r--r--src/containers/Page.tsx2
-rw-r--r--src/containers/ProductForm.tsx51
-rw-r--r--src/containers/Products.tsx20
-rw-r--r--src/hooks/useAPIClient.ts18
-rw-r--r--src/index.tsx1
6 files changed, 76 insertions, 18 deletions
diff --git a/src/containers/Home.tsx b/src/containers/Home.tsx
index f39861a..0deefd1 100644
--- a/src/containers/Home.tsx
+++ b/src/containers/Home.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import Page from '../containers/Page';
+import Page from './Page';
import Button from '../components/Button';
const Home: React.FC = () => (
diff --git a/src/containers/Page.tsx b/src/containers/Page.tsx
index f6ae814..a7c0964 100644
--- a/src/containers/Page.tsx
+++ b/src/containers/Page.tsx
@@ -7,7 +7,7 @@ export interface Action extends ButtonProps {
}
interface Props {
- title: string;
+ title?: string;
actions?: Action[];
}
diff --git a/src/containers/ProductForm.tsx b/src/containers/ProductForm.tsx
index d79b1d1..0d21df9 100644
--- a/src/containers/ProductForm.tsx
+++ b/src/containers/ProductForm.tsx
@@ -1,14 +1,51 @@
import React from 'react';
-import Page, { Action } from '../containers/Page';
+import { useParams, useHistory } from 'react-router-dom';
+import { Formik, Form, Field } from 'formik';
+import Page, { Action } from './Page';
+import Input from '../components/Input';
+import { useProduct } from '../hooks/useAPIClient';
+import { post, patch } from '../requests';
+
+interface Params {
+ id: string;
+}
const actions: Action[] = [
- { name: 'Назад', route: '/', variant: 'outlined' },
- { name: 'Сохранить', route: '/' },
+ { name: 'Назад', variant: 'outlined', route: '..' },
+ { name: 'Сохранить', type: 'submit', form: 'productForm' },
];
-const ProductForm: React.FC = () => (
- <Page title="Продукт" actions={actions}>
- </Page>
-);
+const ProductForm: React.FC = () => {
+ const history = useHistory();
+ const { id } = useParams<Params>();
+ const { data: product } = useProduct(id);
+
+ const onSubmit = (values: any) => {
+ const promise = id
+ ? patch(`/products/${id}`, values)
+ : post('/products', values);
+ return promise.then(() => history.push('/products'));
+ };
+
+ return (
+ <Page title={id ? product?.name : 'Новый товар'} actions={actions}>
+ {(!id || product) && (
+ <Formik
+ initialValues={product || { name: '', price: '' }}
+ onSubmit={onSubmit}
+ >
+ {() => (
+ <Form id="productForm">
+ <div className="max-w-lg">
+ <Field name="name" label="Название" as={Input} />
+ <Field name="price" type="number" label="Цена ($)" as={Input} />
+ </div>
+ </Form>
+ )}
+ </Formik>
+ )}
+ </Page>
+ );
+};
export default ProductForm;
diff --git a/src/containers/Products.tsx b/src/containers/Products.tsx
index 3542df1..0b6ea70 100644
--- a/src/containers/Products.tsx
+++ b/src/containers/Products.tsx
@@ -1,26 +1,32 @@
import React from 'react';
-import Page from '../containers/Page';
+import { useHistory } from 'react-router-dom';
+import Page from './Page';
import ListTable from '../components/ListTable';
import { useProducts } from '../hooks/useAPIClient';
const fields = [
- { key: '_id', label: 'ID' },
{ key: 'name', label: 'Название' },
- { key: 'type', label: 'Тип' },
+ { key: 'price', label: 'Цена' },
];
const actions = [
- { name: 'Добавить', route: 'products/add' }
+ { name: 'Добавить', route: 'products/add' },
];
-const Home: React.FC = () => {
+const Products: React.FC = () => {
+ const history = useHistory();
const { data: products } = useProducts();
+ const handleRowClick = (index: number) => {
+ const product = products && products[index];
+ history.push(`/products/edit/${product?._id}`);
+ };
+
return (
<Page title="Товары" actions={actions}>
- <ListTable items={products} fields={fields} />
+ <ListTable items={products} fields={fields} handleRowClick={handleRowClick} />
</Page>
);
};
-export default Home;
+export default Products;
diff --git a/src/hooks/useAPIClient.ts b/src/hooks/useAPIClient.ts
index a27453e..b36cfec 100644
--- a/src/hooks/useAPIClient.ts
+++ b/src/hooks/useAPIClient.ts
@@ -1,4 +1,5 @@
import useSWR, { responseInterface } from 'swr';
+import _ from 'lodash';
import { get } from '../requests';
type Response<T> = responseInterface<T, Error>;
@@ -16,6 +17,19 @@ export interface Product {
const fetcher = (endpoint: string) => get(endpoint).then(response => response.data);
-export const useProducts = (): Response<Product[]> => {
- return useSWR('/products', fetcher);
+export const useProducts = (options = {}): Response<Product[]> => {
+ return useSWR('/products', fetcher, options);
};
+
+export const useProduct = (_id: string): Response<Product> => {
+ const { data: preloadedProducts } = useProducts({ revalidateOnMount: false });
+ const result = useSWR(`/products/${_id}`, fetcher);
+ if (!result.data && result.isValidating) {
+ // If we are waiting for the first result, check if we can maybe
+ // get the data from already cached list for the time-being
+ const product = _.find(preloadedProducts, { _id });
+ return { ...result, data: product };
+ }
+ return result;
+};
+
diff --git a/src/index.tsx b/src/index.tsx
index 4972454..8af383e 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -25,6 +25,7 @@ const App: React.FC = () => (
<Route exact path="/" component={Home} />
<Route exact path="/products" component={Products} />
<Route exact path="/products/add" component={ProductForm} />
+ <Route exact path="/products/edit/:id" component={ProductForm} />
</Switch>
</Router>
);