diff options
Diffstat (limited to 'src/services/waybills')
-rw-r--r-- | src/services/waybills/WaybillForm.tsx | 86 | ||||
-rw-r--r-- | src/services/waybills/WaybillPanel.tsx | 42 | ||||
-rw-r--r-- | src/services/waybills/index.ts | 27 |
3 files changed, 155 insertions, 0 deletions
diff --git a/src/services/waybills/WaybillForm.tsx b/src/services/waybills/WaybillForm.tsx new file mode 100644 index 0000000..c11ab9e --- /dev/null +++ b/src/services/waybills/WaybillForm.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import { Form, FormikProps } from 'formik'; +import _ from 'lodash'; +import moment from 'moment'; +import Input from '../../components/Input'; +import Button from '../../components/Button'; +import Select from '../../components/Select'; +import Paper from '../../components/Paper'; +import hooks from '../../hooks/useAPIClient'; + + +const mapper = (item: any) => ({ key: item._id, label: item.name }); + + +const WaybillForm: React.FC<FormikProps<any>> = ({ setFieldValue, values }) => { + const { data: products } = hooks.products.useList(); + const { data: contractors } = hooks.contractors.useList(); + + if (!values.date) setFieldValue('date', moment().format('YYYY-MM-DD')); + if (!values.contractorId && contractors?.length) setFieldValue('contractorId', contractors[0]._id); + + const handleAddRecord = () => setFieldValue('records', [...values.records, { + productId: _.map(products, '_id').reduce((acc, id) => { + return acc || (!_.map(values.records, 'productId').includes(id) && id); + }, false), + price: '', + quantity: 1, + }]); + + const handleRemoveRecord = (index: number) => () => { + const records = [...values.records]; + records.splice(index, 1); + setFieldValue('records', records); + }; + + return ( + <Form id="form"> + <Select + name="contractorId" + label="Контрагент" + options={contractors?.map(mapper)} + /> + <div className="grid grid-cols-2"> + <Select + name="operation" + label="Операция" + options={[ + { key: 'in', label: 'Приход' }, + { key: 'out', label: 'Расход' }, + ]} + /> + <Input name="date" type="date" label="Дата" /> + </div> + {values.records.map((record: any, index: number) => ( + <Paper variant="outlined" className="my-4 md:mx-4" key={`${index}-${record.productId}`}> + <Select + name={`records.${index}.productId`} + label="Товар" + options={products?.map(mapper)} + required + /> + <div className="grid grid-cols-3"> + <Input + name={`records.${index}.price`} + type="number" + label="Цена" + required + /> + <Input + name={`records.${index}.quantity`} + type="number" + label="Количество" + required + /> + <div className="flex justify-end items-end"> + <Button onClick={handleRemoveRecord(index)} size="sm" variant="outlined">Удалить</Button> + </div> + </div> + </Paper> + ))} + <Button onClick={handleAddRecord} variant="outlined" size="sm">Добавить товар</Button> + </Form> + ); +}; + +export default WaybillForm; diff --git a/src/services/waybills/WaybillPanel.tsx b/src/services/waybills/WaybillPanel.tsx new file mode 100644 index 0000000..101a871 --- /dev/null +++ b/src/services/waybills/WaybillPanel.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import Button from '../../components/Button'; +import { patch, baseURL } from '../../requests'; +import { PanelProps } from '../../containers/Service/ServiceContext'; + + +const WaybillPanel: React.FC<PanelProps> = ({ item, mutate }) => { + const history = useHistory(); + + const handleChangeStatus = (status: any) => patch(`/waybills/${item._id}`, { status }) + .then(() => { + history.push('/waybills'); + mutate({ ...item, status }); + }); + + const handlePrint = () => window.open(`${baseURL}/spreadsheets/${item._id}`, '_blank'); + + const handleExecute = () => handleChangeStatus('executed'); + const handleCancel = () => handleChangeStatus('cancelled'); + + const executed = item.status === 'executed'; + + return ( + <div className="lg:m-4 p-4 flex flex-col lg:pl-16 lg:border-l"> + <div className="grid lg:grid-cols-2"> + <Button route={`/contractors/${item.contractorId}`} variant="outlined"> + Перейти к контрагенту + </Button> + <Button onClick={handlePrint} variant="outlined"> + Печать + </Button> + <span className="text-lg text-center mt-4">Итоговая сумма: ${item.total}</span> + <Button onClick={executed ? handleCancel : handleExecute} size="lg"> + {executed ? 'Откатить' : 'Провести'} + </Button> + </div> + </div> + ); +}; + +export default WaybillPanel; diff --git a/src/services/waybills/index.ts b/src/services/waybills/index.ts new file mode 100644 index 0000000..f8a4be6 --- /dev/null +++ b/src/services/waybills/index.ts @@ -0,0 +1,27 @@ +import Form from './WaybillForm'; +import Panel from './WaybillPanel'; +import { waybillStatusNames, operationNames } from '../constants'; + +const service = { + route: 'waybills', + name: 'Накладные', + nameSingular: 'Накладная', + tableFields: [ + { + key: 'status', + label: 'Статус', + transform: (status: 'waiting' | 'executed' | 'cancelled') => waybillStatusNames[status], + }, + { key: 'operation', label: 'Операция', transform: (op: 'in' | 'out') => operationNames[op] }, + { key: 'total', label: 'Сумма' }, + { key: 'contractor.name', label: 'Контрагент' }, + ], + default: { + operation: 'in', + records: [], + }, + Form, + Panel, +}; + +export default service; |