OLD/ChatLink
[ChatLink] Frontend: NextJs v14 - shadcn을 이용한 로그인 / 회원가입 폼 구현
joseph0926
2024. 3. 9. 09:17
1. 사용 기술
- NextJs v14, Tailwind(shadcn-ui)
2. 프로젝트 구성
- 초기 next 프로젝트 설치
npx create-next-app@latest <프로젝트명>
- 필요 라이브러리 설치
npm i zod // 유효성 검사
// shadcn-ui
npx shadcn-ui@latest init
npx shadcn-ui@latest add input form
- 폴더 구조
src/
|-- app/
|-- layout.ts
|-- (root)/
|-- page.tsx
|-- layout.tsx
// 메인 레이아웃을 사용하는 페이지들
|-- sign/
|-- page.tsx
|-- layout.tsx
|-- api/
|-- components/
|-- auth/
|-- ui/
|-- lib/
|-- utils.ts
|-- uploadthing.ts
|-- schemas/
// 유효성 스키마
|-- types/
// 타입
|-- service/
// api 호출 로직
3. 회원가입 / 로그인 폼 구성
- 기본 아이디어
- 요구되는 값
- 회원가입: nickname, email, password, profileImage
- 로그인: email, password
- 로직 순서
- 유저 입력 -> 제출 -> 유효성 검사 -> 백엔드에 요청
- 서버 컴포넌트 / 클라이언트 컴포넌트
- 회원가입 / 로그인 폼을 감싸는 레이아웃 컴포넌트 <= 서버 컴포넌트
- 회원가입 / 로그인 폼 <= 클라이언트 컴포넌트
- 전환 아이디어
- url 쿼리 파라미터 (type = in | up)
- 구현 로직
"use client";
import Link from "next/link";
import { useForm } from "react-hook-form";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { signinSchema } from "@/schemas/signin.schema";
export default function SigninForm() {
const form = useForm<z.infer<typeof signinSchema>>({
defaultValues: {
email: "",
password: "",
},
resolver: zodResolver(signinSchema),
});
const submitHandler = async (values: z.infer<typeof signinSchema>) => {
console.log(values);
};
return (
<div className="w-full lg:w-1/2 p-8 flex flex-col items-center justify-center">
<h1 className="text-3xl font-bold mb-6">ChatLink</h1>
<Form {...form}>
<form
onSubmit={form.handleSubmit(submitHandler)}
className="flex flex-col gap-4 w-[60%]"
>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel className="text-lg font-bold">Email</FormLabel>
<FormControl>
<Input type="text" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel className="text-lg font-bold">Password</FormLabel>
<FormControl>
<Input type="text" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="flex items-center justify-between w-full mt-4">
<Link href="/sign?type=up">
아직 회원이 아니신가요?
<br />
<span className="text-indigo-400 font-semibold">회원가입</span>
으로 이동하기
</Link>
<Button variant="outline" className="bg-indigo-400 text-white">
로그인
</Button>
</div>
</form>
</Form>
</div>
);
}
[Github]