From 1da83ccaf314690b9ac247e3690b5fecc5c26eab Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Mon, 30 Nov 2020 19:57:23 +0200 Subject: [PATCH] feat: auto-focus first fields. --- .../Customers/CustomerFormPrimarySection.js | 7 +++++-- .../AccountFormDialogContent.js | 4 ++-- .../AccountFormDialog/AccountFormDialogFields.js | 10 ++++++++-- .../ItemCategoryDialog/ItemCategoryForm.js | 10 +++++++++- .../containers/Items/ItemFormPrimarySection.js | 16 ++++++++++++++-- .../Vendors/VendorFormPrimarySection.js | 5 +++++ client/src/hooks/index.js | 6 +++--- client/src/hooks/useAutofocus.js | 13 +++++++++++++ 8 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 client/src/hooks/useAutofocus.js diff --git a/client/src/containers/Customers/CustomerFormPrimarySection.js b/client/src/containers/Customers/CustomerFormPrimarySection.js index 46afad8a1..d29410a23 100644 --- a/client/src/containers/Customers/CustomerFormPrimarySection.js +++ b/client/src/containers/Customers/CustomerFormPrimarySection.js @@ -12,12 +12,14 @@ import { import CustomerTypeRadioField from 'containers/Customers/CustomerTypeRadioField'; import { CLASSES } from 'common/classes'; import { inputIntent } from 'utils'; +import { useAutofocus } from 'hooks'; /** * Customer form primary section. */ -export default function CustomerFormPrimarySection({ -}) { +export default function CustomerFormPrimarySection({}) { + const firstNameFieldRef = useAutofocus(); + return (
{/**-----------Customer type. -----------*/} @@ -54,6 +56,7 @@ export default function CustomerFormPrimarySection({ placeholder={'First Name'} intent={inputIntent({ error, touched })} className={classNames('input-group--first-name')} + inputRef={(ref) => (firstNameFieldRef.current = ref)} {...field} /> )} diff --git a/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogContent.js b/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogContent.js index 310343e1a..c90d5f999 100644 --- a/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogContent.js +++ b/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogContent.js @@ -1,8 +1,8 @@ -import React, { useCallback, useMemo, useEffect } from 'react'; +import React, { useCallback } from 'react'; import { Intent } from '@blueprintjs/core'; import { Formik } from 'formik'; import { FormattedMessage as T, useIntl } from 'react-intl'; -import { pick, omit } from 'lodash'; +import { omit } from 'lodash'; import { useQuery, queryCache } from 'react-query'; import { AppToaster, DialogContent } from 'components'; diff --git a/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogFields.js b/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogFields.js index e4eecc585..68f8b4178 100644 --- a/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogFields.js +++ b/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogFields.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { Form, FastField, Field, ErrorMessage, useFormikContext } from 'formik'; import classNames from 'classnames'; import { FormattedMessage as T } from 'react-intl'; @@ -22,6 +22,7 @@ import withAccounts from 'containers/Accounts/withAccounts'; import { inputIntent } from 'utils'; import { compose } from 'redux'; +import { useAutofocus } from 'hooks'; /** * Account form dialogs fields. @@ -36,6 +37,7 @@ function AccountFormDialogFields({ accountsTypes, }) { const { values, isSubmitting } = useFormikContext(); + const accountNameFieldRef = useAutofocus(); return (
@@ -75,7 +77,11 @@ function AccountFormDialogFields({ helperText={} inline={true} > - + (accountNameFieldRef.current = ref)} + {...field} + /> )} diff --git a/client/src/containers/Dialogs/ItemCategoryDialog/ItemCategoryForm.js b/client/src/containers/Dialogs/ItemCategoryDialog/ItemCategoryForm.js index 09dad964b..a55fbf414 100644 --- a/client/src/containers/Dialogs/ItemCategoryDialog/ItemCategoryForm.js +++ b/client/src/containers/Dialogs/ItemCategoryDialog/ItemCategoryForm.js @@ -19,6 +19,8 @@ import { } from 'components'; import { inputIntent } from 'utils'; +import { useAutofocus } from 'hooks'; + export default function ItemCategoryForm({ itemCategoryId, accountsList, @@ -26,6 +28,8 @@ export default function ItemCategoryForm({ isSubmitting, onClose, }) { + const categoryNameFieldRef = useAutofocus(); + // Filters Item Categories list. const filterItemCategories = useCallback( (query, category, _index, exactMatch) => { @@ -68,7 +72,11 @@ export default function ItemCategoryForm({ helperText={} inline={true} > - + (categoryNameFieldRef.current = ref)} + {...field} + /> )} diff --git a/client/src/containers/Items/ItemFormPrimarySection.js b/client/src/containers/Items/ItemFormPrimarySection.js index d35bcc4fc..441834160 100644 --- a/client/src/containers/Items/ItemFormPrimarySection.js +++ b/client/src/containers/Items/ItemFormPrimarySection.js @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useRef } from 'react'; import { FormGroup, InputGroup, @@ -40,6 +40,14 @@ function ItemFormPrimarySection({ // #ownProps itemType, }) { + const nameFieldRef = useRef(null); + + useEffect(() => { + // Auto focus item name field once component mount. + if (nameFieldRef.current) { + nameFieldRef.current.focus(); + } + }, []); const itemTypeHintContent = ( <> @@ -112,7 +120,11 @@ function ItemFormPrimarySection({ helperText={} inline={true} > - + (nameFieldRef.current = ref)} + /> )} diff --git a/client/src/containers/Vendors/VendorFormPrimarySection.js b/client/src/containers/Vendors/VendorFormPrimarySection.js index e68cd3e34..c1bf1830e 100644 --- a/client/src/containers/Vendors/VendorFormPrimarySection.js +++ b/client/src/containers/Vendors/VendorFormPrimarySection.js @@ -13,10 +13,14 @@ import { import { CLASSES } from 'common/classes'; import { inputIntent } from 'utils'; +import { useAutofocus } from 'hooks'; + /** * Vendor form primary section. */ function VendorFormPrimarySection() { + const firstNameFieldRef = useAutofocus(); + return (
{/**----------- Vendor name -----------*/} @@ -50,6 +54,7 @@ function VendorFormPrimarySection() { placeholder={'First Name'} intent={inputIntent({ error, touched })} className={classNames('input-group--first-name')} + inputRef={(ref) => (firstNameFieldRef.current = ref)} {...field} /> )} diff --git a/client/src/hooks/index.js b/client/src/hooks/index.js index 9f654ad77..66a6c87bf 100644 --- a/client/src/hooks/index.js +++ b/client/src/hooks/index.js @@ -1,5 +1,6 @@ import {useRef, useEffect} from 'react'; import useAsync from './async'; +import useAutofocus from './useAutofocus'; // import use from 'async'; @@ -34,8 +35,7 @@ export function useIsValuePassed(value, compatatorValue) { return cache.current.indexOf(compatatorValue) !== -1; } - -export default { +export { useAsync, - useUpdateEffect, + useAutofocus, } \ No newline at end of file diff --git a/client/src/hooks/useAutofocus.js b/client/src/hooks/useAutofocus.js new file mode 100644 index 000000000..0546956f2 --- /dev/null +++ b/client/src/hooks/useAutofocus.js @@ -0,0 +1,13 @@ +import { useRef, useEffect } from 'react'; + +export default function useAutofocus() { + const ref = useRef(); + + useEffect(() => { + if (ref.current) { + ref.current.focus(); + } + }, [ref]); + + return ref; +}