Skip to content

Commit

Permalink
Merge pull request #60 from team-Ollie/17-feature-Signup-API
Browse files Browse the repository at this point in the history
[feature] signup validation
  • Loading branch information
leejin-rho authored Jul 4, 2024
2 parents db68fa5 + 0faad91 commit c48ad8a
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 92 deletions.
15 changes: 15 additions & 0 deletions apis/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,18 @@ export const getCenterList = async () => {
throw error;
}
};

interface IdCheckResponseBody {
timestamp: string;
status: number;
error: string;
code: string;
message: string;
}

async function postIdCheck(loginId: string): Promise<IdCheckResponseBody> {
const { data } = await client.post(`/users/loginId`, { loginId });
return data;
}

export { postIdCheck };
21 changes: 19 additions & 2 deletions apis/hooks/auth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useQuery, useMutation } from "@tanstack/react-query";
import { SignUp, getCenterList, userProps } from "../auth";
import { SignUp, getCenterList, postIdCheck, userProps } from "../auth";
import { useRouter } from "next/router";
import { InputError } from "@/pages/mypage/password";

function useGetCenterList() {
const { data } = useQuery({
Expand Down Expand Up @@ -28,4 +29,20 @@ function useSignUp(userData: userProps) {
return { mutate };
}

export { useGetCenterList, useSignUp };
function usePostIdCheck(
loginId: string,
setIdError: React.Dispatch<React.SetStateAction<InputError>>,
) {
const { mutate } = useMutation({
mutationKey: ["postIdCheck", loginId],
mutationFn: () => postIdCheck(loginId),
onSuccess: () => setIdError({ status: false, text: "" }),
onError: () => {
setIdError({ status: true, text: "이미 사용 중인 아이디입니다." });
},
});

return { mutate };
}

export { useGetCenterList, useSignUp, usePostIdCheck };
18 changes: 11 additions & 7 deletions components/auth/AuthInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface TextInputProps {
name: string;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
maxLength?: number;
isSuccess?: boolean;
}

const AuthInput = forwardRef<HTMLInputElement, TextInputProps>(
Expand All @@ -24,20 +25,23 @@ const AuthInput = forwardRef<HTMLInputElement, TextInputProps>(
name,
onChange,
maxLength = 10,
isSuccess = false,
},
ref,
) => {
const borderStyle = () => {
if (isSuccess) return "border-green-600";
else if (isError) return "border-red-500";
return "border-solid";
};

return (
<div className="w-full relative">
<div
className={`${className} rounded-xl border border-solid ${
isError ? "border-red-500" : "border-semantic-grey-2"
} rounded-lg p-2`}
>
<div className={`${className} border ${borderStyle()} rounded-xl p-2`}>
<input
type={type}
name={name}
className="w-full outline-none border-none h4 placeholder:text-grey-400 pl-1"
className="w-full outline-none border-none h4 leading-normal placeholder:text-grey-400 pl-1"
value={value}
onChange={onChange}
placeholder={placeholder}
Expand All @@ -46,7 +50,7 @@ const AuthInput = forwardRef<HTMLInputElement, TextInputProps>(
/>
</div>
{isError && (
<div className="text-red-500 h5 px-2 absolute">{errorText}</div>
<div className="text-red-500 h6 px-2 absolute">{errorText}</div>
)}
</div>
);
Expand Down
231 changes: 150 additions & 81 deletions pages/signup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { centerProps, userProps } from "@/apis/auth";
import { useGetCenterList, useSignUp } from "@/apis/hooks/auth";
import { useGetCenterList, usePostIdCheck, useSignUp } from "@/apis/hooks/auth";
import Button from "@/components/Button";
import HeadFunction from "@/components/HeadFunction";
import AuthInput from "@/components/auth/AuthInput";
Expand All @@ -12,6 +12,7 @@ import CheckIcon from "@/public/svgs/Check.svg";
import FlexBox from "@/components/Flexbox";
import { usePostNicknameCheck } from "@/apis/hooks/mypage";
import { InputError } from "./mypage/password";
import NicknameInput from "@/components/mypage/NicknameInput";

const SignUp: NextPage = () => {
//input용
Expand Down Expand Up @@ -49,6 +50,8 @@ const SignUp: NextPage = () => {
const { mutate: signUpMutate } = useSignUp(userInfo);

//중복 확인
//닉네임 중복
const [tempName, setTempName] = useState<string>("");
const [nameError, setNameError] = useState<InputError>({
status: false,
text: "",
Expand All @@ -58,7 +61,6 @@ const SignUp: NextPage = () => {
if (checkNicknameValidity()) nameCheckMutate();
};

const [tempName, setTempName] = useState<string>("");
const checkNicknameValidity = () => {
setTempName(userInfo.nickname);
if (userInfo.nickname.length > 8) {
Expand Down Expand Up @@ -86,100 +88,167 @@ const SignUp: NextPage = () => {
setNameError,
);

//아이디 중복
const [tempId, setTempId] = useState<string>("");
const [idError, setIdError] = useState<InputError>({
status: false,
text: "",
});

const checkIdValidity = () => {
setTempId(userInfo.loginId);
if (userInfo.loginId.length > 16) {
setIdError({
status: true,
text: "아이디 최대 길이는 16자입니다.",
});
return false;
}

const regex = /^[a-zA-Z0-9\s]*$/;
if (!regex.test(userInfo.loginId)) {
setIdError({
status: true,
text: "아이디는 영어, 숫자로만 구성할 수 있습니다.",
});
return false;
}

return true;
};

const { mutate: idCheckMutate } = usePostIdCheck(
userInfo.loginId,
setIdError,
);

const onClickIdBtn = () => {
if (checkIdValidity()) idCheckMutate();
};

return (
<div className="flex flex-col w-full h-screen items-center">
<div className="flex flex-col w-screen h-screen items-center">
<HeadFunction title="회원가입" />
<form
onSubmit={onSubmit}
className="h-screen w-full items-center flex flex-col gap-9 overflow-auto scrollbar-hide mt-5"
>
<div className="flex flex-col gap-3">
<TextLine children={"아이디"} className="pl-1" />
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-2">
<TextLine children={"아이디"} className="pl-1" />

<FlexBox className="w-full gap-2">
<AuthInput
placeholder="아이디를 입력하세요"
name="loginId"
ref={idInputRef}
value={userInfo.loginId}
onChange={onChange}
maxLength={16}
className="flex-grow"
isSuccess={
!(
tempId.length === 0 ||
idError.status ||
userInfo.loginId.length === 0
)
}
isError={idError.status}
errorText={idError.text}
/>
<button
className="shrink-0 px-3 py-2.5 border border-main-color text-main-color rounded-lg h5"
onClick={(e) => {
e.preventDefault();
onClickIdBtn();
}}
>
중복
</button>
</FlexBox>
</div>

<div className="flex flex-col gap-2">
<TextLine children={"비밀번호"} className="pl-1" />

<FlexBox className="w-full gap-2">
<AuthInput
placeholder="아이디를 입력하세요"
name="loginId"
ref={idInputRef}
value={userInfo.loginId}
placeholder="비밀번호를 입력하세요"
name="password"
ref={pwInputRef}
value={userInfo.password}
onChange={onChange}
maxLength={16}
className="flex-grow"
className={"w-[19.5rem]"}
/>
{/* <button
className="shrink-0 px-3 py-2.5 border border-main-color text-main-color rounded-lg h5"
onClick={(e) => {
e.preventDefault();
}}
>
중복
</button> */}
</FlexBox>

<TextLine children={"비밀번호"} className="pl-1" />

<AuthInput
placeholder="비밀번호를 입력하세요"
name="password"
ref={pwInputRef}
value={userInfo.password}
onChange={onChange}
className={"w-[19.5rem]"}
/>
</div>

<TextLine children={"닉네임"} className="pl-1" />
<FlexBox className="w-full gap-2">
<div className="flex flex-col gap-2">
<TextLine children={"닉네임"} className="pl-1" />
<FlexBox className="w-full gap-2">
<AuthInput
placeholder="한글, 영어, 숫자 포함 최대 8자"
name="nickname"
ref={nicknameInputRef}
value={userInfo.nickname}
onChange={onChange}
maxLength={8}
className="flex-grow"
isSuccess={
!(
tempName.length === 0 ||
nameError.status ||
userInfo.nickname.length === 0
)
}
isError={nameError.status}
errorText={nameError.text}
/>

<button
className="shrink-0 px-3 py-2.5 border border-main-color text-main-color rounded-lg h5"
onClick={(e) => {
e.preventDefault();
onClickCheckBtn();
}}
>
중복
</button>
</FlexBox>
</div>

<div className="flex flex-col gap-2">
<TextLine children={"식별번호"} className="pl-1" />
<AuthInput
placeholder="한글, 영어, 숫자 포함 최대 8자"
name="nickname"
ref={nicknameInputRef}
value={userInfo.nickname}
placeholder="이름과 전화번호 뒷자리 4개를 입력해주세요."
name="identifier"
ref={idfInputRef}
value={userInfo.identifier}
maxLength={10}
onChange={onChange}
maxLength={8}
className="flex-grow"
className={"w-[19.5rem]"}
/>
{/* <button
className="shrink-0 px-3 py-2.5 border border-main-color text-main-color rounded-lg h5"
onClick={(e) => {
e.preventDefault();
onClickCheckBtn();
}}
>
중복
</button> */}
</FlexBox>

<TextLine children={"식별번호"} className="pl-1" />

<AuthInput
placeholder="이름과 전화번호 뒷자리 4개를 입력해주세요."
name="identifier"
ref={idfInputRef}
value={userInfo.identifier}
maxLength={10}
onChange={onChange}
className={"w-[19.5rem]"}
/>
</div>

<TextLine children={"소속센터"} className="pl-1" />
{data && (
<select
className="border h-9 rounded-xl px-2"
value={userInfo.centerIdx}
onChange={(e) =>
setUserInfo({
...userInfo,
centerIdx: parseInt(e.target.value, 10),
})
}
>
{data.map((center: centerProps) => (
<option key={center.centerIdx} value={center.centerIdx}>
{center.name}
</option>
))}
</select>
)}
<div className="flex flex-col gap-2">
<TextLine children={"소속센터"} className="pl-1" />
{data && (
<select
className="border h-9 rounded-xl px-2"
value={userInfo.centerIdx}
onChange={(e) =>
setUserInfo({
...userInfo,
centerIdx: parseInt(e.target.value, 10),
})
}
>
{data.map((center: centerProps) => (
<option key={center.centerIdx} value={center.centerIdx}>
{center.name}
</option>
))}
</select>
)}
</div>
</div>
<button type="submit" className="w-[20rem] absolute bottom-[3.75rem]">
<Button
Expand Down
4 changes: 2 additions & 2 deletions pages/success.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const SignupSuccess: NextPage = () => {
});

return (
<div className="w-full h-full flex flex justify-center items-center">
<div className="w-screen h-screen flex flex justify-center items-center">
<FlexBox
direction="col"
className="w-[90%] h-full items-center justify-center"
Expand All @@ -31,7 +31,7 @@ const SignupSuccess: NextPage = () => {
<Button
text="로그인하러 가기"
style="bg-main-100 text-grey-900"
onClick={() => router.push("/login")}
onClick={() => router.push("/main")}
/>
</FlexBox>
</div>
Expand Down

0 comments on commit c48ad8a

Please sign in to comment.