diff --git a/striker-ui/components/GeneralInitForm.tsx b/striker-ui/components/GeneralInitForm.tsx index 47432198..f2c087a5 100644 --- a/striker-ui/components/GeneralInitForm.tsx +++ b/striker-ui/components/GeneralInitForm.tsx @@ -1,15 +1,9 @@ import { Box as MUIBox } from '@mui/material'; -import { - forwardRef, - ForwardRefExoticComponent, - RefAttributes, - useImperativeHandle, - useState, -} from 'react'; +import { forwardRef, useImperativeHandle, useRef } from 'react'; import createFunction from '../lib/createFunction'; -import createInputOnChangeHandler from '../lib/createInputOnChangeHandler'; import FlexBox from './FlexBox'; +import InputWithRef, { InputForwardedRefContent } from './InputWithRef'; import isEmpty from '../lib/isEmpty'; import OutlinedInputWithLabel from './OutlinedInputWithLabel'; import pad from '../lib/pad'; @@ -30,7 +24,7 @@ const MAP_TO_ORGANIZATION_PREFIX_BUILDER: Record< words.map((word) => word.substring(0, 1).toLocaleLowerCase()).join(''), }; -const buildOrganizationPrefix = (organizationName: string) => { +const buildOrganizationPrefix = (organizationName = '') => { const words: string[] = organizationName .split(/\s/) .filter((word) => !/and|of/.test(word)) @@ -41,238 +35,254 @@ const buildOrganizationPrefix = (organizationName: string) => { return MAP_TO_ORGANIZATION_PREFIX_BUILDER[builderKey](words); }; -const buildHostName = ( - organizationPrefix: string, - hostNumber: number, - domainName: string, -) => +const buildHostName = ({ + organizationPrefix, + hostNumber, + domainName, +}: { + organizationPrefix?: string; + hostNumber?: number; + domainName?: string; +}) => isEmpty([organizationPrefix, hostNumber, domainName], { not: true }) ? `${organizationPrefix}-striker${pad(hostNumber)}.${domainName}` : ''; -const GeneralInitForm: ForwardRefExoticComponent> = - forwardRef((generalInitFormProps, ref) => { - const [organizationNameInput, setOrganizationNameInput] = - useState(''); - const [organizationPrefixInput, setOrganizationPrefixInput] = - useState(''); - const [ - isOrganizationPrefixInputUserChanged, - setIsOrganizationPrefixInputUserChanged, - ] = useState(false); - const [domainNameInput, setDomainNameInput] = useState(''); - const [hostNumberInput, setHostNumberInput] = useState(0); - const [hostNameInput, setHostNameInput] = useState(''); - const [isHostNameInputUserChanged, setIsHostNameInputUserChanged] = - useState(false); +const GeneralInitForm = forwardRef((generalInitFormProps, ref) => { + const organizationNameInputRef = useRef>( + {}, + ); + const organizationPrefixInputRef = useRef>( + {}, + ); + const domainNameInputRef = useRef>({}); + const hostNumberInputRef = useRef>({}); + const hostNameInputRef = useRef>({}); - const handleOrganizationNameInputOnChange = createInputOnChangeHandler({ - set: setOrganizationNameInput, + const { + current: { value: organizationNameInputValue }, + } = organizationNameInputRef; + const { + current: { + isChangedByUser: isOrganizationPrefixInputChangedByUser, + setValue: setOrganizationPrefixInputValue, + value: organizationPrefixInputValue, + }, + } = organizationPrefixInputRef; + const { + current: { value: domainNameInputValue }, + } = domainNameInputRef; + const { + current: { value: hostNumberInputValue }, + } = hostNumberInputRef; + const { + current: { + isChangedByUser: isHostNameInputChangedByUser, + setValue: setHostNameInputValue, + value: hostNameInputValue, + }, + } = hostNameInputRef; + + const populateOrganizationPrefixInput = ({ + organizationName = organizationNameInputValue, + } = {}) => { + const organizationPrefix = buildOrganizationPrefix(organizationName); + + setOrganizationPrefixInputValue?.call(null, organizationPrefix); + + return organizationPrefix; + }; + const populateHostNameInput = ({ + organizationPrefix = organizationPrefixInputValue, + hostNumber = hostNumberInputValue, + domainName = domainNameInputValue, + } = {}) => { + const hostName = buildHostName({ + organizationPrefix, + hostNumber, + domainName, }); - const handleOrganizationPrefixInputOnChange = createInputOnChangeHandler({ - postSet: () => { - setIsOrganizationPrefixInputUserChanged(true); - }, - set: setOrganizationPrefixInput, - }); - const handleDomainNameInputOnChange = createInputOnChangeHandler({ - set: setDomainNameInput, - }); - const handleHostNumberInputOnChange = createInputOnChangeHandler({ - set: setHostNumberInput, - setType: 'number', - }); - const handleHostNameInputOnChange = createInputOnChangeHandler({ - postSet: () => { - setIsHostNameInputUserChanged(true); - }, - set: setHostNameInput, - }); - const populateOrganizationPrefixInput = ({ - organizationName = organizationNameInput, - } = {}) => { - const organizationPrefix = buildOrganizationPrefix(organizationName); - setOrganizationPrefixInput(organizationPrefix); + setHostNameInputValue?.call(null, hostName); - return organizationPrefix; - }; - const populateHostNameInput = ({ - organizationPrefix = organizationPrefixInput, - hostNumber = hostNumberInput, - domainName = domainNameInput, - } = {}) => { - const hostName = buildHostName( - organizationPrefix, - hostNumber, - domainName, - ); + return hostName; + }; + const populateOrganizationPrefixInputOnBlur = createFunction( + { condition: !isOrganizationPrefixInputChangedByUser }, + populateOrganizationPrefixInput, + ); + const populateHostNameInputOnBlur = createFunction( + { condition: !isHostNameInputChangedByUser }, + populateHostNameInput, + ); + const handleOrganizationPrefixSuggest = createFunction( + { + conditionFn: () => + isOrganizationPrefixInputChangedByUser === true && + isEmpty([organizationNameInputValue], { not: true }), + }, + () => { + const organizationPrefix = populateOrganizationPrefixInput(); - setHostNameInput(hostName); - - return hostName; - }; - const populateOrganizationPrefixInputOnBlur = createFunction( - { condition: !isOrganizationPrefixInputUserChanged }, - populateOrganizationPrefixInput, - ); - const populateHostNameInputOnBlur = createFunction( - { condition: !isHostNameInputUserChanged }, - populateHostNameInput, - ); - const handleOrganizationPrefixSuggest = createFunction( - { - conditionFn: () => - isOrganizationPrefixInputUserChanged && - isEmpty([organizationNameInput], { not: true }), - }, - () => { - const organizationPrefix = populateOrganizationPrefixInput(); - - if (!isHostNameInputUserChanged) { - populateHostNameInput({ organizationPrefix }); - } - }, - ); - const handlerHostNameSuggest = createFunction( - { - conditionFn: () => - isHostNameInputUserChanged && - isEmpty([organizationPrefixInput, hostNumberInput, domainNameInput], { + if (!isHostNameInputChangedByUser) { + populateHostNameInput({ organizationPrefix }); + } + }, + ); + const handlerHostNameSuggest = createFunction( + { + conditionFn: () => + isHostNameInputChangedByUser === true && + isEmpty( + [ + organizationPrefixInputValue, + hostNumberInputValue, + domainNameInputValue, + ], + { not: true, - }), - }, - populateHostNameInput, - ); - - useImperativeHandle( - ref, - () => ({ - organizationNameInput, - organizationPrefixInput, - domainNameInput, - hostNumberInput, - hostNameInput, - }), - [ - organizationNameInput, - organizationPrefixInput, - domainNameInput, - hostNumberInput, - hostNameInput, - ], - ); - - return ( - *': { - flexBasis: '50%', }, + ), + }, + populateHostNameInput, + ); - '& > :not(:first-child)': { - marginLeft: { xs: 0, sm: '1em' }, - marginTop: { xs: '1em', sm: 0 }, - }, - }} - > - - - - ), - inputProps: { - maxLength: MAX_ORGANIZATION_PREFIX_LENGTH, - style: { width: '2.5em' }, - }, - onBlur: populateHostNameInputOnBlur, - sx: { - minWidth: 'min-content', - width: 'fit-content', - }, - }} - label="Prefix" - onChange={handleOrganizationPrefixInputOnChange} - value={organizationPrefixInput} - /> - - - - - , - inputProps: { - style: { - minWidth: '4em', + useImperativeHandle(ref, () => ({ + organizationName: organizationNameInputValue, + organizationPrefix: organizationPrefixInputValue, + domainName: domainNameInputValue, + hostNumber: hostNumberInputValue, + hostName: hostNameInputValue, + })); + + return ( + *': { + flexBasis: '50%', + }, + + '& > :not(:first-child)': { + marginLeft: { xs: 0, sm: '1em' }, + marginTop: { xs: '1em', sm: 0 }, + }, + }} + > + + + } + ref={organizationNameInputRef} + /> + + ), + inputProps: { + maxLength: MAX_ORGANIZATION_PREFIX_LENGTH, + style: { width: '2.5em' }, }, - }, - sx: { - minWidth: 'min-content', - }, - }} - label="Host name" - onChange={handleHostNameInputOnChange} - value={hostNameInput} - /> - - - ); - }); + onBlur: populateHostNameInputOnBlur, + sx: { + minWidth: 'min-content', + width: 'fit-content', + }, + }} + label="Prefix" + /> + } + ref={organizationPrefixInputRef} + /> + + + + } + ref={domainNameInputRef} + /> + + } + ref={hostNumberInputRef} + valueType="number" + /> + + ), + inputProps: { + style: { + minWidth: '4em', + }, + }, + sx: { + minWidth: 'min-content', + }, + }} + label="Host name" + /> + } + ref={hostNameInputRef} + /> + + + ); +}); GeneralInitForm.displayName = 'GeneralInitForm';