Skip to content

Commit

Permalink
Merge pull request StudyBadge-TenTen#142 from StudyBadge-TenTen/hotfix
Browse files Browse the repository at this point in the history
[StudyBadge_FE StudyBadge-TenTen#117 ]: 추가 기능 구현 - 계좌 인증
  • Loading branch information
rabyeoljji authored Aug 10, 2024
2 parents 4527898 + e46e99d commit 6b8b486
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 48 deletions.
69 changes: 63 additions & 6 deletions src/components/auth/SignUpUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,55 @@ import { BANK_LIST } from "../../constants/bank-list";
import PageScrollTop from "../common/PageScrollTop";
import { CustomErrorType } from "@/types/common";
import axios from "axios";
import { getAccountVerification } from "@/services/auth-api";

const SignUp: React.FC = () => {
const formListFirst = ["이메일", "이름", "비밀번호", "비밀번호확인"];
const formListSecond = ["계좌번호", "닉네임", "소개"];
const [isAccountVerified, setIsAccountVerified] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const authStore = useAuthStore();

const verifyAccount = async () => {
const bank = BANK_LIST.find((bankObj) => bankObj.name === authStore.accountBank);

if (bank && authStore.account) {
try {
const response = await getAccountVerification(bank.code, authStore.account);
if (axios.isAxiosError(response)) {
const error = response.response?.data as CustomErrorType;
alert(error.message);
setIsAccountVerified(() => false);
} else {
if (response.data.accountHolder === authStore.name) {
alert("계좌번호 인증에 성공하였습니다");
setIsAccountVerified(() => true);
} else {
alert("본인 명의의 계좌가 아닙니다. 입력한 이름과 계좌 소유주명이 동일하지 않습니다.");
setIsAccountVerified(() => false);
}
}
} catch (error) {
if (axios.isAxiosError(error)) {
const customError = error.response?.data as CustomErrorType;
alert(customError.message);
setIsAccountVerified(() => false);
} else {
alert(
"계좌번호 인증에 문제가 발생하였습니다. 문제가 반복될 경우 [email protected] 해당 주소로 문의 메일을 보내주시면 감사하겠습니다.",
);
setIsAccountVerified(() => false);
}
}
} else if (!bank) {
alert("선택한 은행이 존재하지 않습니다.");
return;
} else if (!authStore.account) {
alert("계좌번호를 입력해주세요");
return;
}
};

const validateForm = (): boolean => {
let result = true;
if (!authStore.email) {
Expand All @@ -29,6 +71,8 @@ const SignUp: React.FC = () => {
} else if (!authStore.account) {
alert("계좌번호 입력은 필수입니다.");
result = false;
} else if (!isAccountVerified) {
alert("계좌 인증이 필요합니다");
} else if (!authStore.password) {
alert("비밀번호 입력은 필수입니다.");
result = false;
Expand All @@ -40,12 +84,20 @@ const SignUp: React.FC = () => {
};

const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>, formName: string) => {
if (formName === "금융기관") {
if (isAccountVerified) {
setIsAccountVerified(() => false);
}
}
if (e.target.id === "계좌번호") {
if (Number.isNaN(Number(e.target.value))) {
authStore.setField("account", authStore.account);
alert("숫자만 입력해주세요");
return;
}
if (isAccountVerified) {
setIsAccountVerified(() => false);
}
}
authStore.setField(nameToField(formName), e.target.value);
};
Expand Down Expand Up @@ -113,8 +165,8 @@ const SignUp: React.FC = () => {
>
<option value="">-- 금융기관을 선택해주세요 --</option>
{BANK_LIST.map((bank) => (
<option key={bank} value={bank}>
{bank}
<option key={bank.name} value={bank.name}>
{bank.name}
</option>
))}
</select>
Expand All @@ -123,10 +175,7 @@ const SignUp: React.FC = () => {
{formName === "계좌번호" && (
<div className="w-full max-w-96 text-xs text-Gray-4 mb-2">계좌번호는 환급금 송금을 위한 항목입니다.</div>
)}
<div
key={formName}
className={`w-full sm:w-96 flex justify-between items-center ${formName === "계좌번호" ? "mb-14" : "mb-6"}`}
>
<div key={formName} className={`w-full sm:w-96 flex justify-between items-center mb-6`}>
<label className="text-Blue-2">
{formName}
{formName !== "소개" && <span>*</span>}
Expand All @@ -141,6 +190,14 @@ const SignUp: React.FC = () => {
onChange={(e) => handleChange(e, formName)}
/>
</div>
{formName === "계좌번호" &&
(isAccountVerified ? (
<div className="text-Green-1 mb-14">계좌인증완료</div>
) : (
<button onClick={() => verifyAccount()} className="btn-blue mb-14">
계좌번호 인증
</button>
))}
</React.Fragment>
))}
<button type="submit" className="btn-blue hover:bg-blue-700 text-white mt-10">
Expand Down
99 changes: 82 additions & 17 deletions src/components/profile/ProfileEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,28 @@ import axios from "axios";
import { useAuthStore } from "../../store/auth-store";
import { useNavigate } from "react-router";
import { CustomErrorType } from "@/types/common";
import { getAccountVerification } from "@/services/auth-api";

const ProfileEdit = ({ userInfo }: { userInfo: UserInfoType }): JSX.Element => {
// todo: 회원가입 시 정했던 닉네임이랑 소개 등 글자수 제한 반영하기

const navigate = useNavigate();

const { accessToken } = useAuthStore();
const [imageFile, setImageFile] = useState<File>();
const [isAccountVerified, setIsAccountVerified] = useState(false);
const [profileInfo, setProfileInfo] = useState({
nickname: "",
introduction: "",
account: "",
accountBank: "",
imgUrl: "",
});
const [imageFile, setImageFile] = useState<File>();

const imageInputRef = useRef<HTMLInputElement>(null);
const nicknameRef = useRef<HTMLInputElement>(null);
const accountRef = useRef<HTMLInputElement>(null);
const accountBankRef = useRef<HTMLSelectElement>(null);
const { accessToken } = useAuthStore();

useEffect(() => {
if (userInfo) {
Expand Down Expand Up @@ -56,6 +60,7 @@ const ProfileEdit = ({ userInfo }: { userInfo: UserInfoType }): JSX.Element => {
...origin,
accountBank: e.target.value,
}));
setIsAccountVerified(() => false);
}
if (e.target.id === "editAccount") {
if (Number.isNaN(Number(e.target.value))) {
Expand All @@ -68,6 +73,7 @@ const ProfileEdit = ({ userInfo }: { userInfo: UserInfoType }): JSX.Element => {
...origin,
account: e.target.value,
}));
setIsAccountVerified(() => false);
}
}
};
Expand Down Expand Up @@ -106,6 +112,47 @@ const ProfileEdit = ({ userInfo }: { userInfo: UserInfoType }): JSX.Element => {
}));
};

// 계좌 인증하는 함수
const verifyAccount = async () => {
const bank = BANK_LIST.find((bankObj) => bankObj.name === profileInfo.accountBank);

if (bank && profileInfo.account) {
try {
const response = await getAccountVerification(bank.code, profileInfo.account);
if (axios.isAxiosError(response)) {
const error = response.response?.data as CustomErrorType;
alert(error.message);
setIsAccountVerified(() => false);
} else {
if (response.data.accountHolder === userInfo.name) {
alert("계좌번호 인증에 성공하였습니다");
setIsAccountVerified(() => true);
} else {
alert("본인 명의의 계좌가 아닙니다. 입력한 이름과 계좌 소유주명이 동일하지 않습니다.");
setIsAccountVerified(() => false);
}
}
} catch (error) {
if (axios.isAxiosError(error)) {
const customError = error.response?.data as CustomErrorType;
alert(customError.message);
setIsAccountVerified(() => false);
} else {
alert(
"계좌번호 인증에 문제가 발생하였습니다. 문제가 반복될 경우 [email protected] 해당 주소로 문의 메일을 보내주시면 감사하겠습니다.",
);
setIsAccountVerified(() => false);
}
}
} else if (!bank) {
alert("선택한 은행이 존재하지 않습니다.");
return;
} else if (!profileInfo.account) {
alert("계좌번호를 입력해주세요");
return;
}
};

// 프로필 수정을 저장할 때 반영하도록 하는 함수
const handleSaveClick = async (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
Expand Down Expand Up @@ -139,6 +186,15 @@ const ProfileEdit = ({ userInfo }: { userInfo: UserInfoType }): JSX.Element => {
}
}

if (!isAccountVerified) {
alert("계좌 인증이 필요합니다");
if (accountRef.current) {
accountRef.current.classList.add("outline-Red-2");
accountRef.current.focus();
}
return;
}

if (nicknameRef.current) {
if (!nicknameRef.current.value) {
alert("닉네임 입력은 필수입니다.");
Expand Down Expand Up @@ -263,21 +319,30 @@ const ProfileEdit = ({ userInfo }: { userInfo: UserInfoType }): JSX.Element => {
ref={accountRef}
required
></input>
<select
name="bank"
id="bankDropdown"
className="w-fit p-1 border border-solid border-Gray-2 rounded-[10px] mt-2 mb-8"
value={profileInfo.accountBank}
ref={accountBankRef}
onChange={handleChange}
>
<option value="">-- 금융기관을 선택해주세요 --</option>
{BANK_LIST.map((bank) => (
<option key={bank} value={bank}>
{bank}
</option>
))}
</select>
<div className="flex flex-col items-center sm:flex-row sm:items-start mb-14">
<select
name="bank"
id="bankDropdown"
className="w-fit p-1 border border-solid border-Gray-2 rounded-[10px] mt-2"
value={profileInfo.accountBank}
ref={accountBankRef}
onChange={handleChange}
>
<option value="">-- 금융기관을 선택해주세요 --</option>
{BANK_LIST.map((bank) => (
<option key={bank.name} value={bank.name}>
{bank.name}
</option>
))}
</select>
{isAccountVerified ? (
<div className="text-Green-1 mb-14">계좌인증완료</div>
) : (
<button onClick={() => verifyAccount()} className="btn-blue w-24 mt-2 ml-4">
계좌번호 인증
</button>
)}
</div>
<button
onClick={(e) => handleSaveClick(e, profileInfo, imageFile)}
className="btn-blue w-fit self-center mt-10"
Expand Down
46 changes: 23 additions & 23 deletions src/constants/bank-list.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
export const BANK_LIST = [
"KEB하나은행",
"SC제일은행",
"국민은행",
"신한은행",
"외환은행",
"우리은행",
"한국시티은행",
"경남은행",
"광주은행",
"대구은행",
"부산은행",
"전북은행",
"제주은행",
"기업은행",
"농협",
"수협",
"한국산업은행",
"한국수출입은행",
"우리종합금융",
"SBI저축은행",
"애큐온저축은행",
"키움YES저축은행",
"푸른저축은행",
{ name: "KEB하나은행", code: "081" },
{ name: "SC제일은행", code: "023" },
{ name: "국민은행", code: "004" },
{ name: "신한은행", code: "088" },
{ name: "외환은행", code: "005" },
{ name: "우리은행", code: "020" },
{ name: "한국시티은행", code: "027" },
{ name: "경남은행", code: "039" },
{ name: "광주은행", code: "034" },
{ name: "대구은행", code: "031" },
{ name: "부산은행", code: "032" },
{ name: "전북은행", code: "037" },
{ name: "제주은행", code: "035" },
{ name: "기업은행", code: "003" },
{ name: "농협", code: "011" },
{ name: "수협", code: "007" },
{ name: "한국산업은행", code: "002" },
{ name: "한국수출입은행", code: "008" },
{ name: "우리종합금융", code: "295" },
{ name: "SBI저축은행", code: "103" },
{ name: "애큐온저축은행(HK)", code: "104" },
{ name: "키움YES저축은행(키움증권)", code: "264" },
{ name: "푸른저축은행(상호저축은행)", code: "050" },
];
9 changes: 7 additions & 2 deletions src/services/auth-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ export const postSignUp = async (userData: SignUpData) => {
};

export const getAuthEmail = async (email: string, code: string) => {
const response = await fetchCall<AxiosResponse | AxiosError>(`/api/members/auth?email=${email}&code=${code}`, "get");
const response = await fetchCall<AxiosResponse | AxiosError>(`/api/members/auth`, "get", null, { email, code });
return response;
};

export const postEmailResend = async (email: string) => {
const response = await fetchCall<AxiosResponse | AxiosError>(`/api/members/resend?email=${email}`, "post");
const response = await fetchCall<AxiosResponse | AxiosError>(`/api/members/resend`, "post", null, { email });
return response;
};

Expand Down Expand Up @@ -103,3 +103,8 @@ export const patchResetPassword = async (email: string, newPassword: string) =>
});
return response;
};

export const getAccountVerification = async (bankCode: string, bankNum: string) => {
const response = await fetchCall<AxiosResponse | AxiosError>(`/api/members/cert`, "get", null, { bankCode, bankNum });
return response;
};

0 comments on commit 6b8b486

Please sign in to comment.