Skip to content

Commit 5052eee

Browse files
authored
Merge pull request #84 from haruharuganda/passwordChange
Feat. authenticationNumber #78 이메일 인증 기능,CSS완성
2 parents a6c39a5 + a124a60 commit 5052eee

21 files changed

+638
-64
lines changed

src/api/LoginApi.jsx

+8
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,12 @@ export const LoginApi = {
1010
console.log("카카오 페이로드", payload);
1111
return await instance.post("kakao/login", payload);
1212
},
13+
14+
SendEmailAuthenticationNumber: async (payload) => {
15+
return await instance.post("/auth/password", payload);
16+
},
17+
18+
SendAuthenticationNumber: async (payload) => {
19+
return await instance.patch("/auth/code", payload);
20+
},
1321
};

src/components/follow/SearchCards.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const SearchCards = ({ userInfo }) => {
3131
<div className="flex w-[119px] items-center">{userInfo.username}</div>
3232
</div>
3333
{isFollowed || (
34-
<div className="flex items-center w-[62px] h-[39px] justify-center text-sm rounded-[4px] text-white bg-[#002C51]">
34+
<div className="flex items-center w-[62px] h-[39px] justify-center text-sm rounded-[4px] text-white bg-[#002C51] cursor-pointer">
3535
<span onClick={handleClick}>{isFollowed || "팔로우"}</span>
3636
</div>
3737
)}

src/components/follow/UserSearch.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const UserSearch = () => {
4141
placeholder="찾고자 하는 사용자 이름을 입력해 주세요."
4242
></input>
4343
<img
44-
className="absolute top-[20px] right-[40px]"
44+
className="absolute top-[15px] right-[40px]"
4545
src={searchIcon}
4646
alt="돋보기 아이콘"
4747
/>

src/components/layout/Layout.jsx

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ const Layout = ({ children }) => {
6464
case "/editProfile":
6565
setHeader(() => <TopNavTitleBar>프로필 변경</TopNavTitleBar>);
6666
break;
67+
case "/login/auth/InputEmail":
68+
setHeader(() => <TopNavTitleBar>이메일 입력</TopNavTitleBar>);
69+
break;
6770
default:
6871
setHeader(null);
6972
break;

src/components/layout/input/LoginSignupInputBox.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ const LoginSignupInputBox = forwardRef((props, ref) => {
44
const { type, placeholder, onChange, id, bgColor, shadow } = props;
55
return (
66
<>
7-
<div className={`${shadow}`}>
7+
<div>
88
<input
99
// className={`w-full px-3 h-[50px] ${bgColor} focus:bg-inputBoxFocus placeholder-inputText `}
10-
className={`w-full px-3 h-[50px] ${bgColor} placeholder-inputPlaceHoldText`}
10+
className={`w-full px-3 h-[50px] ${bgColor} ${shadow} placeholder-inputPlaceHoldText`}
1111
type={type}
1212
id={id}
1313
ref={ref}

src/components/login/EmailLogin.jsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ const EmailLogin = () => {
2626
shadowEmail: "",
2727
shadowPassword: "",
2828
});
29-
const { isLoading } = useSelector((state) => state.LoginSlice);
3029

31-
console.log(isLoading);
3230
//서버에 전달하기 위한 input Ref 생성
3331
const userEmailRef = useRef();
3432
const userPasswordRef = useRef();
@@ -209,7 +207,10 @@ const EmailLogin = () => {
209207
</form>
210208
<div className="mt-[26px] grid grid-cols-2 text-center">
211209
<div className="border-4 border-indigo-600">
212-
<button className="text-textBlack text-[16px] font-[400] px-[30px] py-[10px]">
210+
<button
211+
className="text-textBlack text-[16px] font-[400] px-[30px] py-[10px]"
212+
onClick={() => navigate("/login/auth/InputEmail")}
213+
>
213214
비밀번호 재설정
214215
</button>
215216
</div>

src/components/login/InputEmail.jsx

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
import React, { useState } from "react";
2+
import Label from "../layout/Label";
3+
import LoginSignupInputBox from "../layout/input/LoginSignupInputBox";
4+
import IsModal from "../modal/Modal";
5+
import { useRef } from "react";
6+
import { LoginApi } from "../../api/LoginApi";
7+
8+
const InputEmail = () => {
9+
const emailRef = useRef();
10+
const authenticationNumberRef = useRef();
11+
const [style, setStyle] = useState({
12+
bgColorEmail: "bg-inputBox",
13+
shadowEmail: "",
14+
bgColorAuthenticationNumber: "bg-inputBox",
15+
shadowAuthenticationNumber: "",
16+
});
17+
const [regulation, setRegulation] = useState("");
18+
const [isOpen, setOpen] = useState(false);
19+
const [ModalStr, setModalStr] = useState({
20+
modalTitle: "",
21+
modalMessage: "",
22+
});
23+
const [isLoding, setIsLoding] = useState(false);
24+
const [InputCheck, setInputCheck] = useState(false);
25+
const onModalOpen = () => {
26+
setOpen({ isOpen: true });
27+
};
28+
const onMoalClose = () => {
29+
setOpen({ isOpen: false });
30+
};
31+
32+
const onInputColor = (event) => {
33+
const { id, value } = event.target;
34+
if (id === "email") {
35+
console.log("email입니다");
36+
setStyle(() => ({
37+
...style,
38+
bgColorEmail: "bg-inputBoxFocus",
39+
shadowEmail: "drop-shadow-inputBoxShadow",
40+
}));
41+
if (value.trim() === "") {
42+
setStyle(() => ({
43+
...style,
44+
bgColorEmail: "bg-inputBox",
45+
shadowEmail: "",
46+
}));
47+
}
48+
} else {
49+
setStyle(() => ({
50+
...style,
51+
bgColorAuthenticationNumber: "bg-inputBoxFocus",
52+
shadowAuthenticationNumber: "drop-shadow-inputBoxShadow",
53+
}));
54+
if (value.trim() === "") {
55+
setStyle(() => ({
56+
...style,
57+
bgColorAuthenticationNumber: "bg-inputBox",
58+
shadowAuthenticationNumber: "",
59+
}));
60+
}
61+
}
62+
};
63+
64+
const onSendEmail = () => {
65+
const email = emailRef.current;
66+
if (email.value.trim() === "") {
67+
setRegulation(() => "이메일을 입력해주세요");
68+
} else {
69+
setRegulation(() => "");
70+
}
71+
sendEmail({ email: email.value });
72+
};
73+
74+
const sendEmail = async (payload) => {
75+
try {
76+
setIsLoding(() => true);
77+
onModalOpen();
78+
const data = await LoginApi.SendEmailAuthenticationNumber(payload);
79+
setIsLoding(() => false);
80+
setModalStr({
81+
modalTitle: "이메일함을 확인해주세요",
82+
modalMessage: "인증번호를 입력해주세요",
83+
});
84+
setInputCheck(() => true);
85+
} catch (error) {
86+
console.log(error.response);
87+
const { data } = error.response;
88+
if (data.status === 400) {
89+
setIsLoding(() => false);
90+
setModalStr({
91+
modalTitle: data.message,
92+
modalMessage: "이메일을 확인해주세요.",
93+
});
94+
}
95+
}
96+
};
97+
98+
const onSubmitNextPage = () => {
99+
const email = emailRef.current;
100+
const authenticationNumber = authenticationNumberRef.current;
101+
102+
if (email.value.trim() === "") {
103+
setRegulation(() => "이메일을 입력해주세요");
104+
email.focus();
105+
return;
106+
} else if (authenticationNumber.value.trim() === "") {
107+
setRegulation(() => "인증번호를 입력해주세요");
108+
authenticationNumber.focus();
109+
return;
110+
}
111+
112+
if (InputCheck) {
113+
onSubmitNextPageAxios({
114+
email: email.value,
115+
code: authenticationNumber.value,
116+
});
117+
}
118+
};
119+
120+
const onSubmitNextPageAxios = async (payload) => {
121+
try {
122+
setIsLoding(() => true);
123+
onModalOpen();
124+
const data = await LoginApi.SendAuthenticationNumber(payload);
125+
setIsLoding(() => false);
126+
console.log(data);
127+
} catch (error) {
128+
console.log(error.response);
129+
const { data } = error.response;
130+
if (data.status === 400) {
131+
setIsLoding(() => false);
132+
setModalStr({
133+
modalTitle: "인증번호 실패",
134+
modalMessage: `인증번호가 잘못 입력되었습니다. \n 인증요청을 재시도 해주세요.`,
135+
});
136+
}
137+
}
138+
};
139+
140+
return (
141+
<div className="container ">
142+
<div className=" grid grid-flow-row ml-[20px] mr-[20px] mt-[55px]">
143+
<div className="mb-[4px]">
144+
<Label>비밀번호를 분실한 아이디를 입력해주세요</Label>
145+
</div>
146+
<div className="w-full">
147+
<div className="flex flex-col gap-[12px]">
148+
<div className="flex items-center gap-[20px] w-full">
149+
<input
150+
id="email"
151+
type={"email"}
152+
ref={emailRef}
153+
onChange={onInputColor}
154+
autoComplete="off"
155+
placeholder="아이디(이메일) 입니다."
156+
className={`w-[234px] px-3 h-[50px] ${style.bgColorEmail} ${style.shadowEmail} placeholder-inputPlaceHoldText`}
157+
/>
158+
<div
159+
onClick={onSendEmail}
160+
className=" bg-[#FFFFFF] flex items-center h-[50px] p-[5px] border-solid border-2 text-[16px] font-[600] border-[#002C51] rounded-[4px] leading-[28px] cursor-pointer"
161+
>
162+
인증 요청
163+
</div>
164+
</div>
165+
<div className="flex items-center h-[20px]">
166+
<p className=" w-full font-[500] text-[16px] text-[#DE0D0D] flex items-center">
167+
{regulation}
168+
</p>
169+
</div>
170+
<div className="h-[full]">
171+
<LoginSignupInputBox
172+
id="AuthenticationNumber"
173+
type="text"
174+
placeholder="인증번호 입력"
175+
onChange={onInputColor}
176+
bgColor={style.bgColorAuthenticationNumber}
177+
shadow={style.shadowAuthenticationNumber}
178+
ref={authenticationNumberRef}
179+
/>
180+
</div>
181+
</div>
182+
<div>
183+
<button
184+
className="mt-[65px] w-full bg-[#002C51] h-[40px] rounded-[4px] font-[600] text-[#fff]"
185+
onClick={onSubmitNextPage}
186+
>
187+
확인
188+
</button>
189+
</div>
190+
</div>
191+
<IsModal
192+
isModalOpen={isOpen.isOpen}
193+
onMoalClose={onMoalClose}
194+
message={{ ModalStr }}
195+
isLoding={isLoding}
196+
/>
197+
</div>
198+
</div>
199+
);
200+
};
201+
202+
export default InputEmail;

src/components/main/Main.jsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ const Main = () => {
1515
console.log(schedules);
1616
const [nickName, setNickname] = useState(sessionStorage.getItem("nickname"));
1717
useEffect(() => {
18-
const getemail = sessionStorage.getItem("email");
18+
const getNickname = sessionStorage.getItem("nickname");
1919
const getprofilImg = sessionStorage.getItem("profileImage");
2020
const userId = sessionStorage.getItem("userId");
2121

22-
if (nickName && getemail) {
22+
if (getNickname && userId) {
2323
if (getprofilImg) {
2424
setProfileImg(getprofilImg);
2525
dispatch(__getSchedule(userId));
2626
}
2727
} else {
2828
navigate(`/login`);
2929
}
30-
}, [navigate, nickName]);
30+
}, [navigate, nickName, dispatch]);
3131

3232
return (
3333
<>

src/components/modal/Modal.jsx

+32-16
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useState } from "react";
22
import Modal from "react-modal";
3-
4-
const IsModal = ({ isModalOpen, onMoalClose, message }) => {
3+
import MoonLoader from "react-spinners/MoonLoader";
4+
const IsModal = ({ isModalOpen, onMoalClose, message, isLoding }) => {
55
const modalStr = message.ModalStr;
66

77
const [modalIsOpen, setModalIsOpen] = useState(false);
@@ -43,20 +43,36 @@ const IsModal = ({ isModalOpen, onMoalClose, message }) => {
4343
onRequestClose={() => setModalIsOpen(false)}
4444
>
4545
<div className="grid grid-flow-row gap-[20px] text-center">
46-
<div className="flex flex-col items-center gap-[14px] mt-[10px]">
47-
<h1 className="px-[10px] text-[#12396F] text-[18px] font-[700] whitespace-pre-line">
48-
{modalStr.modalTitle}
49-
</h1>
50-
<p className="font-[400] text-[14px] text-[#12396F] whitespace-pre">
51-
{modalStr.modalMessage}
52-
</p>
53-
</div>
54-
<button
55-
className=" w-full bg-[#002C51] h-[40px] rounded-[4px] font-[600] text-[#fff]"
56-
onClick={onMoalClose}
57-
>
58-
확인
59-
</button>
46+
{isLoding ? (
47+
<div className="flex flex-col items-center mt-[35px]">
48+
<MoonLoader
49+
color="#36a6d6"
50+
cssOverride={{}}
51+
loading
52+
size={50}
53+
speedMultiplier={1}
54+
/>
55+
</div>
56+
) : (
57+
<>
58+
<div className="flex flex-col items-center gap-[14px] mt-[10px]">
59+
<h1 className="px-[10px] text-[#12396F] text-[18px] font-[700] whitespace-pre-line">
60+
{modalStr.modalTitle}
61+
</h1>
62+
<div className="h-[20px]">
63+
<p className="font-[400] text-[14px] text-[#12396F] whitespace-pre">
64+
{modalStr.modalMessage}
65+
</p>
66+
</div>
67+
</div>
68+
<button
69+
className=" w-full bg-[#002C51] h-[40px] rounded-[4px] font-[600] text-[#fff]"
70+
onClick={onMoalClose}
71+
>
72+
확인
73+
</button>
74+
</>
75+
)}
6076
</div>
6177
</Modal>
6278
);

0 commit comments

Comments
 (0)