Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: 전화번호 입력 시 하이픈 추가 #298

Merged
merged 3 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 37 additions & 84 deletions src/components/Authentication/UserInputNumber.jsx
Original file line number Diff line number Diff line change
@@ -1,118 +1,62 @@
import { message } from "antd";
import axios from "axios";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import useFetchUserPhoneNumber from "../../hooks/useFetchUserPhoneNumber";
import useSendSms from "../../hooks/useSendSms";
import RedButton from "./RedButton";
import "./UserInputNumber.css";
import UserInputNumberMessage from "./UserInputNumberMessage";

const TIMER_DURATION = 180; //타이머 시간 설정(3분)


const UserInputNumber = () => {
const [chkButton, setChkButton] = useState(false); // 인증버튼 클릭 여부
const [Phonenumber, setPhonenumber] = useState(""); // 전화번호 상태
const [verifyState, setVerifyState] = useState(false); //전화번호 인증 상태
const [postmessage, setPostmessage] = useState(false); // 인증 번호 발송 성공 여부
const navigate = useNavigate();
const apiRoot = process.env.REACT_APP_API_ROOT;
const apiVer = "api/v1";
const apiUrl1 = `${apiRoot}/${apiVer}/sms/send`;
const apiUrl2 = `${apiRoot}/${apiVer}/sms/authority`;
const token = localStorage.getItem("accessToken");
const [postmessage, setPostmessage] = useState(false); // 인증 번호 발송 여부
const { handleFetchUserPhoneNumber } = useFetchUserPhoneNumber();
const { handleSendSms } = useSendSms();

const handleCheckSendSem = (send) => {
setPostmessage(send);
};

const handleButtonClick = () => {
if (/^\d+$/.test(Phonenumber) && Phonenumber.length === 11) {
setChkButton(true);
if (!postmessage) {
handlePostmessage();
handleSendSms(Phonenumber, handleCheckSendSem);
} else {
setPostmessage(false);
handlePostmessage();
handleSendSms(Phonenumber, handleCheckSendSem);
}
} else {
message.info("전화번호를 올바르게 입력해주세요.");
}
};

const handlePostmessage = async () => {
try {
setChkButton(true);
const response = await axios.post(
apiUrl1,
{
phoneNumber: Phonenumber,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
console.log(response);

if (response.data.success) {
message.success("인증번호를 발송했습니다.");
setPostmessage(true);
} else {
message.error("인증번호를 발송에 실패했습니다.");
setPostmessage(false);
}
} catch (error) {
console.error(error);
message.error("인증번호를 발송에 실패했습니다.");
setPostmessage(false);
}
const handlePhoneChange = (event) => {
const HyphenNumber = event.target.value.replace(/[^0-9]/g, "");
setPhonenumber(HyphenNumber);
};

// 주석 풀기
const renderUserInputNumberMessage = () => {
if (postmessage) {
return (
<UserInputNumberMessage
phoneNumber={Phonenumber}
initialTimer={TIMER_DURATION}
onAuthSuccess={handleAuthSuccess}
/>
);
const displayFormattedPhoneNumber = (numbers) => {
if (numbers.length <= 3) {
return numbers;
} else if (numbers.length <= 7) {
return `${numbers.slice(0, 3)}-${numbers.slice(3)}`;
} else {
return `${numbers.slice(0, 3)}-${numbers.slice(3, 7)}-${numbers.slice(
7
)}`;
}
return null;
};

const handlePhoneChange = (event) => {
setPhonenumber(event.target.value);
};
// 번호 인증 성공 여부 확인
const handleAuthSuccess = (success) => {
setVerifyState(success);
};

const handleRegisterClick = async () => {
const handleRegisterClick = () => {
if (verifyState) {
try {
const response = await axios.post(
apiUrl2,
{
phoneNumber: Phonenumber,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
console.log(response);

if (response.data.success) {
message.success("전화번호 등록 성공했습니다.");
navigate("/");
} else {
console.log("전화번호 등록 실패", response.data);
message.info("전화번호 등록에 실패하셨습니다.");
}
} catch (error) {
console.error(error);
message.info("전화번호 등록에 실패하셨습니다.");
}
handleFetchUserPhoneNumber(Phonenumber);
} else {
message.info("전화번호 인증부터 진행해주세요.");
}
Expand All @@ -123,9 +67,12 @@ const UserInputNumber = () => {
<div className="user-input-phone-number-wrapper">
<input
type="tel"
inputmode="numeric"
pattern="[0-9]*"
placeholder="전화번호"
value={Phonenumber}
value={displayFormattedPhoneNumber(Phonenumber)}
onChange={handlePhoneChange}
maxLength="13"
className="user-input-phone-number-input"
/>
<button
Expand All @@ -138,7 +85,13 @@ const UserInputNumber = () => {
인증
</button>
</div>
{renderUserInputNumberMessage()}
{postmessage && (
<UserInputNumberMessage
phoneNumber={Phonenumber}
initialTimer={TIMER_DURATION}
onAuthSuccess={handleAuthSuccess}
/>
)}
<RedButton
type="submit"
onClick={handleRegisterClick}
Expand Down
106 changes: 37 additions & 69 deletions src/components/Authentication/UserInputNumberMessage.jsx
Original file line number Diff line number Diff line change
@@ -1,83 +1,37 @@
import axios from "axios";
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import useAuthVerification from "../../hooks/useAuthVerification";
import useTimer from "../../hooks/useTimer";
import LoginChkAlrm from "./LoginChkAlrm";
import "./UserInputNumberMessage.css";
const Timer = ({ minutes, seconds }) => (
<div className="timer">
{minutes}:{seconds < 10 ? `0${seconds}` : seconds}
</div>
);
function useTimer(initialSeconds) {
const [timer, setTimer] = useState(initialSeconds);
useEffect(() => {
const interval = setInterval(() => {
setTimer((prevTimer) => (prevTimer > 0 ? prevTimer - 1 : 0));
}, 1000);

return () => clearInterval(interval);
}, [setTimer]);
return { timer };
}
function UserInputNumberMessage({ phoneNumber, onAuthSuccess, initialTimer }) {
const token = localStorage.getItem("accessToken");
const [chkNum, setChkNum] = useState("");
const [isAuth, setIsAuth] = useState();
const apiUrl = process.env.REACT_APP_API_ROOT;
const { timer } = useTimer(initialTimer);
const handleInputText = async (e) => {
const [isCheck, setIsCheck] = useState(false);
const { handleAuthVerificationNumer } = useAuthVerification();

// 번호 인증 성공 여부 확인
const handleCheckInputNumber = (success) => {
setIsCheck(success);
onAuthSuccess(success);
};

const handleInputText = (e) => {
const newChkNum = e.target.value;
setChkNum(newChkNum);
// equlChknum(newChkNum, AUTH_CODE);
if (newChkNum.length === 6) {
try {
const response = await axios.post(
`${apiUrl}/api/v1/sms/verify`,
{
phoneNumber: phoneNumber,
verifyNumber: newChkNum,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);

if (response.data.success) {
onAuthSuccess(true);
setIsAuth(true);
} else {
onAuthSuccess(false);
setIsAuth(false);
}
} catch (error) {
console.log("통신에러", error);
}
} else {
onAuthSuccess(false);
setIsAuth(false);
}
};

const renderMessage = () => {
if (timer <= 0) {
return (
<LoginChkAlrm icon={"X"} paddingSize={"0.45rem"}>
인증 시간이 초과되었습니다.
</LoginChkAlrm>
);
} else if (timer > 0 && !isAuth) {
return (
<LoginChkAlrm icon={"X"} paddingSize={"0.45rem"}>
인증번호가 일치하지 않습니다.
</LoginChkAlrm>
);
} else if (timer > 0 && isAuth) {
return (
<LoginChkAlrm icon={""} paddingSize={"0.45rem"}>
인증이 완료되었습니다.
</LoginChkAlrm>
handleAuthVerificationNumer(
phoneNumber,
newChkNum,
handleCheckInputNumber
);
} else {
handleCheckInputNumber(false);
}
};

Expand All @@ -89,17 +43,31 @@ function UserInputNumberMessage({ phoneNumber, onAuthSuccess, initialTimer }) {
type="text"
placeholder="인증번호"
value={chkNum}
autocomplete="off" //자동완성 없애기
autoComplete="one-time-code" //1번씩 자동완성(인증번호)
onChange={handleInputText}
maxLength="6"
// readOnly={isAuth}
/>
{timer > 0 && (
<Timer minutes={Math.floor(timer / 60)} seconds={timer % 60} />
<Timer minutes={Math.floor(timer / 60)} seconds={timer % 60} />
)}
</div>

<div style={{ width: "100%", marginTop: "0.37rem" }}>
{renderMessage()}
{timer > 0 && chkNum.length === 6 ? (
isCheck ? (
<LoginChkAlrm icon={""} paddingSize={"0.45rem"}>
인증이 완료되었습니다.
</LoginChkAlrm>
) : (
<LoginChkAlrm icon={"X"} paddingSize={"0.45rem"}>
인증번호가 일치하지 않습니다.
</LoginChkAlrm>
)
) : timer <= 0 ? (
<LoginChkAlrm icon={"X"} paddingSize={"0.45rem"}>
인증 시간이 초과되었습니다.
</LoginChkAlrm>
) : null}
</div>
</>
);
Expand Down
37 changes: 37 additions & 0 deletions src/hooks/useAuthVerification.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import commonApis from "../utils/commonApis";

// 인증번호 확인
const useAuthVerification = () => {
const apiUrl = `/sms/verify`;
const token = localStorage.getItem("accessToken");
const handleAuthVerificationNumer = async (
phoneNumber,
verifyNumber,
handleCheckInputNumber
) => {
try {
const response = await commonApis.post(
apiUrl,
{
phoneNumber: phoneNumber,
verifyNumber: verifyNumber,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
if (response.data.success) {
handleCheckInputNumber(true);
} else {
handleCheckInputNumber(false);
}
} catch (error) {
console.log("통신에러", error);
handleCheckInputNumber(false);
}
};
return { handleAuthVerificationNumer };
};
export default useAuthVerification;
6 changes: 3 additions & 3 deletions src/hooks/useFetchCoupons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import commonApis from "../utils/commonApis";
const apiUrl = `/coupon`;

const useFetchCoupons = () => {
const [coupons, setCoupons] = useState([]);
const [coupons, setCoupons] = useState(null); // null || []
const token = localStorage.getItem("accessToken");

useEffect(() => {
const fetchCoupons = async () => {
try {
const response = await commonApis.get(apiUrl, {
headers: {
Authorization: `Bearer ${token}`
}
Authorization: `Bearer ${token}`,
},
});
setCoupons(response.data.coupons);
} catch (error) {
Expand Down
Loading
Loading