InputContainer
import React from 'react';
import { uid } from 'react-uid';
import { findNotCompletedInput } from '../../utils/util';
import Input from '../Input';
import PropTypes from 'prop-types';
import { useMouseHover } from '../../hooks/useMouseHover';
const INPUT_TYPE = {
'cardNumber-first': 'text',
'cardNumber-second': 'text',
'cardNumber-third': 'password',
'cardNumber-forth': 'password',
'expirationDate-month': 'text',
'expirationDate-year': 'text',
ownerName: 'text',
securityCode: 'password',
'password-first': 'text',
'password-second': 'text',
};
const INPUT_PLACEHOLDER = {
ownerName: '카드에 표시된 이름과 동일하게 입력하세요.',
};
function InputContainer({
state,
stateName,
dispatch,
inputElementsRef,
validate,
setIsShowVirtualKeyboard,
maxLength,
multiInput,
required,
actionType,
labelTitle,
helpText,
inputSize,
}) {
const [isMouseOver, onMouseOver, onMouseLeave] = useMouseHover();
const onChange = (e, stateKey) => {
const {
target: { value, maxLength },
} = e;
if (validate(value, maxLength)) {
dispatch({ type: actionType, payload: { value, stateKey, stateName, multiInput } });
}
if (value.length === maxLength) {
const key = stateKey ? `${stateName}-${stateKey}` : stateName;
const { current: inputElementsMap } = inputElementsRef;
const {
nextInput: { element },
} = findNotCompletedInput(inputElementsMap, key);
inputElementsMap[key].isComplete = true;
element?.focus();
}
};
return (
<div className="input-container">
<span className="input-title">{labelTitle}</span>
<div className={`input-box ${inputSize}`}>
{multiInput ? (
Object.keys(state).map(stateKey => (
<Input
key={uid(stateKey)}
className="input-basic"
type={INPUT_TYPE[`${stateName}-${stateKey}`]}
value={state[stateKey]}
onChange={e => onChange(e, stateKey)}
required={required}
maxLength={maxLength}
elementKey={`${stateName}-${stateKey}`}
inputElementsRef={inputElementsRef}
setIsShowVirtualKeyboard={setIsShowVirtualKeyboard}
/>
))
) : (
<Input
className="input-basic"
type={INPUT_TYPE[stateName]}
value={state}
onChange={onChange}
required={required}
maxLength={maxLength}
placeholder={INPUT_PLACEHOLDER[stateName]}
elementKey={stateName}
inputElementsRef={inputElementsRef}
setIsShowVirtualKeyboard={setIsShowVirtualKeyboard}
/>
)}
{helpText && (
<div className="help-content" onMouseOver={onMouseOver} onMouseLeave={onMouseLeave}>
?
</div>
)}
{isMouseOver && <div className="help-content-text">{helpText}</div>}
</div>
</div>
);
}
InputContainer.propTypes = {
state: PropTypes.any,
stateName: PropTypes.any,
dispatch: PropTypes.any,
labelTitle: PropTypes.any,
inputElementsRef: PropTypes.any,
validate: PropTypes.any,
setIsShowVirtualKeyboard: PropTypes.any,
maxLength: PropTypes.number,
inputSize: PropTypes.string,
helpText: PropTypes.any,
multiInput: PropTypes.any,
required: PropTypes.bool,
actionType: PropTypes.string,
};
export default InputContainer;
(변경되는 값으로 바뀌는 경우 여기서 삭제하고 상태화해야함.. 불편)
import { isAlphabetOrSpace } from '../../utils/validations';
import { isNumberInRange } from '../InputForm/validation';
export const TYPE_INPUT_INFORMATION = {
CARD_NUMBER: {
multiInput: true,
stateName: 'cardNumber',
labelTitle: '카드번호',
validate: isNumberInRange,
maxLength: 4,
required: true,
actionType: 'CHANGE_NUMBER_INPUT',
},
EXPIRATION_DATE: {
multiInput: true,
stateName: 'expirationDate',
labelTitle: '만료일 (01~12의 월 / 년도)',
validate: isNumberInRange,
maxLength: 2,
required: true,
actionType: 'CHANGE_NUMBER_INPUT',
inputSize: 'w-50',
},
OWNER_NAME: {
multiInput: false,
stateName: 'ownerName',
labelTitle: '카드 소유자 이름(선택) (영문만 입력가능)',
validate: isAlphabetOrSpace,
maxLength: 30,
required: false,
actionType: 'CHANGE_UPPER_TEXT_INPUT',
},
SECURITY_CODE: {
multiInput: false,
stateName: 'securityCode',
labelTitle: '보안코드(CVC/CVV)',
validate: isNumberInRange,
maxLength: 3,
required: true,
actionType: 'CHANGE_NUMBER_INPUT',
inputSize: 'w-25',
helpText: '카드 뒷면 서명란 또는 신용카드 번호 오른쪽 상단에 기재된 3자리 숫자',
},
PASSWORD: {
multiInput: true,
stateName: 'password',
labelTitle: '카드 비밀번호',
validate: isNumberInRange,
maxLength: 1,
required: true,
actionType: 'CHANGE_NUMBER_INPUT',
inputSize: 'w-50',
},
};
case 'CHANGE_NUMBER_INPUT': {
const { stateKey, value, stateName, multiInput } = payload;
return {
...state,
[stateName]: multiInput ? { ...state[stateName], [`${stateKey}`]: value } : value,
};
}
case 'CHANGE_UPPER_TEXT_INPUT': {
const { stateKey, value, stateName, multiInput } = payload;
return {
...state,
[stateName]: multiInput
? { ...state[stateName], [`${stateKey}`]: value.toUpperCase() }
: value.toUpperCase(),
};
}