-
Notifications
You must be signed in to change notification settings - Fork 4
Feat/markup/signup/DEVING-25 회원가입 페이지 개발 #25
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
Changes from all commits
15192a0
54440cb
92772d8
380ab9e
7f6bfc9
b95dd8d
c5f7eb2
94809a7
6778d13
9e7d588
801b035
787c2a8
442530f
c4d9a92
e4e3ac0
c1fdeb6
0dcbd56
303fb79
66d5593
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| 'use client'; | ||
|
|
||
| import { Input } from '@/components/ui/Input'; | ||
| import useDebounce from '@/hooks/useDebounde'; | ||
| import { loginEmailValidation } from '@/util/validation'; | ||
| import { useCallback } from 'react'; | ||
| import { useWatch } from 'react-hook-form'; | ||
| import { IInputProps, ILoginFormData } from 'types/auth'; | ||
|
|
||
| const EmailInput = ({ | ||
| control, | ||
| register, | ||
| errors, | ||
| trigger, | ||
| }: IInputProps<ILoginFormData>) => { | ||
| const email = useWatch({ control, name: 'email' }); | ||
|
|
||
| useDebounce({ | ||
| value: email, | ||
| callBack: useCallback(() => { | ||
| trigger?.('email'); | ||
| }, [email]), | ||
|
Check warning on line 22 in src/app/login/components/EmailInput.tsx
|
||
| }); | ||
|
|
||
| return ( | ||
| <> | ||
| <label htmlFor="email" className="typo-head3 text-Cgray700"> | ||
| 이메일 | ||
| </label> | ||
| <Input | ||
| id="email" | ||
| className="mb-[20px] mt-[8px]" | ||
| placeholder="이메일을 입력해주세요." | ||
| {...register('email', loginEmailValidation)} | ||
| errorMessage={errors.email?.message} | ||
| /> | ||
| </> | ||
| ); | ||
| }; | ||
|
|
||
| export default EmailInput; | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,42 @@ | ||||||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import { Input } from '@/components/ui/Input'; | ||||||||||||||||||||||||||
| import useDebounce from '@/hooks/useDebounde'; | ||||||||||||||||||||||||||
| import { loginPasswordValidation } from '@/util/validation'; | ||||||||||||||||||||||||||
| import { useCallback } from 'react'; | ||||||||||||||||||||||||||
| import { useWatch } from 'react-hook-form'; | ||||||||||||||||||||||||||
| import { IInputProps, ILoginFormData } from 'types/auth'; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const PasswordInput = ({ | ||||||||||||||||||||||||||
| control, | ||||||||||||||||||||||||||
| register, | ||||||||||||||||||||||||||
| errors, | ||||||||||||||||||||||||||
| trigger, | ||||||||||||||||||||||||||
| }: IInputProps<ILoginFormData>) => { | ||||||||||||||||||||||||||
| const password = useWatch({ control, name: 'password' }); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| useDebounce({ | ||||||||||||||||||||||||||
| value: password, | ||||||||||||||||||||||||||
| callBack: useCallback(() => { | ||||||||||||||||||||||||||
| trigger?.('password'); | ||||||||||||||||||||||||||
| }, [password]), | ||||||||||||||||||||||||||
|
Check warning on line 22 in src/app/login/components/PasswordInput.tsx
|
||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
|
Comment on lines
+18
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion useCallback 의존성 배열에 trigger를 추가해주세요. useCallback 훅의 의존성 배열에 trigger 함수가 포함되어 있지 않습니다. 이로 인해 trigger 함수가 변경될 때 콜백이 업데이트되지 않을 수 있습니다. useDebounce({
value: password,
callBack: useCallback(() => {
trigger?.('password');
- }, [password]),
+ }, [password, trigger]),
});📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: check[warning] 22-22: |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||
| <label htmlFor="password" className="typo-head3 text-Cgray700"> | ||||||||||||||||||||||||||
| 비밀번호 | ||||||||||||||||||||||||||
| </label> | ||||||||||||||||||||||||||
| <Input | ||||||||||||||||||||||||||
| {...register('password', loginPasswordValidation)} | ||||||||||||||||||||||||||
| id="password" | ||||||||||||||||||||||||||
| type="password" | ||||||||||||||||||||||||||
| className="mb-[20px] mt-[8px]" | ||||||||||||||||||||||||||
| placeholder="비밀번호를 입력해주세요." | ||||||||||||||||||||||||||
| errorMessage={errors.password?.message} | ||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| export default PasswordInput; | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,40 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import Chip from '@/components/ui/Chip'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import React, { useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default function ChipPreview() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [position, setPosition] = useState(''); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex flex-col gap-8 bg-gray-50 p-8 pb-32"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Chip>All</Chip> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Chip isActive>All</Chip> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="w-[544px] p-[40px]"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex w-full"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Chip | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={`flex-1 hover:cursor-pointer`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isActive={position === 'Frontend'} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={() => setPosition('Frontend')} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 프론트엔드 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Chip> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Chip | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={`flex-1 hover:cursor-pointer`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isActive={position === 'Backend'} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={() => setPosition('Backend')} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 백엔드 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Chip> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Chip | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={`flex-1 hover:cursor-pointer`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isActive={position === 'Designer'} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={() => setPosition('Designer')} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 디자이너 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Chip> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+13
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion ChipContainer 컴포넌트 재사용이 필요합니다. 이미 구현된 ChipContainer 컴포넌트를 재사용하여 코드 중복을 제거하는 것이 좋습니다. - <div className="w-[544px] p-[40px]">
- <div className="flex w-full">
- <Chip
- className={`flex-1 hover:cursor-pointer`}
- isActive={position === 'Frontend'}
- onClick={() => setPosition('Frontend')}
- >
- 프론트엔드
- </Chip>
- <Chip
- className={`flex-1 hover:cursor-pointer`}
- isActive={position === 'Backend'}
- onClick={() => setPosition('Backend')}
- >
- 백엔드
- </Chip>
- <Chip
- className={`flex-1 hover:cursor-pointer`}
- isActive={position === 'Designer'}
- onClick={() => setPosition('Designer')}
- >
- 디자이너
- </Chip>
- </div>
+ <div className="w-[544px] p-[40px]">
+ <ChipContainer position={position} setPosition={setPosition} />
</div>📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| 'use client'; | ||
|
|
||
| import { useToast } from '@/components/common/ToastContext'; | ||
|
|
||
| export default function Page() { | ||
| const { showToast } = useToast(); | ||
|
|
||
| return ( | ||
| <div> | ||
| <button | ||
| onClick={() => showToast('로그인 성공!', 'success', { duration: 3000 })} | ||
| className="bg-blue-500 rounded px-4 py-2 text-white" | ||
| > | ||
| 성공 토스트 보여주기 | ||
| </button> | ||
| <button | ||
| onClick={() => showToast('로그인 실패!', 'error', { duration: 3000 })} | ||
| className="bg-blue-500 rounded px-4 py-2 text-white" | ||
| > | ||
| 실패 토스트 보여주기 | ||
| </button> | ||
| <button | ||
| onClick={() => | ||
| showToast('로그인 실패!', 'error', { | ||
| btnText: '재시도', | ||
| onClick: () => alert('버튼 클릭'), | ||
| }) | ||
| } | ||
| className="bg-blue-500 rounded px-4 py-2 text-white" | ||
| > | ||
| 토스트 보여주기(with button) | ||
| </button> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| 'use client'; | ||
|
|
||
| import { Button } from '@/components/ui/Button'; | ||
| import { Input } from '@/components/ui/Input'; | ||
| import useDebounce from '@/hooks/useDebounde'; | ||
| import { emailValidation } from '@/util/validation'; | ||
| import { Dispatch, SetStateAction, useCallback, useEffect } from 'react'; | ||
| import { useWatch } from 'react-hook-form'; | ||
| import { IInputProps, ISignupFormData } from 'types/auth'; | ||
|
|
||
| export interface IEmailInputProps extends IInputProps<ISignupFormData> { | ||
| isEmailCheck: boolean; | ||
| handleEmailCheck: () => void; | ||
| setIsEmailCheck: Dispatch<SetStateAction<boolean>>; | ||
| } | ||
|
|
||
| const EmailInput = ({ | ||
| register, | ||
| errors, | ||
| isEmailCheck, | ||
| handleEmailCheck, | ||
| setIsEmailCheck, | ||
| control, | ||
| trigger, | ||
| }: IEmailInputProps) => { | ||
| const email = useWatch({ control, name: 'email' }); | ||
|
|
||
| // 입력이 있다면 중복확인 버튼 활성화 | ||
| useEffect(() => { | ||
| setIsEmailCheck(false); | ||
| }, [email]); | ||
|
Check warning on line 31 in src/app/signup/components/EmailInput.tsx
|
||
|
|
||
| useDebounce({ | ||
| value: email, | ||
| callBack: useCallback(() => { | ||
| trigger?.('email'); | ||
| }, [email]), | ||
|
Check warning on line 37 in src/app/signup/components/EmailInput.tsx
|
||
| }); | ||
|
|
||
| return ( | ||
| <div className="flex flex-col gap-[8px]"> | ||
| <label htmlFor="id" className="typo-head3 text-Cgray700"> | ||
| 이메일 | ||
| </label> | ||
| <div className="flex flex-row gap-[8px]"> | ||
| <Input | ||
| id="email" | ||
| className=" h-full" | ||
| placeholder="이메일을 입력해주세요." | ||
| {...register('email', emailValidation)} | ||
| state={isEmailCheck ? 'success' : 'default'} | ||
| errorMessage={errors.email?.message} | ||
| /> | ||
| <Button | ||
| disabled={isEmailCheck} | ||
| variant={'outline'} | ||
| size={'sm'} | ||
| className="h-[50px]" | ||
| onClick={handleEmailCheck} | ||
| type="button" | ||
| > | ||
| 중복확인 | ||
| </Button> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
| export default EmailInput; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
useCallback 의존성 배열에 trigger를 추가해주세요.
useCallback 훅을 사용할 때 의존성 배열에 trigger 함수를 포함시켜야 합니다. 현재는 email만 포함되어 있어 trigger 함수가 변경될 경우 콜백이 업데이트되지 않을 수 있습니다.
useDebounce({ value: email, callBack: useCallback(() => { trigger?.('email'); - }, [email]), + }, [email, trigger]), });📝 Committable suggestion
🧰 Tools
🪛 GitHub Check: check
[warning] 22-22:
React Hook useCallback has a missing dependency: 'trigger'. Either include it or remove the dependency array. If 'trigger' changes too often, find the parent component that defines it and wrap that definition in useCallback