diff options
author | eug-vs <eug-vs@keemail.me> | 2021-03-26 01:56:04 +0300 |
---|---|---|
committer | eug-vs <eug-vs@keemail.me> | 2021-03-26 01:56:04 +0300 |
commit | ef742ea9b2f246f74eae74169675a331679ad41c (patch) | |
tree | 693e92f3e6c2897038875550a12bbc1191b6d5c0 | |
parent | 865b41114060765308d560181f4996c0aa7a3e74 (diff) | |
download | commercel-ui-ef742ea9b2f246f74eae74169675a331679ad41c.tar.gz |
feat: add strong typing where possible
-rw-r--r-- | src/components/Input.tsx | 4 | ||||
-rw-r--r-- | src/components/ListTable.tsx | 4 | ||||
-rw-r--r-- | src/hooks/useAPIClient.ts | 22 | ||||
-rw-r--r-- | src/hooks/useQuery.ts | 2 | ||||
-rw-r--r-- | src/lib/ServiceContext.tsx | 16 | ||||
-rw-r--r-- | src/services/contractors/ContractorPanel.tsx | 3 | ||||
-rw-r--r-- | src/services/contractors/index.ts | 3 | ||||
-rw-r--r-- | src/services/products/index.ts | 5 | ||||
-rw-r--r-- | src/services/transfers/TransferForm.tsx | 5 | ||||
-rw-r--r-- | src/services/transfers/TransfersUpload.tsx | 12 | ||||
-rw-r--r-- | src/services/transfers/index.ts | 4 | ||||
-rw-r--r-- | src/services/types.ts | 40 | ||||
-rw-r--r-- | src/services/waybills/WaybillForm.tsx | 7 | ||||
-rw-r--r-- | src/services/waybills/WaybillPanel.tsx | 5 | ||||
-rw-r--r-- | src/services/waybills/index.ts | 3 |
15 files changed, 81 insertions, 54 deletions
diff --git a/src/components/Input.tsx b/src/components/Input.tsx index a8a6f31..298d14c 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -3,17 +3,19 @@ import { Field } from 'formik'; export interface Props extends React.InputHTMLAttributes<HTMLInputElement> { label?: string; + ref?: React.Ref<HTMLInputElement> } const focusStyles = 'focus:outline-none focus:shadow focus:border-gray-400'; const baseStyles = 'p-2 border bg-white border-gray-300 rounded-sm'; -const InputBase: React.FC<Props> = ({ label, ...props }) => { +const InputBase: React.FC<Props> = ({ label, ref, ...props }) => { return ( <div className="m-2 mb-4 flex flex-col"> <label htmlFor={props?.name} className="mb-1 text-sm text-gray-600">{label}</label> <input id={props?.name} + ref={ref} placeholder={label} className={`${baseStyles} ${focusStyles}`} {...props} diff --git a/src/components/ListTable.tsx b/src/components/ListTable.tsx index 79e1ecd..89a2e06 100644 --- a/src/components/ListTable.tsx +++ b/src/components/ListTable.tsx @@ -7,8 +7,8 @@ export interface Field { transform?: (value: string) => JSX.Element | string; } -interface Props { - items?: any[]; +interface Props<T = any> { + items?: T[]; fields: Field[]; handleRowClick?: (index: number) => void; } diff --git a/src/hooks/useAPIClient.ts b/src/hooks/useAPIClient.ts index b523d1f..e992b42 100644 --- a/src/hooks/useAPIClient.ts +++ b/src/hooks/useAPIClient.ts @@ -28,28 +28,6 @@ const registerServiceHooks = <Item = any>(service: string): void => { hooks[service] = { useItem, useList }; }; -// Products -export interface Product { - _id: string; - name: string; - description: string; - price: number; - quantity: number; - specs: any; - createdAt: string; - updatedAt: string; -} - -// Contractors -export interface Contractor { - _id: string; - name: string; - fullName: string; - vatId: string; - type: string; - debt: number; -} - hooks.account = { useList: () => { const { data: transfers } = useSWR('/transfers', fetcher); diff --git a/src/hooks/useQuery.ts b/src/hooks/useQuery.ts index b2cb628..f025a46 100644 --- a/src/hooks/useQuery.ts +++ b/src/hooks/useQuery.ts @@ -1,6 +1,6 @@ import { useLocation } from 'react-router-dom'; -const useQuery = () => { +const useQuery = (): Record<string, string> => { const location = useLocation(); const searchParams = new URLSearchParams(location.search); return Object.fromEntries(searchParams); diff --git a/src/lib/ServiceContext.tsx b/src/lib/ServiceContext.tsx index 93cac4e..f7170d1 100644 --- a/src/lib/ServiceContext.tsx +++ b/src/lib/ServiceContext.tsx @@ -7,22 +7,22 @@ export interface Action extends ButtonProps { name: string; } -export interface PanelProps { - item: any; - mutate: (item: any) => void; +export interface PanelProps<T> { + item: T; + mutate: (item: T) => void; } -export interface ServiceParams { +export interface ServiceParams<T = any> { route: string; name: string; tableFields: Field[]; nameSingular?: string; - default?: Record<string, any>; + default?: Partial<T>; routes?: Record<string, React.FC>; actions?: Action[]; - rowLink?: (item: any) => string; - Form?: React.FC<FormikProps<any>>; - Panel?: React.FC<PanelProps>; + rowLink?: (item: T) => string; + Form?: React.FC<FormikProps<T>>; + Panel?: React.FC<PanelProps<T>>; } const ServiceContext = React.createContext<ServiceParams>({ diff --git a/src/services/contractors/ContractorPanel.tsx b/src/services/contractors/ContractorPanel.tsx index f7ed8ad..6e703b5 100644 --- a/src/services/contractors/ContractorPanel.tsx +++ b/src/services/contractors/ContractorPanel.tsx @@ -1,9 +1,10 @@ import React from 'react'; import Button from '../../components/Button'; import { PanelProps } from '../../lib/ServiceContext'; +import { Contractor } from '../types'; -const ContractorPanel: React.FC<PanelProps> = ({ item }) => { +const ContractorPanel: React.FC<PanelProps<Contractor>> = ({ item }) => { return ( <div className="lg:m-4 p-4 flex flex-col lg:pl-16 lg:border-l"> <span className="text-lg mb-10"> diff --git a/src/services/contractors/index.ts b/src/services/contractors/index.ts index 2341f3a..9730eff 100644 --- a/src/services/contractors/index.ts +++ b/src/services/contractors/index.ts @@ -1,8 +1,9 @@ import Form from './ContractorForm'; import Panel from './ContractorPanel'; import { ServiceParams } from '../../lib/ServiceContext'; +import { Contractor } from '../types'; -const service: ServiceParams = { +const service: ServiceParams<Contractor> = { route: 'contractors', name: 'Контрагенты', nameSingular: 'Контрагент', diff --git a/src/services/products/index.ts b/src/services/products/index.ts index c869541..8e09eb2 100644 --- a/src/services/products/index.ts +++ b/src/services/products/index.ts @@ -1,7 +1,8 @@ import Form from './ProductForm'; import { ServiceParams } from '../../lib/ServiceContext'; +import { Product } from '../types'; -const service: ServiceParams = { +const service: ServiceParams<Product> = { route: 'products', name: 'Товары', nameSingular: 'Товар', @@ -12,7 +13,7 @@ const service: ServiceParams = { ], default: { name: '', - price: '', + price: 0, quantity: 0, }, Form, diff --git a/src/services/transfers/TransferForm.tsx b/src/services/transfers/TransferForm.tsx index 3502609..92846a3 100644 --- a/src/services/transfers/TransferForm.tsx +++ b/src/services/transfers/TransferForm.tsx @@ -4,12 +4,13 @@ import moment from 'moment'; import Input from '../../components/Input'; import Select from '../../components/Select'; import hooks from '../../hooks/useAPIClient'; +import { Contractor, Transfer } from '../types'; -const mapper = (item: any) => ({ key: item._id, label: item.name }); +const mapper = (item: Contractor) => ({ key: item._id, label: item.name }); -const TransferForm: React.FC<FormikProps<any>> = ({ setFieldValue, values }) => { +const TransferForm: React.FC<FormikProps<Transfer>> = ({ setFieldValue, values }) => { const { data: contractors } = hooks.contractors.useList(); if (!values.date) setFieldValue('date', moment().format('YYYY-MM-DD')); diff --git a/src/services/transfers/TransfersUpload.tsx b/src/services/transfers/TransfersUpload.tsx index c14a5c1..56bcd7e 100644 --- a/src/services/transfers/TransfersUpload.tsx +++ b/src/services/transfers/TransfersUpload.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useRef } from 'react'; import { useHistory } from 'react-router-dom'; import { Form, Formik } from 'formik'; import Input from '../../components/Input'; @@ -8,15 +8,15 @@ import { post } from '../../requests'; const TransfersUpload: React.FC = () => { const history = useHistory(); + const inputRef = useRef<HTMLInputElement>(null); const handleSubmitFile = () => { const reader = new FileReader(); - const element = document.getElementById('file') as HTMLInputElement; - const file = element?.files?.[0]; + const file = inputRef?.current?.files?.[0]; if (file) { reader.readAsDataURL(file); - reader.onload = (e: any) => { - const uri = e.target.result; + reader.onload = (event: ProgressEvent<FileReader>) => { + const uri = event.target?.result; post('/uploads', { uri }).then(history.goBack); }; } @@ -34,7 +34,7 @@ const TransfersUpload: React.FC = () => { > <Formik onSubmit={handleSubmitFile} initialValues={{}}> <Form id="form"> - <Input name="file" type="file" accept=".pdf" label="Прикрепите файл" id="file" /> + <Input name="file" type="file" accept=".pdf" label="Прикрепите файл" ref={inputRef} /> </Form> </Formik> </Page> diff --git a/src/services/transfers/index.ts b/src/services/transfers/index.ts index 37f7b11..1782103 100644 --- a/src/services/transfers/index.ts +++ b/src/services/transfers/index.ts @@ -2,9 +2,10 @@ import Form from './TransferForm'; import UploadPage from './TransfersUpload'; import { transformOperation } from '../transforms'; import { ServiceParams } from '../../lib/ServiceContext'; +import { Transfer } from '../types'; -const service: ServiceParams = { +const service: ServiceParams<Transfer> = { route: 'transfers', name: 'Переводы', nameSingular: 'Перевод', @@ -27,7 +28,6 @@ const service: ServiceParams = { ], default: { operation: 'in', - records: [], }, routes: { upload: UploadPage }, Form, diff --git a/src/services/types.ts b/src/services/types.ts new file mode 100644 index 0000000..e6e01db --- /dev/null +++ b/src/services/types.ts @@ -0,0 +1,40 @@ +interface BaseModel { + _id: string; + createdAt: string; + updatedAt: string; +} + +export interface Contractor extends BaseModel { + name: string; + vatId: string; + debt: number; +} + +export interface Product extends BaseModel { + name: string; + description: string; + price: number; + quantity: number; +} + +export interface Transfer extends BaseModel { + date: string; + operation: 'in' | 'out'; + contractorId: string; + amount: number; + contractor?: Contractor; +} + +export interface Waybill extends BaseModel { + date: string; + operation: 'in' | 'out'; + status: 'waiting' | 'executed' | 'cancelled'; + contractorId: string; + contractor?: Contractor; + records: { + productId: string; + price: number; + quantity: number; + }[]; + total: number; +} diff --git a/src/services/waybills/WaybillForm.tsx b/src/services/waybills/WaybillForm.tsx index c11ab9e..613989f 100644 --- a/src/services/waybills/WaybillForm.tsx +++ b/src/services/waybills/WaybillForm.tsx @@ -7,12 +7,13 @@ import Button from '../../components/Button'; import Select from '../../components/Select'; import Paper from '../../components/Paper'; import hooks from '../../hooks/useAPIClient'; +import { Product, Contractor, Waybill } from '../types'; -const mapper = (item: any) => ({ key: item._id, label: item.name }); +const mapper = (item: Product | Contractor) => ({ key: item._id, label: item.name }); -const WaybillForm: React.FC<FormikProps<any>> = ({ setFieldValue, values }) => { +const WaybillForm: React.FC<FormikProps<Waybill>> = ({ setFieldValue, values }) => { const { data: products } = hooks.products.useList(); const { data: contractors } = hooks.contractors.useList(); @@ -51,7 +52,7 @@ const WaybillForm: React.FC<FormikProps<any>> = ({ setFieldValue, values }) => { /> <Input name="date" type="date" label="Дата" /> </div> - {values.records.map((record: any, index: number) => ( + {values.records.map((record, index) => ( <Paper variant="outlined" className="my-4 md:mx-4" key={`${index}-${record.productId}`}> <Select name={`records.${index}.productId`} diff --git a/src/services/waybills/WaybillPanel.tsx b/src/services/waybills/WaybillPanel.tsx index 1d1701d..c501fc2 100644 --- a/src/services/waybills/WaybillPanel.tsx +++ b/src/services/waybills/WaybillPanel.tsx @@ -3,12 +3,13 @@ import { useHistory } from 'react-router-dom'; import Button from '../../components/Button'; import { patch, baseURL } from '../../requests'; import { PanelProps } from '../../lib/ServiceContext'; +import { Waybill } from '../types'; -const WaybillPanel: React.FC<PanelProps> = ({ item, mutate }) => { +const WaybillPanel: React.FC<PanelProps<Waybill>> = ({ item, mutate }) => { const history = useHistory(); - const handleChangeStatus = (status: any) => patch(`/waybills/${item._id}`, { status }) + const handleChangeStatus = (status: Waybill['status']) => patch(`/waybills/${item._id}`, { status }) .then(() => { history.push('/waybills'); mutate({ ...item, status }); diff --git a/src/services/waybills/index.ts b/src/services/waybills/index.ts index 8cd6c0c..a26318b 100644 --- a/src/services/waybills/index.ts +++ b/src/services/waybills/index.ts @@ -2,8 +2,9 @@ import Form from './WaybillForm'; import Panel from './WaybillPanel'; import { transformOperation, transformStatus } from '../transforms'; import { ServiceParams } from '../../lib/ServiceContext'; +import { Waybill } from '../types'; -const service: ServiceParams = { +const service: ServiceParams<Waybill> = { route: 'waybills', name: 'Накладные', nameSingular: 'Накладная', |