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: 로그인/회원가입 구현 #75

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9ce4f27
feat: 공통 레이아웃 추가
21ow Jan 4, 2025
66137a4
feat: 로그인 정보 저장 스토리지 변경
21ow Jan 4, 2025
ffc2447
feat: 로그인 페이지 기본 구조 및 스타일링 추가
21ow Jan 4, 2025
77c1096
feat: 루트 페이지 임시 레이아웃 추가
21ow Jan 4, 2025
f0ec89e
chore: 로그인 페이지 파일명 변경
21ow Jan 4, 2025
f90acbb
chore: 임시 리다이렉트 경로 추가
21ow Jan 4, 2025
43971ca
chore: 전역 컬러 및 언어 추가
21ow Jan 4, 2025
950dada
chore: UI 디자인 수정
21ow Jan 4, 2025
fc530dc
chore: 타입 수정 및 조건부 렌더링 추가
21ow Jan 4, 2025
c0b7e1d
chore: Button으로 수정
21ow Jan 4, 2025
f6cc5af
chore: 경로 수정 및 스타일 추가
21ow Jan 4, 2025
b068aa6
chore: UI 디자인 수정
21ow Jan 4, 2025
3783565
chore: 리액트 쿼리 데브툴 추가
21ow Jan 4, 2025
ebf4ba1
feat: form 기본 스타일 함수 추가
21ow Jan 4, 2025
2d1c873
chore: 코드 위치 수정
21ow Jan 4, 2025
abef39a
feat: 컨텐츠 최소 너비 추가
21ow Jan 4, 2025
df4035d
feat: 로그인/회원가입 페이지 반응형 디자인 추가
21ow Jan 4, 2025
5d1ac33
refactor: 반응형 분기점 모듈화 및 리팩토링
21ow Jan 5, 2025
b502828
chore: 불필요 코드 제거 및 레이아웃 재배치
21ow Jan 5, 2025
a4e3151
refactor: 불필요 중복 스타일링 제거
21ow Jan 5, 2025
49c7aac
chore: svg 커스텀 스타일링 속성 추가
21ow Jan 6, 2025
7caa3e2
chore: 아이디 계정 코멘트 수정
21ow Jan 6, 2025
d8fb4b8
feat: 버튼 hover 스타일 추가
21ow Jan 6, 2025
af0840c
style: fill 속성값 수정
21ow Jan 6, 2025
55113a6
style: input 내 아이콘 padding 수정
21ow Jan 6, 2025
85aa7b2
style: fill 속성 제거
21ow Jan 6, 2025
f2b4025
chore: 폴더 구조 재구성
21ow Jan 6, 2025
3c0b790
Merge branch 'develop' into feature/auth-v1
21ow Jan 6, 2025
3217aed
chore: api 로직 수정 및 파일명 변경
21ow Jan 8, 2025
b071e3a
chore: 컴포넌트 및 경로 수정
21ow Jan 8, 2025
067304a
Merge branch 'develop' into feature/auth-v1
21ow Jan 8, 2025
24c784e
Merge branch 'develop' into feature/auth-v1
21ow Jan 9, 2025
55dba29
fix: 버전 충돌 해결
21ow Jan 9, 2025
c926361
chore: 불필요 layout 파일 삭제
21ow Jan 9, 2025
9cf1543
refactor: createMutations 로직 제거 및 수정
21ow Jan 9, 2025
de49856
style: 중앙정렬 추가
21ow Jan 9, 2025
1136a67
chore: 컴포넌트, 파일명 변경 및 경로 수정
21ow Jan 9, 2025
9d6e95e
chore: 컴포넌트, 파일명 변경 및 경로 수정
21ow Jan 9, 2025
dc22f81
chore: 프리빌트 바이너리 업데이트
21ow Jan 9, 2025
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
351 changes: 134 additions & 217 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@
"@eslint/eslintrc": "^3.2.0",
"@mui/material": "^6.2.0",
"@svgr/webpack": "^8.1.0",
"@tanstack/react-query": "^5.63.0",
"@tanstack/react-query": "^5.62.11",
"@tanstack/react-query-devtools": "^5.62.14",
"axios": "^1.7.9",
"classnames": "^2.5.1",
"next": "15.0.3",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-hook-form": "^7.54.1",
"react-merge-refs": "^2.1.1",
"react-query": "^3.39.3",
"sass": "^1.83.0",
"vercel": "^39.2.2",
"zustand": "^5.0.2"
Expand Down
2 changes: 2 additions & 0 deletions public/icon/ic-add-item.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions public/icon/ic-compare.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions public/icon/ic-search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/app/auth/signin/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import SignIn from '@/feature/auth/signin/SignIn';

const SignInPage = () => {
return <SignIn />;
};

export default SignInPage;
7 changes: 7 additions & 0 deletions src/app/auth/signup/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import SignUp from '@/feature/auth/signup/SignUp';

const SignUpPage = () => {
return <SignUp />;
};

export default SignUpPage;
3 changes: 3 additions & 0 deletions src/app/globals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
body {
font-family: Pretendard;
background-color: $black-450;
color: $white;
min-width: 375px;
height: 100vh;
}
26 changes: 19 additions & 7 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
import type { Metadata } from 'next';
import './globals.scss';
'use client';

export const metadata: Metadata = {
title: 'Mogazoa',
};
import Head from 'next/head';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import './globals.scss';

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const queryClient = new QueryClient();

return (
<html lang="kr">
<body>{children}</body>
<html lang="ko">
<Head>
<title>Mogazoa</title>
<meta name="description" content="Mogazoa application" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<body>
<QueryClientProvider client={queryClient}>
{children}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
</body>
</html>
);
}
41 changes: 35 additions & 6 deletions src/asset/variables.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
$black-500: #17171c; //dard
$black-450: #1c1c22; //배경
$black-500: #17171c;
$black-450: #1c1c22;
$black-400: #181d26;
$black-350: #252530;
$black-300: #2e2e3a; //light
$black-200: #353542; //mood
$black-300: #2e2e3a;
$black-200: #353542;

$dark-gray: #6e6e82;
$gray: #9fa6b2;
Expand Down Expand Up @@ -31,7 +31,7 @@ $border-blue: 1px solid $blue;

$pad-input: 20px;
$pad-button: 24px 288px;
$pad-search: 16px 20px 16px 64px;
$pad-search: 16px 20px 16px 44px;
$pad-menu: 15px 20px;
$pad-category: 4px 10px;
$pad-category-small: 4px 8px;
Expand All @@ -46,7 +46,7 @@ $pad-statistics: 30px 74px;
$right: auto,
$transform: none,
$color: $dark-gray,
$background-color: $black-350
$background-color: inherit
) {
position: $position;
top: $top;
Expand All @@ -57,3 +57,32 @@ $pad-statistics: 30px 74px;
color: $color;
background-color: $background-color;
}

@mixin form-style(
$width: 100%,
$display: grid,
$grid-template-columns: none,
$column-gap: 0,
$grid-template-rows: none,
$row-gap: 0
) {
width: $width;
display: $display;
grid-template-columns: $grid-template-columns;
column-gap: $column-gap;
grid-template-rows: $grid-template-rows;
row-gap: $row-gap;
column-gap: $column-gap;
}

@mixin tablet {
@media (max-width: 1199px) {
@content;
}
}

@mixin mobile {
@media (max-width: 767px) {
@content;
}
}
13 changes: 13 additions & 0 deletions src/feature/auth/component/SocialSiginin.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@use '@/shared/button/Button.module.scss' as button;

.socialButton {
@include button.button-style(
$background: $black-450,
$border: $border-black,
$radius: $radius-rank,
$width: 56px,
$height: 56px,
$padding: 0
);
display: flex;
}
18 changes: 18 additions & 0 deletions src/feature/auth/component/SocialSignin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Image from 'next/image';
import Button from '@/shared/button/Button';
import styles from './SocialSiginIn.module.scss';

type SocialSignInProps = {
src: string;
social: string;
};

const SocialSignIn = ({ src, social }: SocialSignInProps) => {
return (
<Button className={styles.socialButton}>
<Image src={src} width={28} height={28} alt={`${social} 간편로그인`} />
</Button>
);
};

export default SocialSignIn;
73 changes: 73 additions & 0 deletions src/feature/auth/signin/Signin.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
@use '@/shared/button/Button.module.scss' as button;

.signInWrapper {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20px;
}

.form {
@include form-style(
$width: 640px,
$grid-template-rows: repeat(3, auto),
$row-gap: 40px
);

@include tablet {
width: 440px;
}

@include mobile {
width: 335px;
row-gap: 30px;
}
}

.submitButton {
@include button.button-style(
$width: 100%,
$height: 65px,
$font-weight: 600,
$font-size: 18px,
$background: linear-gradient(90deg, #5097fa, #5363ff),
$padding: 0
);

&:hover {
background: linear-gradient(90deg, #3a7bc7, #3c50e0);
}

@include tablet {
height: 55px;
font-size: 16px;
}
}

.accountActions {
display: flex;
gap: 20px;
color: $gray;
font-size: 13px;
}

.socialSignIn {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
margin-top: 15px;
}

.socialTitle {
color: $dark-gray;
font-size: 12px;
font-weight: 400;
}

.socialWrapper {
display: flex;
gap: 20px;
}
89 changes: 89 additions & 0 deletions src/feature/auth/signin/Signin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use client';

import { useForm, SubmitHandler } from 'react-hook-form';
import { useRouter } from 'next/navigation';
import { useMutation } from '@tanstack/react-query';
import { AuthResponse, SignInRequest } from '@/api/type/Auth';
import axiosInstance from '@/lib/axiosInstance';
import { AxiosError } from 'axios';
import Input from '@/shared/Input/Input';
import Button from '@/shared/button/Button';
import SocialSignIn from '../component/SocialSignIn';
import Link from 'next/link';
import styles from './SignIn.module.scss';

const SignIn = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<SignInRequest>();

const router = useRouter();

const { mutate } = useMutation<AuthResponse, AxiosError, SignInRequest>({
mutationFn: (data) => axiosInstance.post(`/auth/signIn`, data),
onSuccess: (response) => {
localStorage.setItem('signInToken', response.accessToken);
router.push('/'); //임시
},
onError: (error: AxiosError) => {
const message = (error.response?.data as { message: string })?.message;
console.error(message);
},
});

const onSubmit: SubmitHandler<SignInRequest> = (data) => {
mutate(data);
};

return (
<div className={styles.signInWrapper}>
<form onSubmit={handleSubmit(onSubmit)} className={styles.form}>
<Input
label="이메일"
placeholder="이메일을 입력해 주세요"
autoComplete="username"
formErrorMessage={errors.email?.message}
{...register('email', {
required: '이메일을 입력해주세요.',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
message: '유효한 이메일을 입력해주세요.',
},
})}
/>
<Input
type="password"
label="비밀번호"
placeholder="비밀번호를 입력해 주세요"
autoComplete="current-password"
formErrorMessage={errors.password?.message}
{...register('password', {
required: '비밀번호를 입력해주세요.',
minLength: {
value: 8,
message: '최소 8자 이상',
},
})}
/>
<Button type="submit" className={styles.submitButton}>
로그인
</Button>
</form>
<div className={styles.accountActions}>
<Link href="#">비밀번호 재설정</Link>
<Link href="/auth/signup">회원가입</Link>
</div>
<div className={styles.socialSignIn}>
<div className={styles.socialTitle}>SNS로 바로 시작하기</div>
<div className={styles.socialWrapper}>
<SocialSignIn src={'/icon/ic-google.svg'} social="구글" />
<SocialSignIn src={'/icon/ic-kakaotalk.svg'} social="카카오톡" />
</div>
</div>
</div>
);
};

export default SignIn;
Loading
Loading