diff options
-rw-r--r-- | src/containers/Home.tsx | 2 | ||||
-rw-r--r-- | src/containers/Page.tsx | 2 | ||||
-rw-r--r-- | src/containers/ProductForm.tsx | 51 | ||||
-rw-r--r-- | src/containers/Products.tsx | 20 | ||||
-rw-r--r-- | src/hooks/useAPIClient.ts | 18 | ||||
-rw-r--r-- | src/index.tsx | 1 |
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> ); |