Skip to content
Open
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
260 changes: 260 additions & 0 deletions components/Oauth2/SocialSignupForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
import "react-datepicker/dist/react-datepicker.css";

import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form";

import DatePickerInput from "@/components/Form/Input/DatePickerInput";
import ImageUpload from "@/components/Form/Input/ImageUploadInput";
import IntroTextarea from "@/components/Form/Input/IntroTextarea";
import RadioInput from "@/components/Form/Input/RadioInput";
import TagInput from "@/components/Form/Input/TagInput";
import Modal from "@/components/Modal";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import axios from "@/lib/api/axios";

interface SignUp {
bio?: string;
confirmPassword: string;
dayOfBirth: string;
favoriteSpots?: string[];
gender: "MALE" | "FEMALE";
nickname: string;
password: string;
profile?: string;
}

function SocialSignUpForm() {
const {
register,
handleSubmit,
control,
formState: { errors, isValid },
watch,
} = useForm<SignUp>({ mode: "onBlur" });

const router = useRouter();

const [isModalOpen, setIsModalOpen] = useState(false);
const [isCheckEmailModalOpen, setIsCheckEmailModalOpen] = useState(false);

const [oauthEmail, setOauthEmail] = useState("[email protected]");

const onSubmit = async (data: SignUp) => {
const formData = new FormData();

const { confirmPassword, profile, ...submitData } = data;
formData.append(
"request",
new Blob([JSON.stringify(submitData)], { type: "application/json" }),
);

if (data.profile) {
formData.append("profile", data.profile);
}

try {
const res = await axios.post("/oauth2/signup", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
setIsModalOpen(true);
} catch (error) {
console.error("회원가입 실패:", error);
}
};

const handleFormSubmit = (data: SignUp) => {
onSubmit(data);
};

const getOauthEmail = async () => {
try {
const response = await axios.get("/oauth2/signup", {
baseURL: "http://mylittleforest.shop:8080",
});
console.log(response);
setOauthEmail(response.data.email);
console.log("oauth2 이메일 조회 성공! ", response.data);
} catch (error) {
console.error("oauth2 이메일 조회 실패", error);
}
};

useEffect(() => {
getOauthEmail();
}, []);

return (
<>
<form onSubmit={handleSubmit(handleFormSubmit)}>
<div className="flex w-[956px] flex-col items-center rounded-32 bg-white px-32 py-48 tablet:w-[720px] mobile:w-[312px]">
<div className="mb-40 flex items-center gap-32 tablet:gap-28">
<div className="h-px w-294 bg-line-02 tablet:w-248 mobile:w-52"></div>
<div className="text-18 tablet:text-16 mobile:text-14">
필수 정보 입력
</div>
<div className="h-px w-294 bg-line-02 tablet:w-248 mobile:w-52"></div>
</div>
<div className="flex flex-col gap-24">
<div className="flex flex-col gap-8">
<Label htmlFor="email">이메일</Label>
<Input
id="email"
type="email"
className={`h-52 w-[756px] rounded-2xl border border-line-02 bg-bg-02 px-16 placeholder:text-text-05 focus:border focus:border-line-01 focus:bg-white focus-visible:ring-0 focus-visible:ring-offset-0 tablet:w-[672px] mobile:w-272 mobile:text-sm `}
placeholder={oauthEmail}
disabled
/>
</div>
<div className="flex flex-col gap-8">
<Label htmlFor="nickname">
닉네임<span className="text-pink-500">*</span>
</Label>
<Input
id="nickname"
type="text"
className={`h-52 w-[756px] rounded-2xl border border-line-02 bg-bg-02 px-16 placeholder:text-text-05 focus:border focus:border-line-01 focus:bg-white focus-visible:ring-0 focus-visible:ring-offset-0 tablet:w-[672px] mobile:w-272 mobile:text-sm ${errors.nickname && "border-0 bg-input-error"}`}
placeholder="닉네임을 입력해 주세요"
{...register("nickname", {
required: true,
minLength: 2,
maxLength: 8,
})}
/>
{errors.nickname && errors.nickname.type === "required" && (
<span className="text-12 text-system-error">
닉네임을 입력해 주세요
</span>
)}
{errors.nickname && errors.nickname.type === "minLength" && (
<span className="text-12 text-system-error">
닉네임은 최소 2글자 입니다
</span>
)}
{errors.nickname && errors.nickname.type === "maxLength" && (
<span className="text-12 text-system-error">
닉네임은 최대 8글자 입니다
</span>
)}
</div>

<div className="flex flex-col gap-8">
<Label htmlFor="gender">
성별<span className="text-pink-500">*</span>
</Label>
<Controller
control={control}
name="gender"
rules={{ required: true }}
render={({ field }) => (
<RadioInput
onChange={(gender: any) => field.onChange(gender)}
value={field.value}
pageType="singUp"
id={"gender"}
/>
)}
/>
</div>
<div className="flex flex-col gap-8">
<Label htmlFor="date">
생년월일<span className="text-pink-500">*</span>
</Label>
<Controller
control={control}
name="dayOfBirth"
rules={{ required: true }}
render={({ field }) => (
<DatePickerInput
onChange={(date: any) => field.onChange(date)}
value={field.value}
id={"date"}
/>
)}
/>
</div>
</div>
<div className="my-40 flex items-center gap-32 tablet:gap-28">
<div className="h-px w-294 bg-line-02 tablet:w-248 mobile:w-52"></div>
<div className="text-18 tablet:text-16 mobile:text-14">
추가 정보 입력
</div>
<div className="h-px w-294 bg-line-02 tablet:w-248 mobile:w-52"></div>
</div>
<div className="flex flex-col items-center gap-24">
<Controller
control={control}
name="profile"
render={({ field }) => (
<ImageUpload
onChange={profile => field.onChange(profile)}
value={field.value ?? ""}
/>
)}
/>
<div className="flex flex-col gap-8">
<Label htmlFor="tags">좋아하는 여행지</Label>
<Controller
control={control}
name="favoriteSpots"
render={({ field }) => (
<TagInput
onChange={(tags: any) => field.onChange(tags)}
value={field.value}
formType={"signUp"}
id={"tags"}
/>
)}
/>
</div>
<div className="flex flex-col gap-8">
<Label htmlFor="bio">자기소개</Label>
<Controller
control={control}
name="bio"
render={({ field }) => (
<IntroTextarea
onChange={text => field.onChange(text)}
value={field.value ?? ""}
id={"bio"}
/>
)}
/>
</div>
</div>
</div>
<div className="mt-40 flex w-[956px] flex-col items-center rounded-32 tablet:w-[720px] mobile:w-[312px]">
<button
type="submit"
disabled={!isValid}
className="flex h-52 w-240 items-center justify-center rounded-32 bg-primary text-white hover:bg-primary-press disabled:bg-line-02 disabled:text-text-04 mobile:h-44 mobile:w-180"
>
가입하기
</button>
</div>
</form>
{isModalOpen && (
<Modal
modalType="signupSuccess"
onClose={() => {
setIsModalOpen(false);
router.push("/login");
}}
/>
)}
{isCheckEmailModalOpen && (
<Modal
modalType="emailInUse"
onClose={() => {
setIsCheckEmailModalOpen(false);
}}
/>
)}
</>
);
}

export default SocialSignUpForm;
16 changes: 12 additions & 4 deletions components/Travel/Contents/CardGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ interface itemType {
export interface CardData {
content: itemType[];
totalPages: number;
first: boolean;
last: boolean;
numberOfElements: number;
}

Expand Down Expand Up @@ -140,7 +142,7 @@ function CardGrid() {

<div className="m-auto flex w-max items-center gap-3">
<div
className="relative h-24 w-24 cursor-pointer"
className={`relative h-24 w-24 ${!card?.first && "cursor-pointer"}`}
onClick={() => firstLastPage(0)}
>
<Image
Expand All @@ -150,7 +152,10 @@ function CardGrid() {
sizes="24px"
/>
</div>
<div className="relative h-24 w-24 cursor-pointer" onClick={prevPage}>
<div
className={`relative h-24 w-24 ${!card?.first && "cursor-pointer"}`}
onClick={prevPage}
>
<Image
src={"/icons/keyboard_arrow_left.svg"}
alt="이전페이지"
Expand Down Expand Up @@ -180,7 +185,10 @@ function CardGrid() {
) : null;
})}
</div>
<div className="relative h-24 w-24 cursor-pointer" onClick={nextPage}>
<div
className={`relative h-24 w-24 ${!card?.last && "cursor-pointer"}`}
onClick={nextPage}
>
<Image
src={"/icons/keyboard_arrow_right.svg"}
alt="다음페이지"
Expand All @@ -189,7 +197,7 @@ function CardGrid() {
/>
</div>
<div
className="relative h-24 w-24 cursor-pointer"
className={`relative h-24 w-24 ${!card?.last && "cursor-pointer"}`}
onClick={() => firstLastPage(Number(card?.totalPages) - 1)}
>
<Image
Expand Down
8 changes: 6 additions & 2 deletions pages/login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ export default function Login() {

<div className="flex w-full items-center justify-between gap-20 text-18 mobile:text-16">
<Link
href={"http://3.38.76.39:8080/oauth2/authorization/kakao"}
href={
"http://mylittleforest.shop:8080/oauth2/authorization/kakao"
}
className="w-1/2"
>
<Button
Expand All @@ -191,7 +193,9 @@ export default function Login() {
</Link>

<Link
href={"http://3.38.76.39:8080/oauth2/authorization/google"}
href={
"http://mylittleforest.shop:8080/oauth2/authorization/google"
}
className="w-1/2"
>
<Button
Expand Down
2 changes: 1 addition & 1 deletion pages/oauth2/signup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import SocialSignUpForm from "@/components/Form/SocialSignupForm";
import SocialSignUpForm from "@/components/Oauth2/SocialSignupForm";

export default function Oauth2Signup() {
return (
Expand Down