Skip to content
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
7 changes: 6 additions & 1 deletion src/common/apis/member.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ export const handleKakaoLogin = () =>
location.href = `${import.meta.env.VITE_SERVER_URL}/oauth2/authorization/kakao`;

export const getProfile = async () =>
await axiosApi.get("/member/profile");
await axiosApi.get("/member/profile");

export const updateUsername = async (username: string) =>
await axiosApi.post("/member/username", {
username: username,
});
10 changes: 5 additions & 5 deletions src/common/slices/loginSlice.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {createSlice} from "@reduxjs/toolkit";

const initialState = {
isLogin: true,
accessToken: "token",
email: "diglog@example.com",
username: "diglog",
roles: ["ROLE_USER"],
isLogin: false,
accessToken: "",
email: "",
username: "",
roles: [],
}

const loginSlice = createSlice({
Expand Down
5 changes: 3 additions & 2 deletions src/common/util/regex.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
export const checkEmail = (email: string) => {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return email !== "" && email.match(regex);

return !!(email !== "" && email.match(regex));
}

export const checkPassword = (password: string) => {
const regex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\W_]{8,16}$/;

return password !== "" && password.match(regex);
return !!(password !== "" && password.match(regex));
}
8 changes: 4 additions & 4 deletions src/components/member/LoginButton.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import {ReactNode} from "react";

function LoginButton({text, onClick, bgColor, icon}: {
function LoginButton({text, onClick, bgColor, disable, icon}: {
text: string,
onClick: () => void,
bgColor: string,
disable?: boolean,
icon?: ReactNode
}) {
return (
<button onClick={onClick}
className={`rounded-[calc(12px)] ${bgColor} w-full h-14 flex gap-x-2 justify-center items-center hover:brightness-105 hover:cursor-pointer`}>
{(icon) ? icon : <div></div>}
className={`rounded-[calc(12px)] ${bgColor} ${disable && "opacity-40 hover:!cursor-auto"} w-full h-14 flex gap-x-2 justify-center items-center hover:brightness-105 hover:cursor-pointer cursor`}>
{(icon) ? icon : null}
<div>{text}</div>
<div></div>
</button>
);
}
Expand Down
9 changes: 8 additions & 1 deletion src/components/member/LoginTextField.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import * as React from "react";

function LoginTextField({label, type, placeholder, value, setValue, onKeyDown}: {
function LoginTextField({label, type, placeholder, value, setValue, error, isError, onKeyDown}: {
label?: string,
type: string,
placeholder: string,
value: string,
setValue: (value: string) => void,
error?: string,
isError?: boolean,
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void,
}) {
return (
Expand All @@ -19,6 +21,11 @@ function LoginTextField({label, type, placeholder, value, setValue, onKeyDown}:
value={value}
onChange={(event => setValue(event.target.value))}
onKeyDown={onKeyDown}/>
{(error) && (
isError ?
<p className="h-4 mt-2 text-sm text-red-600">{error}</p>
: <div className="h-4 mt-2"/>
)}
</div>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/layout/LoadingLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ function LoadingLayout({loading}: { loading: boolean }) {
return (
loading &&
<div
className="fixed inset-0 flex items-center justify-center bg-gray-300 bg-opacity-50 z-1000 dark:bg-gray-100 dark:bg-opacity-50">
className="fixed inset-0 flex items-center justify-center bg-gray-300 opacity-50 z-1000 dark:bg-gray-100 dark:bg-opacity-50">
<div role="status">
<svg aria-hidden="true"
className="inline w-8 h-8 text-gray-200 animate-spin dark:text-gray-600 fill-gray-600 dark:fill-gray-300"
Expand Down
8 changes: 7 additions & 1 deletion src/pages/member/CodePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import BasicLayout from "../../layout/BasicLayout.tsx";
import {useLocation, useNavigate} from "react-router-dom";
import {formatTimer} from "../../common/util/date.tsx";
import LoadingLayout from "../../layout/LoadingLayout.tsx";
import {checkCode} from "../../common/apis/member.tsx";

function CodePage() {

Expand Down Expand Up @@ -63,7 +64,12 @@ function CodePage() {
if (code[5] !== "") {
setLoading(true);

navigate("/signup", {state: {email: email, code: code.join("")}});
checkCode(email, code.join(""))
.then(() => {
navigate("/signup", {state: {email: email, code: code.join("")}});
})
.catch((error) => alert(error.response.data.message))
.finally(() => setLoading(false));
}
}, [code]);

Expand Down
26 changes: 18 additions & 8 deletions src/pages/member/EmailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import LoginButton from "../../components/member/LoginButton.tsx";
import {useNavigate} from "react-router-dom";
import * as React from "react";
import {checkEmail} from "../../common/util/regex.tsx";
import {sendMail} from "../../common/apis/member.tsx";
import LoadingLayout from "../../layout/LoadingLayout.tsx";

function EmailPage() {

const [signupInfo, setSignupInfo] = useState({email: "", code: "", password: ""});
const [loading, setLoading] = useState(false);
const [email, setEmail] = useState("");

const navigate = useNavigate();

Expand All @@ -21,12 +24,18 @@ function EmailPage() {
}

const handleVerifyEmail = () => {
if (!checkEmail(signupInfo.email)) {
alert("이메일 형식을 확인해주세요.");
if (!checkEmail(email)) {
alert("이메일 형식에 맞게 입력해주세요.");
return;
}

navigate("/signup/code", {state: {email: signupInfo.email}});
setLoading(true);

sendMail(email)
.then(() => {
navigate("/signup/code", {state: {email: email}});
})
.catch((error) => alert(error.response.data.message))
.finally(() => setLoading(false));
}

return (
Expand All @@ -37,11 +46,12 @@ function EmailPage() {
label={"이메일"}
type={"email"}
placeholder={"diglog@example.com"}
value={signupInfo.email}
setValue={(value) => setSignupInfo({...signupInfo, email: value})}
value={email}
setValue={(value) => setEmail(value)}
onKeyDown={handleEmailEnter}/>
<LoginButton text={"인증코드 전송"} onClick={handleVerifyEmail} bgColor={"bg-lime-400"}/>
<LoginButton text={"인증코드 전송"} onClick={handleVerifyEmail} disable={!checkEmail(email)} bgColor={"bg-lime-400"}/>
</div>
<LoadingLayout loading={loading}/>
</BasicLayout>
);
}
Expand Down
32 changes: 22 additions & 10 deletions src/pages/member/SignupPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {checkPassword} from "../../common/util/regex.tsx";
import LoadingLayout from "../../layout/LoadingLayout.tsx";
import * as React from "react";
import LoginButton from "../../components/member/LoginButton.tsx";
import {signup} from "../../common/apis/member.tsx";

function SignupPage() {

Expand All @@ -25,17 +26,29 @@ function SignupPage() {
}

const handleSignup = () => {
setLoading(true);
console.log(email, code);

if (!checkPassword(passwordInfo.password) || passwordInfo.password !== passwordInfo.confirmPassword) {
setLoading(false);
if (!checkPassword(passwordInfo.password)) {
alert("비밀번호가 영문, 숫자 포함 8-16자리가 되도록 입력해주세요.");
return;
}

if (passwordInfo.password !== passwordInfo.confirmPassword) {
alert("비밀번호 확인이 일치하지 않습니다.");
return;
}

alert("회원가입 되었습니다.");
setLoading(true);

signup(email, passwordInfo.password, code)
.then(() => {
alert("회원가입 되었습니다.");
navigate("/login");
})
.catch((error) => alert(error.response.data.message))
.finally(() => setLoading(false));
}

navigate("/login");
const disableSignupButton = () => {
return !checkPassword(passwordInfo.password) || (passwordInfo.password !== passwordInfo.confirmPassword);
}

return (
Expand All @@ -58,12 +71,11 @@ function SignupPage() {
setValue={(value) => setPasswordInfo({...passwordInfo, confirmPassword: value})}
onKeyDown={handlePasswordEnter}/>
</div>
<LoginButton text={"회원가입"} onClick={handleSignup} bgColor={"bg-lime-400"}/>
<LoginButton text={"회원가입"} onClick={handleSignup} disable={disableSignupButton()} bgColor={"bg-lime-400"}/>
</div>
<LoadingLayout loading={loading}/>
</BasicLayout>
)
;
);
}

export default SignupPage;
20 changes: 14 additions & 6 deletions src/pages/setting/ProfileSettingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import {ChangeEvent, useRef, useState} from "react";
import {FillButton} from "../../components/common/FillButton.tsx";
import {setUsername} from "../../common/slices/loginSlice.tsx";
import {TextButton} from "../../components/common/TextButton.tsx";
import {updateUsername} from "../../common/apis/member.tsx";

function ProfileSettingPage() {

const loginState = useSelector((state: RootState) => state.loginSlice);
const dispatch = useDispatch();
const fileInputRef = useRef<HTMLInputElement>(null);

const [input, setInput] = useState("");
const [input, setInput] = useState(loginState.username);
const [image, setImage] = useState<string | null>(null);
const [isUsernameEdit, setIsUsernameEdit] = useState(false);
const [isImageEdit, setIsImageEdit] = useState(false);
Expand All @@ -27,11 +28,18 @@ function ProfileSettingPage() {
}

const handleUsernameSubmit = () => {
alert("변경되었습니다.");
dispatch(setUsername({
username: input,
}));
setIsUsernameEdit(false);

updateUsername(input)
.then(() => {
alert("변경되었습니다.");
dispatch(setUsername({
username: input,
}));
setIsUsernameEdit(false);
})
.catch((error) => alert(error.response.data.message))
.finally(() => {
});
}

const handleImageEdit = () => {
Expand Down