From 887b47a55aa945fde3c2d6b07491a9821c856fb4 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 4 Jun 2024 14:46:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=90=9C=E7=B4=A2=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SearchForm.jsx | 225 +++++++++++++++++++++++++++++++ src/stores/Form.js | 12 ++ src/utils/commons.js | 2 +- src/views/reservation/Newest.jsx | 19 ++- 4 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 src/components/SearchForm.jsx create mode 100644 src/stores/Form.js diff --git a/src/components/SearchForm.jsx b/src/components/SearchForm.jsx new file mode 100644 index 0000000..d4b5e05 --- /dev/null +++ b/src/components/SearchForm.jsx @@ -0,0 +1,225 @@ +import { createContext, useContext, useEffect, useState } from 'react'; +import { Form, Input, Row, Col, Select, DatePicker, Space, Button } from 'antd'; +import { objectMapper, at, isEmpty } from '@/utils/commons'; +import { DATE_FORMAT } from '@/config'; +import useFormStore from '@/stores/Form'; +import usePresets from '@/hooks/usePresets'; +import { useTranslation } from 'react-i18next'; + +const { RangePicker } = DatePicker; + +const SearchForm = ({ initialValue, onSubmit, onReset, ...props }) => { + const { t } = useTranslation(); + const presets = usePresets(); + const [formValues, setFormValues] = useFormStore((state) => [state.formValues, state.setFormValues]); + const [formValuesToSub, setFormValuesToSub] = useFormStore((state) => [state.formValuesToSub, state.setFormValuesToSub]); + const [form] = Form.useForm(); + const { sort, hides, shows, fieldProps } = { + sort: '', + // initialValue: '', + fieldProps: '', + hides: [], + shows: [], + ...props.defaultValue, + }; + const { confirmText } = props; + const readValues = { ...initialValue, ...formValues }; + + const formValuesMapper = (values) => { + const destinationObject = { + 'referenceNo': { key: 'referenceNo' }, + 'dates': [ + { key: 'startdate', transform: (arrVal) => (arrVal ? arrVal[0].format(DATE_FORMAT) : '') }, + { key: 'enddate', transform: (arrVal) => (arrVal ? arrVal[1].format(DATE_FORMAT) : '') }, + ], + 'invoiceStatus': { key: 'invoiceStatus', transform: (value) => value?.value || value?.key || '', default: '' }, + }; + let dest = {}; + const { dates, ...omittedValue } = values; + dest = { ...omittedValue, ...objectMapper(values, destinationObject) }; + for (const key in dest) { + if (Object.prototype.hasOwnProperty.call(dest, key)) { + dest[key] = typeof dest[key] === 'string' ? (dest[key] || '').trim() : dest[key]; + } + } + // omit empty + Object.keys(dest).forEach((key) => (dest[key] == null || dest[key] === '' || dest[key].length === 0) && delete dest[key]); + return dest; + }; + + useEffect(() => { + const dest = formValuesMapper(formValues); + setFormValuesToSub(dest); + return () => {}; + }, []); + + const onFinish = (values) => { + console.log('Received values of form, origin form value: ', values); + const dest = formValuesMapper(values); + console.log('form value send to onSubmit:', dest); + const str = new URLSearchParams(dest).toString(); + setFormValues(values); + setFormValuesToSub(dest); + if (typeof onSubmit === 'function') { + onSubmit(null, dest, values, str); + } + }; + + const handleReset = () => { + form.setFieldsValue({ + // 'DateType': undefined, + }); + if (typeof onReset === 'function') { + onReset(); + } + }; + const onValuesChange = (changedValues, allValues) => { + + const dest = formValuesMapper(allValues); + setFormValues(allValues); + setFormValuesToSub(dest); + // console.log('form onValuesChange', Object.keys(changedValues), args); + }; + return ( + <> +
+ {/* */} + + {getFields({ sort, initialValue: readValues, hides, shows, fieldProps, form, presets, t })} + {/* 'textAlign': 'right' */} + + + + {/* */} + + + + {/* */} +
+ + ); +}; + +function getFields(props) { + const { fieldProps, form, presets, t } = props; + const bigCol = 4 * 2; + const midCol = 6; + const layoutProps = { + // gutter: { xs: 8, sm: 8, lg: 16 }, + lg: { span: 4 }, + md: { span: 8 }, + sm: { span: 12 }, + xs: { span: 24 }, + }; + const item = (name, sort = 0, render, col) => { + const customCol = col || 4; + const mdCol = customCol * 2; + return { + 'key': '', + sort, + name, + render, + 'hide': false, + 'col': { lg: { span: customCol }, md: { span: mdCol < 8 ? 10 : mdCol }, flex: mdCol < 8 ? '1 0' : '' }, + }; + }; + let baseChildren = []; + baseChildren = [ + item( + 'referenceNo', + 99, + + + ,4 + ), + item( + 'invoiceStatus', + 99, + + + , + 3 + ), + item( + 'dates', + 99, + + {/* */} + { + // reservationStore.updatePropertyValue('arrivalDateRange', dateRange == null ? [] : dateRange) + // }} + /> + , + fieldProps?.dates?.col || midCol + ), + ]; + baseChildren = baseChildren + .map((x) => { + x.hide = false; + if (props.sort === undefined) { + return x; + } + const tmpSort = props.sort; + for (const key in tmpSort) { + if (Object.prototype.hasOwnProperty.call(tmpSort, key)) { + if (x.name === key) { + x.sort = tmpSort[key]; + } + } + } + return x; + }) + .map((x) => { + if (props.hides.length === 0 && props.shows.length === 0) { + return x; + } + if (props.hides.length === 0) { + x.hide = !props.shows.includes(x.name); + } else if (props.shows.length === 0) { + x.hide = props.hides.includes(x.name); + } + return x; + }) + .filter((x) => !x.hide) + .sort((a, b) => { + return a.sort < b.sort ? -1 : 1; + }); + const children = []; + const leftStyle = {}; // { borderRight: '1px solid #dedede' }; + for (let i = 0; i < baseChildren.length; i++) { + let style = {}; // { padding: '0px 2px' }; + style = i % 2 === 0 && baseChildren[i].col === 12 ? { ...style, ...leftStyle } : style; + style = !baseChildren[i].hide ? { ...style, display: 'block' } : { ...style, display: 'none' }; + const Item = ( + + {baseChildren[i].render} + + ); + children.push(Item); + } + return children; +} + +export default SearchForm; diff --git a/src/stores/Form.js b/src/stores/Form.js new file mode 100644 index 0000000..61a30f8 --- /dev/null +++ b/src/stores/Form.js @@ -0,0 +1,12 @@ +import { create } from 'zustand'; +import { devtools } from 'zustand/middleware'; + +export const useFormStore = create( + devtools((set, get) => ({ + formValues: {}, + setFormValues: (values) => set((state) => ({ formValues: { ...state.formValues, ...values } })), + formValuesToSub: {}, + setFormValuesToSub: (values) => set((state) => ({ formValuesToSub: { ...state.formValuesToSub, ...values } })), + })) +); +export default useFormStore; diff --git a/src/utils/commons.js b/src/utils/commons.js index 9b178ee..c5508ca 100644 --- a/src/utils/commons.js +++ b/src/utils/commons.js @@ -340,7 +340,7 @@ export function objectMapper(input, keyMap) { if (map) { let value = input[key]; if (map.transform) value = map.transform(value); - mappedObj[map.key || key] = value; + mappedObj[map.key || map] = value; } } }); diff --git a/src/views/reservation/Newest.jsx b/src/views/reservation/Newest.jsx index c2203c5..472b6b6 100644 --- a/src/views/reservation/Newest.jsx +++ b/src/views/reservation/Newest.jsx @@ -5,11 +5,12 @@ import { toJS } from "mobx"; import { Row, Col, Space, Button, Table, Input, Typography, DatePicker, Modal, App, Select } from 'antd'; import dayjs from "dayjs"; import { useStore } from '@/stores/StoreContext.js'; -import { isEmpty } from "@/utils/commons"; +import { isEmpty, objectMapper } from "@/utils/commons"; import { useTranslation } from 'react-i18next'; import usePresets from '@/hooks/usePresets'; import useAuthStore from '@/stores/Auth' import useReservationStore from '@/stores/Reservation' +import SearchForm from '@/components/SearchForm'; const { Title } = Typography; @@ -218,6 +219,22 @@ function Newest() { + { + const _ff = objectMapper(formVal, { startdate: 'DateStart', enddate: 'DateEnd', referenceNo: 'GroupNo' }) + console.log('from form', formVal, 'mappered for search', _ff); + }} + /> { reservationStore.updatePropertyValue('referenceNo', e.target.value)} } />