Skip to content

Commit

Permalink
feat: 계좌번호 입력 제한 추가 (#634)
Browse files Browse the repository at this point in the history
* feat: 계좌번호 입력 유효성 기능 추가

* feat: 계좌번호 유효성을 검증하고 input을 컨트롤하는 기능 추가

* style: console.log 제거

* feat: 계좌번호 정규표현식 수정

---------

Co-authored-by: Soyeon Choe <[email protected]>
  • Loading branch information
jinhokim98 and soi-ha authored Sep 26, 2024
1 parent dff7f4f commit 19b91a5
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 10 deletions.
1 change: 1 addition & 0 deletions client/src/constants/errorMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const ERROR_MESSAGE = {
preventEmpty: '값은 비어있을 수 없어요',
invalidInput: '올바르지 않은 입력이에요.',
emptyBank: '계좌번호가 입력되지 않아서\n토스 송금 기능을 사용할 수 없어요',
invalidAccountNumber: '계좌번호는 8자에서 30자 사이로 입력 가능해요',
};

export const UNKNOWN_ERROR = 'UNKNOWN_ERROR';
1 change: 1 addition & 0 deletions client/src/constants/regExp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const REGEXP = {
eventUrl: /\/event\/([a-zA-Z0-9-]+)\//,
billTitle: /^([ㄱ-ㅎ가-힣a-zA-Z0-9ㆍᆢ]\s?)*$/,
memberName: /^([ㄱ-ㅎ가-힣a-zA-Zㆍᆢ]\s?)*$/,
accountNumber: /^\d+([\s\-]\d+)*[\s\-]?$/,
};

export default REGEXP;
2 changes: 2 additions & 0 deletions client/src/constants/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const RULE = {
maxEventPasswordLength: 4,
maxMemberNameLength: 4,
maxPrice: 10000000,
minAccountNumberLength: 8,
maxAccountNumberLength: 30,
};

export default RULE;
42 changes: 37 additions & 5 deletions client/src/hooks/useAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ import type {Event} from 'types/serviceType';

import {useEffect, useState} from 'react';

import validateAccountNumber from '@utils/validate/validateAccountNumber';

import RULE from '@constants/rule';

import useRequestPatchEvent from './queries/event/useRequestPatchEvent';
import useRequestGetEvent from './queries/event/useRequestGetEvent';

const useAccount = () => {
const {bankName, accountNumber} = useRequestGetEvent();

const [bankNameState, setBankName] = useState(bankName);
const [accountNumberState, setAccountNumber] = useState(accountNumber);
const [accountNumberErrorMessage, setAccountNumberErrorMessage] = useState<string | null>(null);
const [canSubmit, setCanSubmit] = useState(false);
const [isPasting, setIsPasting] = useState(false);

useEffect(() => {
setBankName(bankName);
Expand All @@ -24,7 +29,32 @@ const useAccount = () => {
};

const handleAccount = (event: React.ChangeEvent<HTMLInputElement>) => {
setAccountNumber(event.target.value);
if (isPasting) return;

const newValue = event.target.value;
const {isValid, errorMessage} = validateAccountNumber(newValue);
setAccountNumberErrorMessage(errorMessage);

const isValidMinLength = newValue.length >= RULE.minAccountNumberLength;

if (isValid) {
setAccountNumber(event.target.value);
} else if (!isValid && !isValidMinLength) {
setAccountNumber(event.target.value.replace(/[^0-9\s\-]/g, '').trim());
}
};

const handleAccountOnPaste = (event: React.ClipboardEvent<HTMLInputElement>) => {
setIsPasting(true);

const value = `${accountNumberState}${event.clipboardData.getData('text')}`;
const newValue = value.replace(/[^0-9\s\-]/g, '').trim();
const {isValid, errorMessage} = validateAccountNumber(newValue);

setAccountNumberErrorMessage(errorMessage);
if (isValid) setAccountNumber(newValue);

setTimeout(() => setIsPasting(false), 0);
};

const getChangedField = () => {
Expand All @@ -49,15 +79,17 @@ const useAccount = () => {
const existEmptyField = bankNameState.trim() === '' || accountNumberState.trim() === '';
const isChanged = bankName !== bankNameState || accountNumber !== accountNumberState;

setCanSubmit(!existEmptyField && isChanged);
}, [bankNameState, accountNumberState]);

setCanSubmit(!existEmptyField && isChanged && accountNumberErrorMessage === null);
}, [bankName, accountNumber, bankNameState, accountNumberState, accountNumberErrorMessage]);
return {
bankName: bankNameState,
accountNumber: accountNumberState,
accountNumberErrorMessage,
canSubmit,
selectBank,
handleAccount,
handleAccountOnPaste,
enrollAccount,
};
};
Expand Down
19 changes: 14 additions & 5 deletions client/src/pages/AccountPage/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ const Account = () => {

const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false);

const {bankName, accountNumber, canSubmit, selectBank, handleAccount, enrollAccount} = useAccount();
const {
bankName,
accountNumber,
accountNumberErrorMessage,
canSubmit,
selectBank,
handleAccount,
handleAccountOnPaste,
enrollAccount,
} = useAccount();

const enrollAccountAndNavigateAdmin = async () => {
await enrollAccount();
Expand All @@ -40,19 +49,19 @@ const Account = () => {
errorText={null}
autoFocus={false}
isAlwaysOnLabel
isAlwaysOnInputBorder
readOnly
onClick={() => setIsBottomSheetOpen(true)}
/>
<LabelInput
labelText="계좌번호"
placeholder="030302-04-191806"
errorText={null}
placeholder="ex) 030302-04-191806"
errorText={accountNumberErrorMessage}
isError={accountNumberErrorMessage !== null}
value={accountNumber ?? ''}
onChange={handleAccount}
onPaste={handleAccountOnPaste}
autoFocus={false}
isAlwaysOnLabel
isAlwaysOnInputBorder
/>
{isBottomSheetOpen && (
<BankSelectModal
Expand Down
23 changes: 23 additions & 0 deletions client/src/utils/validate/validateAccountNumber.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {ERROR_MESSAGE} from '@constants/errorMessage';
import REGEXP from '@constants/regExp';
import RULE from '@constants/rule';

import {ValidateResult} from './type';

const validateAccountNumber = (accountNumber: string): ValidateResult => {
const isValidateType = () => {
return REGEXP.accountNumber.test(accountNumber);
};

const isValidateLength = () => {
return accountNumber.length >= RULE.minAccountNumberLength && accountNumber.length <= RULE.maxAccountNumberLength;
};

if (isValidateType() && isValidateLength()) {
return {isValid: true, errorMessage: null};
}

return {isValid: false, errorMessage: ERROR_MESSAGE.invalidAccountNumber};
};

export default validateAccountNumber;

0 comments on commit 19b91a5

Please sign in to comment.