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

로그인 UI 변경 #168

Merged
merged 22 commits into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fc3f05e
[chore] login, profile Navigation 라우팅 변경
Im-younique Jun 3, 2024
692be84
[chore] 메인로고 컴포넌트 생성
Im-younique Jun 3, 2024
1758ea1
[feat] 로그인 폼 컴포넌트 분리 및 UI 수정
Im-younique Jun 3, 2024
d19fbeb
[feat] 비밀번호 보기 기능 추가
Im-younique Jun 3, 2024
dc2d6b2
[chore] 로그인 화면 UI 완성
Im-younique Jun 3, 2024
8eec5aa
[chore] 로그인 페이지 스타일 수정
Im-younique Jun 3, 2024
1a52150
[chore] 로그인 유지 default로 설정
Im-younique Jun 4, 2024
36fae78
[chore] 준비 중인 기능 모달 표시 추가
Im-younique Jun 4, 2024
00269fc
[feat] useClickAway Custom hook 추가
Im-younique Jun 5, 2024
0dbfa10
[chore] 불필요한 store 파일 제거
Im-younique Jun 6, 2024
9cda4d9
[chore] app-router 이전에 따른 next-redux-wrapper 패키지 제거
Im-younique Jun 6, 2024
81fc2db
[Add] redux-persist 패키지 추가
Im-younique Jun 7, 2024
29843a0
[feat] redux-persist 적용 (auth)
Im-younique Jun 7, 2024
3e1b4ca
[feat] Navigator 로그인 체크 로직 추가
Im-younique Jun 7, 2024
251738d
[fix] redux-persist 서버사이드 에러 제거
Im-younique Jun 7, 2024
00c45c7
[chore] 불필요한 async 함수 제거
Im-younique Jun 7, 2024
be95496
[chore] 비로그인시 네비게이터 수정
Im-younique Jun 7, 2024
403f02a
[feat] Dropdown 컴포넌트 생성
Im-younique Jun 7, 2024
251a475
[feat] ProfileButton내 Dropdown 적용
Im-younique Jun 7, 2024
beff118
[chore] 로그인 성공시 라우팅 수정
Im-younique Jun 8, 2024
2ef2507
[chore] useClickAwayRef로 네이밍 변경
Im-younique Jun 8, 2024
1dec392
[chore] useServerLoginCheck 코드 단순화
Im-younique Jun 8, 2024
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
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
"isomorphic-dompurify": "^2.2.0",
"lowlight": "^3.1.0",
"next": "^14.0.4",
"next-redux-wrapper": "^8.1.0",
"openai": "^4.8.0",
"postcss-nesting": "^12.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.11",
"react-redux": "^8.0.5",
"redux-persist": "^6.0.0",
"socketjs-client": "^1.0.2",
"tiptap-extension-resize-image": "^1.0.2",
"typescript": "5.0.2",
Expand Down
Binary file added client/public/images/check.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 9 additions & 2 deletions client/src/app/StoreProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import { useRef } from 'react';
import { Provider } from 'react-redux';
import { makeStore, AppStore, store } from '../lib/redux/store';
import { makeStore, AppStore, store, persistor } from '../lib/redux/store';
import { PersistGate } from 'redux-persist/integration/react';

export default function StoreProvider({
children,
Expand All @@ -15,5 +16,11 @@ export default function StoreProvider({
storeRef.current = makeStore();
}

return <Provider store={store}>{children}</Provider>;
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
{children}
</PersistGate>
</Provider>
);
}
34 changes: 34 additions & 0 deletions client/src/app/login/components/GithubLoginButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use client';

import { Icon } from '@iconify/react';

//hooks
import useModal from '@/hooks/modal/useModal';

//constant
import { errorMessage, ModalType } from '@/constants/constant';

export default function GithubLoginButton() {
const { openModal } = useModal();

return (
<div className="grid py-4">
<button
onClick={() =>
openModal({
type: ModalType.ERROR,
message: errorMessage.notComplete,
})
}
className="relative p-3 border border-gray-900 hover:bg-blue-gray-scale-100 active:bg-blue-gary-scale-100 disabled:bg-gray-scale-50 disabled:border-gray-800 disabled:text-blue-gray-600"
>
<Icon
className="absolute top-2 left-2"
icon="mdi:github"
fontSize={34}
/>
<span>깃허브로 로그인</span>
</button>
</div>
);
}
34 changes: 34 additions & 0 deletions client/src/app/login/components/GoogleLoginButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use client';

import { Icon } from '@iconify/react';

//hooks
import useModal from '@/hooks/modal/useModal';

//constant
import { errorMessage, ModalType } from '@/constants/constant';

export default function GoogleLoginButton() {
const { openModal } = useModal();

return (
<div className="grid py-4">
<button
onClick={() =>
openModal({
type: ModalType.ERROR,
message: errorMessage.notComplete,
})
}
className="relative p-3 border border-gray-900 hover:bg-blue-gray-scale-100 active:bg-blue-gary-scale-100 disabled:bg-gray-scale-50 disabled:border-gray-800 disabled:text-blue-gray-600"
>
<Icon
className="absolute top-2 left-2"
icon="devicon:google"
fontSize={34}
/>
<span>구글로 로그인</span>
</button>
</div>
);
}
188 changes: 188 additions & 0 deletions client/src/app/login/components/LoginForm/index.tsx
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아이디와 비밀번호로 로그인하는 폼을 컴포넌트로 분리하는게 낫다고 생각하여 분리하며 스타일 수정

Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
'use client';

import { useState, useCallback } from 'react';
import { useRouter } from 'next/navigation';

//redux
import { useDispatch, useSelector } from 'react-redux';
import { logIn } from '@/lib/redux/features/auth/authSlice';

//components
import { Tooltip } from '@/components';

//hooks
import useModal from '@/hooks/modal/useModal';

//icons
import { EyeOnIcon, EyeOffIcon } from '@/assets/Icon';

//formik
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';

//services
import { userManager } from '@/service/user';

//constant
import {
initialLoginValue,
errorMessage,
errorCodeToMessage,
ModalType,
} from '@/constants/constant';

//types
import { IReduxState } from '@/types/redux/IReduxState';

const ValidationSchema = Yup.object().shape({
userId: Yup.string().required(errorMessage.blankID),
password: Yup.string().required(errorMessage.blankPassword),
});

interface ILogin {
userId: string;
password: string;
}

export default function LoginForm() {
const [viewPassword, setViewPassword] = useState(false);

const dispatch = useDispatch();

const router = useRouter();

const modalState = useSelector((state: IReduxState) => state.modal);
const { openModal } = useModal();

const handleSubmit = useCallback(
async (sendData: ILogin, setSubmitting: (value: boolean) => void) => {
if (modalState.type === ModalType.CLOSE) {
setSubmitting(true);
try {
const userData = await userManager.loginUser({ data: sendData });
dispatch(logIn(userData));
router.replace(window.sessionStorage.getItem('previousURL') || '/');
} catch (error) {
if (error instanceof Error) {
type Code = 'USER_NOT_EXIST' | 'INVALID_PASSWORD';
openModal({
type: ModalType.ERROR,
message:
errorCodeToMessage[error.message as Code] || errorMessage.error,
});
} else {
openModal({
type: ModalType.ERROR,
message: errorMessage.error,
});
}
} finally {
setSubmitting(false);
}
}
},
[modalState]
);
return (
<Formik
initialValues={initialLoginValue}
validationSchema={ValidationSchema}
onSubmit={(data, { setSubmitting }) => handleSubmit(data, setSubmitting)}
>
{({ errors, touched, isSubmitting }) => (
<Form>
<div className="flex flex-col gap-5">
<div className="relative flex flex-col gap-3.5">
<label className="text-body3" htmlFor="user-id-input">
아이디
</label>
<Field
type="text"
name="userId"
id="user-id-input"
placeholder="아이디를 입력하세요."
className={`${
touched.userId && errors.userId && 'border-red-scale-600'
} border border-blue-gray-scale-50 py-[7px] px-4 text-body3 text-gray-scale-600 focus:outline-none`}
/>
<ErrorMessage
name="userId"
component="span"
className="absolute -bottom-4 left-2 text-caption1 text-red-scale-600"
/>
</div>
<div className="relative flex flex-col gap-3.5">
<label className="text-body3" htmlFor="password-input">
비밀번호
</label>
<div className="relative flex">
<Field
type={viewPassword ? 'text' : 'password'}
name="password"
id="password-input"
placeholder="비밀번호를 입력하세요."
autoComplete="on"
className={`${
touched.password &&
errors.password &&
'border-red-scale-600'
} flex-grow border border-blue-gray-scale-50 py-[7px] px-4 text-body3 text-gray-scale-600 focus:outline-none`}
/>
<div
className="absolute right-2 top-2 hover:cursor-pointer"
onClick={() => setViewPassword((prev) => !prev)}
>
{viewPassword ? <EyeOnIcon /> : <EyeOffIcon />}
</div>
</div>
<ErrorMessage
name="password"
component="span"
className="absolute -bottom-4 left-2 text-caption1 text-red-scale-600"
/>
</div>
</div>
<div className="flex justify-between my-6">
<Tooltip tooltipText="현재 로그인 유지만 지원합니다">
<div className="flex items-center gap-2">
<input
type="checkbox"
id="keep-logged-check"
className="border appearance-none size-[18px] border-gray-scale-500 checked:bg-black checked:bg-[url('/images/check.png')] checked:bg-no-repeat checked:bg-center hover:cursor-not-allowed"
checked={true}
disabled={true}
/>
<label
className="text-body3 text-gray-scale-600 hover:cursor-not-allowed"
htmlFor="keep-logged-check"
>
로그인 상태유지
</label>
</div>
</Tooltip>
<span
className="underline text-body3 text-blue-gray-scale-500 underline-offset-3 hover:cursor-pointer"
onClick={() =>
openModal({
type: ModalType.ERROR,
message: errorMessage.notComplete,
})
}
>
비밀번호 찾기
</span>
</div>
<div className="grid pt-2 pb-6 text-center">
<button
className="p-3 text-black bg-yellow-scale-400 hover:bg-yellow-scale-500 active:bg-yellow-scale-500 disabled:bg-yellow-scale-100 disabled:text-gray-scale-700"
type="submit"
disabled={isSubmitting}
>
<span className="font-bold text-body2">로그인</span>
</button>
</div>
</Form>
)}
</Formik>
);
}
10 changes: 0 additions & 10 deletions client/src/app/login/layout.tsx

This file was deleted.

Loading
Loading