From d2193fdac092b6356d7a64f41efb90697ba2407c Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Tue, 13 Aug 2024 23:55:53 +0200 Subject: [PATCH] fix: autofill the quick created customer/vendor --- .../components/Customers/CustomersSelect.tsx | 14 ++- .../src/components/Vendors/VendorsSelect.tsx | 17 +++- .../CustomerForm/CustomerFormFormik.tsx | 7 +- .../QuickCreateCustomerDrawerContent.tsx | 11 ++- .../QuickCustomerFormDrawer.tsx | 20 +++- .../QuickCreateCustomerDrawer/index.tsx | 12 ++- .../QuickVendorFormDrawer.tsx | 14 ++- .../QuickWriteVendorDrawerContent.tsx | 4 +- .../Drawers/QuickWriteVendorDrawer/index.tsx | 5 +- .../Vendors/VendorForm/VendorFormFormik.tsx | 10 +- packages/webapp/src/hooks/state/autofill.ts | 94 +++++++++++++++++++ .../src/store/dashboard/dashboard.actions.tsx | 20 ++++ .../src/store/dashboard/dashboard.reducer.tsx | 16 +++- .../src/store/dashboard/dashboard.types.tsx | 3 + 14 files changed, 212 insertions(+), 35 deletions(-) create mode 100644 packages/webapp/src/hooks/state/autofill.ts diff --git a/packages/webapp/src/components/Customers/CustomersSelect.tsx b/packages/webapp/src/components/Customers/CustomersSelect.tsx index 067011792..3dde07f3e 100644 --- a/packages/webapp/src/components/Customers/CustomersSelect.tsx +++ b/packages/webapp/src/components/Customers/CustomersSelect.tsx @@ -1,9 +1,11 @@ // @ts-nocheck import React from 'react'; import * as R from 'ramda'; +import { useFormikContext } from 'formik'; import { createNewItemFromQuery, createNewItemRenderer } from './utils'; import { FSelect } from '../Forms'; import withDrawerActions from '@/containers/Drawer/withDrawerActions'; +import { useCreateAutofillListener } from '@/hooks/state/autofill'; import { DRAWERS } from '@/constants/drawers'; /** @@ -17,6 +19,7 @@ function CustomerSelectRoot({ // #ownProps items, allowCreate, + name, ...props }) { // Maybe inject create new item props to suggest component. @@ -24,14 +27,21 @@ function CustomerSelectRoot({ const maybeCreateNewItemFromQuery = allowCreate ? createNewItemFromQuery : null; + const { setFieldValue } = useFormikContext(); + // Creates autofill listener once the quick customer drawer submit the form. + const autofillRef = useCreateAutofillListener((payload: any) => { + setFieldValue(name, payload.customerId); + }); // Handles the create item click. - const handleCreateItemClick = () => { - openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER); + const handleCreateItemClick = (item) => { + const displayName = item.name; + openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER, { autofillRef, displayName }); }; return ( { + setFieldValue(name, payload.vendorId); + }); // Handles the create item click. - const handleCreateItemClick = () => { - openDrawer(DRAWERS.QUICK_WRITE_VENDOR); + const handleCreateItemClick = (item) => { + openDrawer(DRAWERS.QUICK_WRITE_VENDOR, { + autofillRef, + displayName: item.name, + }); }; return ( { + const onSuccess = (res) => { AppToaster.show({ message: intl.get( isNewMode @@ -73,8 +73,7 @@ function CustomerFormFormik({ }); setSubmitting(false); resetForm(); - - saveInvoke(onSubmitSuccess, values, formArgs, submitPayload); + saveInvoke(onSubmitSuccess, values, formArgs, submitPayload, res.data); }; const onError = () => { diff --git a/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/QuickCreateCustomerDrawerContent.tsx b/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/QuickCreateCustomerDrawerContent.tsx index 630683236..a9fb80b30 100644 --- a/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/QuickCreateCustomerDrawerContent.tsx +++ b/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/QuickCreateCustomerDrawerContent.tsx @@ -5,14 +5,16 @@ import { DrawerBody, FormattedMessage as T, } from '@/components'; - import QuickCustomerFormDrawer from './QuickCustomerFormDrawer'; import { DRAWERS } from '@/constants/drawers'; /** * Quick create/edit customer drawer. */ -export default function QuickCreateCustomerDrawerContent({ displayName }) { +export default function QuickCreateCustomerDrawerContent({ + displayName, + autofillRef, +}) { return ( } /> - + ); diff --git a/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/QuickCustomerFormDrawer.tsx b/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/QuickCustomerFormDrawer.tsx index ca1a6a2d4..856ae9df3 100644 --- a/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/QuickCustomerFormDrawer.tsx +++ b/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/QuickCustomerFormDrawer.tsx @@ -14,6 +14,7 @@ import CustomerFormFormik, { import withDrawerActions from '@/containers/Drawer/withDrawerActions'; import { DRAWERS } from '@/constants/drawers'; +import { useAddAutofillRef } from '@/hooks/state/autofill'; /** * Drawer customer form loading wrapper. @@ -28,9 +29,22 @@ function DrawerCustomerFormLoading({ children }) { /** * Quick customer form of the drawer. */ -function QuickCustomerFormDrawer({ displayName, closeDrawer, customerId }) { +function QuickCustomerFormDrawer({ + displayName, + autofillRef, + closeDrawer, + customerId, +}) { + const addAutofillRef = useAddAutofillRef(); + // Handle the form submit request success. - const handleSubmitSuccess = () => { + const handleSubmitSuccess = (values, formArgs, submitPayload, res) => { + if (autofillRef) { + addAutofillRef(autofillRef, { + displayName: values.display_name, + customerId: res.id, + }); + } closeDrawer(DRAWERS.QUICK_CREATE_CUSTOMER); }; // Handle the form cancel action. @@ -43,7 +57,7 @@ function QuickCustomerFormDrawer({ displayName, closeDrawer, customerId }) { diff --git a/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/index.tsx b/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/index.tsx index f172cca85..1e851023e 100644 --- a/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/index.tsx +++ b/packages/webapp/src/containers/Drawers/QuickCreateCustomerDrawer/index.tsx @@ -2,11 +2,10 @@ import React from 'react'; import { Drawer, DrawerSuspense } from '@/components'; import withDrawers from '@/containers/Drawer/withDrawers'; - import { compose } from '@/utils'; -const QuickCreateCustomerDrawerContent = React.lazy(() => - import('./QuickCreateCustomerDrawerContent'), +const QuickCreateCustomerDrawerContent = React.lazy( + () => import('./QuickCreateCustomerDrawerContent'), ); /** @@ -17,7 +16,7 @@ function QuickCreateCustomerDrawer({ // #withDrawer isOpen, - payload, + payload: { autofillRef, displayName }, }) { return ( - + ); diff --git a/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/QuickVendorFormDrawer.tsx b/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/QuickVendorFormDrawer.tsx index c5f6149b7..de91183db 100644 --- a/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/QuickVendorFormDrawer.tsx +++ b/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/QuickVendorFormDrawer.tsx @@ -16,6 +16,7 @@ import withDrawerActions from '@/containers/Drawer/withDrawerActions'; import withDashboardActions from '@/containers/Dashboard/withDashboardActions'; import { useDrawerContext } from '@/components/Drawer/DrawerProvider'; +import { useAddAutofillRef } from '@/hooks/state/autofill'; import { DRAWERS } from '@/constants/drawers'; /** @@ -36,17 +37,20 @@ function QuickVendorFormDrawer({ closeDrawer, vendorId, addQuickActionEvent, + autofillRef, }) { const { payload } = useDrawerContext(); + const addAutofillRef = useAddAutofillRef(); // Handle the form submit request success. - const handleSubmitSuccess = (values, form, submitPayload, response) => { + const handleSubmitSuccess = (values, form, submitPayload, res) => { if (!submitPayload.noRedirect) { closeDrawer(DRAWERS.QUICK_WRITE_VENDOR); } - if (payload.quickActionEvent) { - addQuickActionEvent(payload.quickActionEvent, { - vendorId: response.data.id, + if (autofillRef) { + addAutofillRef(autofillRef, { + displayName: values.display_name, + vendorId: res.id, }); } }; @@ -60,7 +64,7 @@ function QuickVendorFormDrawer({ diff --git a/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/QuickWriteVendorDrawerContent.tsx b/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/QuickWriteVendorDrawerContent.tsx index c52676f69..de4e7fe3b 100644 --- a/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/QuickWriteVendorDrawerContent.tsx +++ b/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/QuickWriteVendorDrawerContent.tsx @@ -12,7 +12,7 @@ import { DRAWERS } from '@/constants/drawers'; /** * Quick create/edit vendor drawer. */ -export default function QuickWriteVendorDrawerContent({ displayName }) { +export default function QuickWriteVendorDrawerContent({ displayName, autofillRef }) { return ( - + ); diff --git a/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/index.tsx b/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/index.tsx index 4bad7da75..9ebd19b3d 100644 --- a/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/index.tsx +++ b/packages/webapp/src/containers/Drawers/QuickWriteVendorDrawer/index.tsx @@ -17,7 +17,7 @@ function QuickWriteVendorDrawer({ // #withDrawer isOpen, - payload, + payload: { displayName, autofillRef }, }) { return ( - + ); diff --git a/packages/webapp/src/containers/Vendors/VendorForm/VendorFormFormik.tsx b/packages/webapp/src/containers/Vendors/VendorForm/VendorFormFormik.tsx index b61cac922..4a3c92bc0 100644 --- a/packages/webapp/src/containers/Vendors/VendorForm/VendorFormFormik.tsx +++ b/packages/webapp/src/containers/Vendors/VendorForm/VendorFormFormik.tsx @@ -34,6 +34,7 @@ function VendorFormFormik({ organization: { base_currency }, // #ownProps + initialValues, onSubmitSuccess, onSubmitError, onCancel, @@ -54,14 +55,15 @@ function VendorFormFormik({ /** * Initial values in create and edit mode. */ - const initialValues = useMemo( + const initialFormValues = useMemo( () => ({ ...defaultInitialValues, + ...transformToForm(initialValues, defaultInitialValues), currency_code: base_currency, ...transformToForm(vendor, defaultInitialValues), ...transformToForm(contactDuplicate, defaultInitialValues), }), - [vendor, contactDuplicate, base_currency], + [vendor, contactDuplicate, base_currency, initialValues], ); // Handles the form submit. @@ -84,7 +86,7 @@ function VendorFormFormik({ setSubmitting(false); resetForm(); - safeInvoke(onSubmitSuccess, values, form, submitPayload, response); + safeInvoke(onSubmitSuccess, values, form, submitPayload, response.data); }; const onError = () => { @@ -112,7 +114,7 @@ function VendorFormFormik({ validationSchema={ isNewMode ? CreateVendorFormSchema : EditVendorFormSchema } - initialValues={initialValues} + initialValues={initialFormValues} onSubmit={handleFormSubmit} >
diff --git a/packages/webapp/src/hooks/state/autofill.ts b/packages/webapp/src/hooks/state/autofill.ts new file mode 100644 index 000000000..1c2c3d013 --- /dev/null +++ b/packages/webapp/src/hooks/state/autofill.ts @@ -0,0 +1,94 @@ +// @ts-nocheck +import { useCallback, useEffect, useRef } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { createSelector } from 'reselect'; +import { + addAutofill, + removeAutofill, + resetAutofill, +} from '@/store/dashboard/dashboard.actions'; + +const getAutofillPayload = (state, autofillRef) => { + return typeof state.dashboard.autofill[autofillRef + ''] !== 'undefined' + ? state.dashboard.autofill[autofillRef] + : null; +}; + +const getAutofillPayloadSelectorFactory = () => + createSelector(getAutofillPayload, (payload) => payload); + +/** + * + * @param {number} autofillRef + * @returns {any} + */ +const useGetAutofillPayload = (autofillRef: number) => { + const getAutofillPayloadSelector = getAutofillPayloadSelectorFactory(); + + return useSelector((state) => getAutofillPayloadSelector(state, autofillRef)); +}; + +/** + * + * @returns + */ +export const useAddAutofillRef = () => { + const dispatch = useDispatch(); + + return useCallback( + (autofillRef: number, payload: any) => { + return dispatch(addAutofill(autofillRef, payload)); + }, + [dispatch], + ); +}; + +/** + * + * @returns + */ +export const useRemoveAutofillRef = () => { + const dispatch = useDispatch(); + + return useCallback( + (autofillRef: number) => { + return dispatch(removeAutofill(autofillRef)); + }, + [dispatch], + ); +}; + +/** + * + * @returns + */ +export const useResetAutofillRefs = () => { + const dispatch = useDispatch(); + + return () => { + return dispatch(resetAutofill()); + }; +}; + +/** + * + * @param {(payload: any, ref: number) => void} callback + * @returns {number} + */ +export const useCreateAutofillListener = ( + callback: (payload: any, ref: number) => void, +): number => { + const ref = useRef(Date.now()); + const autofillPayload = useGetAutofillPayload(ref.current); + const removeAutofill = useRemoveAutofillRef(); + + useEffect(() => { + if (autofillPayload) { + callback(autofillPayload, ref.current); + removeAutofill(ref.current); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [autofillPayload, removeAutofill]); + + return ref.current; +}; diff --git a/packages/webapp/src/store/dashboard/dashboard.actions.tsx b/packages/webapp/src/store/dashboard/dashboard.actions.tsx index f4e329d71..b956955dd 100644 --- a/packages/webapp/src/store/dashboard/dashboard.actions.tsx +++ b/packages/webapp/src/store/dashboard/dashboard.actions.tsx @@ -125,3 +125,23 @@ export function closeSidebarSubmenu() { type: t.SIDEBAR_SUBMENU_CLOSE, }; } + +export function addAutofill(autofillRef: number, payload: any) { + return { + type: t.ADD_AUTOFILL_REF, + payload: { ref: autofillRef, payload } + } +} + +export function removeAutofill(autofillRef: number) { + return { + type: t.REMOVE_AUTOFILL_REF, + payload: { ref: autofillRef} + } +} + +export function resetAutofill() { + return { + type: t.RESET_AUTOFILL_REF, + } +} \ No newline at end of file diff --git a/packages/webapp/src/store/dashboard/dashboard.reducer.tsx b/packages/webapp/src/store/dashboard/dashboard.reducer.tsx index 59f1bb779..eacbbba7b 100644 --- a/packages/webapp/src/store/dashboard/dashboard.reducer.tsx +++ b/packages/webapp/src/store/dashboard/dashboard.reducer.tsx @@ -1,11 +1,10 @@ // @ts-nocheck import { createReducer } from '@reduxjs/toolkit'; -import { isUndefined, isNumber } from 'lodash'; +import { isUndefined, isNumber, omit } from 'lodash'; import t from '@/store/types'; import { persistReducer, purgeStoredState } from 'redux-persist'; import storage from 'redux-persist/lib/storage'; - const initialState = { pageTitle: '', pageSubtitle: '', @@ -23,6 +22,7 @@ const initialState = { appIntlIsLoading: true, sidebarSubmenu: { isOpen: false, submenuId: null }, features: {}, + autofill: {}, }; const STORAGE_KEY = 'bigcapital:dashboard'; @@ -143,6 +143,18 @@ const reducerInstance = createReducer(initialState, { [t.RESET]: () => { purgeStoredState(CONFIG); }, + + [t.ADD_AUTOFILL_REF]: (state, action) => { + state.autofill[action.payload.ref] = action.payload.payload || null; + }, + + [t.REMOVE_AUTOFILL_REF]: (state, action) => { + state.autofill = omit(state.autofill, [action.payload.ref]); + }, + + [t.RESET_AUTOFILL_REF]: (state, action) => { + state.autofill = {}; + }, }); export default persistReducer(CONFIG, reducerInstance); diff --git a/packages/webapp/src/store/dashboard/dashboard.types.tsx b/packages/webapp/src/store/dashboard/dashboard.types.tsx index bf6aa9f4e..4a04e8c3b 100644 --- a/packages/webapp/src/store/dashboard/dashboard.types.tsx +++ b/packages/webapp/src/store/dashboard/dashboard.types.tsx @@ -21,4 +21,7 @@ export default { SPLASH_START_LOADING: 'SPLASH_START_LOADING', SPLASH_STOP_LOADING: 'SPLASH_STOP_LOADING', SET_FEATURE_DASHBOARD_META: 'SET_FEATURE_DASHBOARD_META', + ADD_AUTOFILL_REF: 'ADD_AUTOFILL_REF', + REMOVE_AUTOFILL_REF: 'REMOVE_AUTOFILL_REF', + RESET_AUTOFILL_REF: 'RESET_AUTOFILL_REF' };