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: 회원가입 완료 #62

Merged
merged 2 commits into from
Jun 21, 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
55 changes: 55 additions & 0 deletions src/components/Auth/Profile.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from "react";
import tw from "twin.macro";
import { styled } from "styled-components";
import * as S from "../../styles/GlobalStyles";

import { useDispatch } from "react-redux";
import { setProfile } from "../../store/reducers/common/profile";

import Profile1 from "~/assets/img/common/character/character_sol.svg";
import Profile2 from "~/assets/img/common/character/character_moli.svg";
import Profile3 from "~/assets/img/common/character/character_rino.svg";
import Profile4 from "~/assets/img/common/character/character_shoo.svg";
import Profile5 from "~/assets/img/common/character/character_doremi.svg";
import Profile6 from "~/assets/img/common/character/character_lulu.svg";
import Profile7 from "~/assets/img/common/character/character_pli.svg";
import Profile8 from "~/assets/img/common/character/character_lay.svg";

const profiles = [
{ id: 1, src: Profile1 },
{ id: 2, src: Profile2 },
{ id: 3, src: Profile3 },
{ id: 4, src: Profile4 },
{ id: 5, src: Profile5 },
{ id: 6, src: Profile6 },
{ id: 7, src: Profile7 },
{ id: 8, src: Profile8 },
];

const Profile = ({ selectedProfileId, onSelectProfile }) => {
// const dispatch = useDispatch();

const handleClick = (profileId) => {
onSelectProfile(profileId);
// dispatch(setProfile(profileId));
};

return (
<ProfileGrid>
{profiles.map((profile) => (
<ProfileImage key={profile.id} src={profile.src} alt={`Profile ${profile.id}`} isSelected={selectedProfileId === profile.id} onClick={() => handleClick(profile.id)} />
))}
</ProfileGrid>
);
};

export default Profile;

const ProfileGrid = styled.div`
${tw`grid grid-cols-3 gap-5`}
`;

const ProfileImage = styled.img`
${tw`w-20 h-20 rounded-full cursor-pointer`}
border: ${(props) => (props.isSelected ? "2px solid red" : "none")};
`;
2 changes: 1 addition & 1 deletion src/pages/Auth/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const Login = () => {
);
navigate("/");
} catch (error) {
alert(error);
alert(error.response.data.error.message);
}
};

Expand Down
77 changes: 57 additions & 20 deletions src/pages/Auth/Signup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import tw from "twin.macro";
import { styled } from "styled-components";
import { join, checkPhoneNum } from "../../services/user";

import * as S from "../../styles/GlobalStyles";

import ChatBubble from "~/components/Auth/ChatBubble";
import Input from "~/components/Auth/Input";
import Profile from "../../components/Auth/Profile";

import CompleteImage from "~/assets/img/common/complete.svg";

Expand All @@ -16,9 +18,10 @@ const Signup = () => {
name: "",
phoneNum: "",
accountInfo: "",
confirmAccountInfo: "",
birthDate: "",
profileId: 0,
});
const [confirmAccountInfo, setConfirmAccountInfo] = useState("");
const [showconfirmAccountInfo, setShowconfirmAccountInfo] = useState(false);
const [errorMessage, setErrorMessage] = useState("");

Expand All @@ -27,25 +30,33 @@ const Signup = () => {
const handleChange = (e) => {
if (e.target.name === "confirmAccountInfo") {
setShowconfirmAccountInfo(true);
setConfirmAccountInfo(e.target.value);
} else {
setUserData({
...userData,
[e.target.name]: e.target.value,
});
}

setUserData({
...userData,
[e.target.name]: e.target.value,
});
};

const handleNext = () => {
const handleNext = async () => {
let error = "";
if (step === 0 && !isNameValid(userData.name)) {
error = "이름은 2~5글자 이내의 한글로 입력해주세요.";
} else if (step === 1 && !isPhoneNumValid(userData.phoneNum)) {
// TODO: 이미 존재하는 전화번호인지도 확인
error = "전화번호는 010-XXXX-XXXX 형식으로 입력해주세요.";
} else if (step === 1) {
if (!isPhoneNumValid(userData.phoneNum)) {
error = "전화번호는 010-XXXX-XXXX 형식으로 입력해주세요.";
} else {
try {
await checkPhoneNum(userData.phoneNum);
} catch (err) {
error = "이미 가입된 전화번호입니다.";
}
}
} else if (step === 2) {
if (!isPasswordValid(userData.accountInfo)) {
error = "비밀번호는 6자리 숫자로 입력해주세요.";
} else if (showconfirmAccountInfo && userData.accountInfo !== userData.confirmAccountInfo) {
} else if (showconfirmAccountInfo && userData.accountInfo !== confirmAccountInfo) {
error = "비밀번호가 일치하지 않습니다.";
}
} else if (step === 3 && !isBirthDateValid(userData.birthDate)) {
Expand All @@ -64,8 +75,24 @@ const Signup = () => {
}
};

const handleSubmit = () => {
setStep(4);
const handleSubmit = async () => {
if (userData.profileId === 0) {
alert("프로필 이미지를 선택해주세요.");
} else {
try {
await join(userData);
setStep(5);
} catch (error) {
setErrorMessage(error);
}
}
};

const handleProfileSelect = (id) => {
setUserData({
...userData,
profileId: id,
});
};

const handleLoginRedirect = () => {
Expand Down Expand Up @@ -108,7 +135,7 @@ const Signup = () => {
<div tw="flex flex-col">
<ChatBubble text="비밀번호를 한 번 더 알려주세요!" />
<RightAlignedDiv>
<Input type="password" name="confirmAccountInfo" value={userData.confirmAccountInfo} onChange={handleChange} />
<Input type="password" name="confirmAccountInfo" value={confirmAccountInfo} onChange={handleChange} />
</RightAlignedDiv>
</div>
)}
Expand All @@ -125,6 +152,15 @@ const Signup = () => {
</StepWrapper>
)}
{step === 4 && (
<StepWrapper>
<CompleteWrapper>
<S.Question>프로필을 선택해주세요!</S.Question>
<Profile selectedProfileId={userData.profileId} onSelectProfile={handleProfileSelect} />
{errorMessage && <ErrorMessage>{errorMessage}</ErrorMessage>}
</CompleteWrapper>
</StepWrapper>
)}
{step === 5 && (
<StepWrapper tw="justify-center mb-40">
<CompleteWrapper>
<img src={CompleteImage} alt="완료" />
Expand All @@ -134,16 +170,16 @@ const Signup = () => {
)}

<ButtonWrapper>
{step < 3 ? (
{step < 4 ? (
<S.BottomBtn onClick={handleNext} text="다음">
다음
</S.BottomBtn>
) : step === 3 ? (
) : step === 4 ? (
<S.BottomBtn onClick={handleSubmit} text="제출">
제출
</S.BottomBtn>
) : (
step === 4 && (
step === 5 && (
<S.BottomBtn onClick={handleLoginRedirect} text="로그인 하러 가기">
로그인 하러 가기
</S.BottomBtn>
Expand Down Expand Up @@ -196,12 +232,13 @@ const ButtonWrapper = styled.div`
mt-4`}
`;

const CompleteWrapper = tw.div`
flex
const CompleteWrapper = styled.div`
${tw`flex
flex-col
gap-2
items-center
justify-center
justify-center`}
height: calc(100vh - 200px)
`;

const ErrorMessage = tw.div`
Expand Down
4 changes: 0 additions & 4 deletions src/services/api.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ export const notiInstance = axios.create({
baseURL: BASE_URL + "/notifications",
});

export const authInstance = axios.create({
baseURL: BASE_URL + "/auth",
});

baseInstance.interceptors.request.use(
(config) => {
const accessToken = getCookie("accessToken");
Expand Down
18 changes: 12 additions & 6 deletions src/services/user.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { authInstance } from "./api";
import { baseInstance } from "./api";
import { setCookie } from "./cookie";

export const join = async (userData) => {
try {
const response = await authInstance.post("/join", userData);
const response = await baseInstance.post("/auth/join", userData);
return response.data.response;
} catch (error) {
throw error;
Expand All @@ -12,7 +12,7 @@ export const join = async (userData) => {

export const login = async (phoneNum, accountInfo) => {
try {
const response = await authInstance.post("/login", {
const response = await baseInstance.post("/auth/login", {
phoneNum,
accountInfo,
});
Expand All @@ -30,6 +30,12 @@ export const login = async (phoneNum, accountInfo) => {
}
};

// export const setAuthHeaders = (accessToken) => {
// authInstance.defaults.headers.common["Authorization"] = `${accessToken}`;
// };
export const checkPhoneNum = async (phoneNum) => {
try {
const response = await baseInstance.post("/auth/useful-phone", phoneNum);

return response.data.response.success;
} catch (error) {
throw error;
}
};
2 changes: 1 addition & 1 deletion src/store/reducers/Auth/user.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createSlice } from "@reduxjs/toolkit";

const initialState = {
isLoggedIn: false,
userInfo: { sn: "1", familyInfo: [] },
userInfo: null,
accessToken: null,
refreshToken: null,
};
Expand Down
19 changes: 19 additions & 0 deletions src/store/reducers/common/profile.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
profileId: 0,
};

const profileSlice = createSlice({
name: "profile",
initialState: initialState,
reducers: {
setProfile(state, action) {
state.profileId = action.payload;
},
},
});

export const { setProfile } = profileSlice.actions;

export default profileSlice.reducer;
4 changes: 3 additions & 1 deletion src/store/stores.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import investReducer from "./reducers/Invest/invest";
import missionReducer from "./reducers/Mission/mission";
import notiReducer from "./reducers/Noti/notification";
import userReducer from "./reducers/Auth/user";
import profileReducer from "./reducers/common/profile";

const rootPersistConfig = {
key: "root",
storage: storage,
whitelist: ["invest", "user"],
whitelist: ["invest", "user", "profile"],
};

const rootReducer = combineReducers({
Expand All @@ -22,6 +23,7 @@ const rootReducer = combineReducers({
loan: loanReducer,
noti: notiReducer,
user: userReducer,
profile: profileReducer,
});

const persistedReducer = persistReducer(rootPersistConfig, rootReducer);
Expand Down