From 0294b81d32a9790bd28dce91c55dba5b9dee3a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Wed, 25 Sep 2024 17:24:15 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EA=B3=84=EC=A2=8C=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/errorMessage.ts | 1 + client/src/constants/regExp.ts | 1 + client/src/constants/rule.ts | 2 ++ .../utils/validate/validateAccountNumber.ts | 23 +++++++++++++++++++ 4 files changed, 27 insertions(+) create mode 100644 client/src/utils/validate/validateAccountNumber.ts diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index b33c12d5a..af59ee50d 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -45,6 +45,7 @@ export const ERROR_MESSAGE = { preventEmpty: '값은 비어있을 수 없어요', invalidInput: '올바르지 않은 입력이에요.', emptyBank: '계좌번호가 입력되지 않아서\n토스 송금 기능을 사용할 수 없어요', + invalidAccountNumber: '계좌번호는 8자에서 30자 사이로 입력 가능해요', }; export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts index d235c1f11..1903e97a4 100644 --- a/client/src/constants/regExp.ts +++ b/client/src/constants/regExp.ts @@ -3,6 +3,7 @@ const REGEXP = { eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, billTitle: /^([ㄱ-ㅎ가-힣a-zA-Z0-9ㆍᆢ]\s?)*$/, memberName: /^([ㄱ-ㅎ가-힣a-zA-Zㆍᆢ]\s?)*$/, + accountNumber: /^[0-9\s\-]*$/, }; export default REGEXP; diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts index 4b78031b9..f311dedea 100644 --- a/client/src/constants/rule.ts +++ b/client/src/constants/rule.ts @@ -3,6 +3,8 @@ const RULE = { maxEventPasswordLength: 4, maxMemberNameLength: 4, maxPrice: 10000000, + minAccountNumberLength: 8, + maxAccountNumberLength: 30, }; export default RULE; diff --git a/client/src/utils/validate/validateAccountNumber.ts b/client/src/utils/validate/validateAccountNumber.ts new file mode 100644 index 000000000..fb100a22b --- /dev/null +++ b/client/src/utils/validate/validateAccountNumber.ts @@ -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; From f6d95fd50705ac392ee746478e150f844f802d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Wed, 25 Sep 2024 17:24:47 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=EA=B3=84=EC=A2=8C=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9C=A0=ED=9A=A8=EC=84=B1=EC=9D=84=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=ED=95=98=EA=B3=A0=20input=EC=9D=84=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useAccount.ts | 44 +++++++++++++++++++++--- client/src/pages/AccountPage/Account.tsx | 19 +++++++--- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/client/src/hooks/useAccount.ts b/client/src/hooks/useAccount.ts index 4e3e83dfc..247794779 100644 --- a/client/src/hooks/useAccount.ts +++ b/client/src/hooks/useAccount.ts @@ -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(null); const [canSubmit, setCanSubmit] = useState(false); + const [isPasting, setIsPasting] = useState(false); useEffect(() => { setBankName(bankName); @@ -24,7 +29,32 @@ const useAccount = () => { }; const handleAccount = (event: React.ChangeEvent) => { - 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) => { + 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 = () => { @@ -49,15 +79,21 @@ const useAccount = () => { const existEmptyField = bankName.trim() === '' && accountNumber.trim() === ''; const isChanged = bankName !== bankNameState || accountNumber !== accountNumberState; - setCanSubmit(!existEmptyField && isChanged); - }, [bankName, accountNumber, bankNameState, accountNumberState]); + setCanSubmit(!existEmptyField && isChanged && accountNumberErrorMessage === null); + }, [bankName, accountNumber, bankNameState, accountNumberState, accountNumberErrorMessage]); + + useEffect(() => { + console.log(accountNumberErrorMessage); + }, [accountNumberErrorMessage]); return { bankName: bankNameState, accountNumber: accountNumberState, + accountNumberErrorMessage, canSubmit, selectBank, handleAccount, + handleAccountOnPaste, enrollAccount, }; }; diff --git a/client/src/pages/AccountPage/Account.tsx b/client/src/pages/AccountPage/Account.tsx index 1b7d685ff..6b331be81 100644 --- a/client/src/pages/AccountPage/Account.tsx +++ b/client/src/pages/AccountPage/Account.tsx @@ -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(); @@ -40,19 +49,19 @@ const Account = () => { errorText={null} autoFocus={false} isAlwaysOnLabel - isAlwaysOnInputBorder readOnly onClick={() => setIsBottomSheetOpen(true)} /> {isBottomSheetOpen && ( Date: Wed, 25 Sep 2024 17:27:37 +0900 Subject: [PATCH 3/4] =?UTF-8?q?style:=20console.log=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useAccount.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/src/hooks/useAccount.ts b/client/src/hooks/useAccount.ts index 247794779..f908c0cd6 100644 --- a/client/src/hooks/useAccount.ts +++ b/client/src/hooks/useAccount.ts @@ -82,10 +82,6 @@ const useAccount = () => { setCanSubmit(!existEmptyField && isChanged && accountNumberErrorMessage === null); }, [bankName, accountNumber, bankNameState, accountNumberState, accountNumberErrorMessage]); - useEffect(() => { - console.log(accountNumberErrorMessage); - }, [accountNumberErrorMessage]); - return { bankName: bankNameState, accountNumber: accountNumberState, From 4c46a990a68ccccb37abf79330f0d3a7005d580a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Thu, 26 Sep 2024 10:34:29 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=EA=B3=84=EC=A2=8C=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=A0=95=EA=B7=9C=ED=91=9C=ED=98=84=EC=8B=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/regExp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts index 1903e97a4..8a32f3755 100644 --- a/client/src/constants/regExp.ts +++ b/client/src/constants/regExp.ts @@ -3,7 +3,7 @@ const REGEXP = { eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, billTitle: /^([ㄱ-ㅎ가-힣a-zA-Z0-9ㆍᆢ]\s?)*$/, memberName: /^([ㄱ-ㅎ가-힣a-zA-Zㆍᆢ]\s?)*$/, - accountNumber: /^[0-9\s\-]*$/, + accountNumber: /^\d+([\s\-]\d+)*[\s\-]?$/, }; export default REGEXP;