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 19 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.push('/');
Copy link
Member

Choose a reason for hiding this comment

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

로그인 완료시에 뒤로가기 하면 어떻게될까? 만약 뒤로가기가 불필요하다면 replace를 써도 될거같아

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

말해준대로 로그인 시 이전페이지로 가는 것이 더 올바른 작동방식이라고 생각이 들었엉 그렇지만 그냥 router.back()을 쓰자니 앞으로 가기가 남아져서 불편한 감을 느꼈고 replace를 사용하는 방법이 최적의 방법이라 생각했습니다.

그래서 로그인 페이지 이전에 경로를 받기 위해서 documet.referrer를 사용하려 했더니 서버사이드 렌더링에서는 그렇게 여유치 않았고 login 페이지로 이동하는 버튼을 클릭했을 때 sessionStorage에 previousURL값을 저장해두고 로그인 성공시 replace로 이동하는 것으로 로직을 수정했습니다.

만일 다이렉트로 로그인페이지로 왔다면 root로 돌아갈수 있게 하였습니다~

} 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