-
Notifications
You must be signed in to change notification settings - Fork 44
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
[백승렬] Week14 #463
[백승렬] Week14 #463
Changes from all commits
ab23f8c
f0f5ec2
7d9fa1e
1be2f55
4ef1fa4
3c142e5
63e71c8
cc73034
cfcf20b
803bb24
01718a4
883af9c
b9271ae
07d48a0
7a4b2cc
658493d
ba5c1ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { SignInForm, Oauth } from "@/src/feature"; | ||
import { SignHeader } from "@/src/ui"; | ||
import { SignLayout } from "@/src/page-layout/SignLayout"; | ||
import { ROUTE } from "@/src/util"; | ||
|
||
const SignInPage = () => { | ||
return ( | ||
<SignLayout | ||
header={ | ||
<SignHeader | ||
message="회원이 아니신가요?" | ||
link={{ text: "회원 가입하기", href: ROUTE.회원가입 }} | ||
/> | ||
} | ||
form={<SignInForm />} | ||
oauth={<Oauth description="소셜 로그인" />} | ||
/> | ||
); | ||
}; | ||
|
||
export default SignInPage; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Oauth, SignUpForm } from "@/src/feature"; | ||
import { SignHeader } from "@/src/ui"; | ||
import { SignLayout } from "@/src/page-layout/SignLayout"; | ||
import { ROUTE } from "@/src/util"; | ||
|
||
const SignUpPage = () => { | ||
return ( | ||
<SignLayout | ||
header={ | ||
<SignHeader | ||
message="이미 회원이신가요?" | ||
link={{ text: "로그인 하기", href: ROUTE.로그인 }} | ||
/> | ||
} | ||
form={<SignUpForm />} | ||
oauth={<Oauth description="다른 방식으로 가입하기" />} | ||
/> | ||
); | ||
}; | ||
|
||
export default SignUpPage; |
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { instance, useAsync } from "@/src/util"; | ||
import { useCallback } from "react"; | ||
|
||
/** | ||
* useCheckEmailDuplicate 훅은 이메일 중복 확인을 위한 비동기 요청을 처리합니다. | ||
* | ||
* @param email - 중복 확인할 이메일 주소입니다. | ||
* @returns 훅의 반환 객체입니다. | ||
* @returns return.execute - 이메일 중복 확인을 실행하는 함수입니다. | ||
* @returns return.loading - 이메일 중복 확인 요청의 로딩 상태입니다. | ||
* @returns return.error - 이메일 중복 확인 요청 중 발생한 오류입니다. | ||
* @returns return.data - 이메일 중복 확인 응답 데이터입니다. | ||
* | ||
* @example | ||
* const { execute, loading, error, data } = useCheckEmailDuplicate("example@example.com"); | ||
* | ||
* useEffect(() => { | ||
* execute(); | ||
* }, [execute]); | ||
*/ | ||
Comment on lines
+4
to
+20
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. 와아... ㄷㄷㄷ
|
||
export const useCheckEmailDuplicate = (email: string) => { | ||
const checkEmailDuplicate = useCallback( | ||
() => | ||
instance.post<{ data: { isUsableNickname: boolean } }>("check-email", { | ||
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. 타입 제네릭도 놓치지 않았군요 👍👍👍타입스크립트도 금방금방 적응하시는군요 😊 |
||
email, | ||
}), | ||
[email] | ||
); | ||
const { execute, loading, error, data } = useAsync(checkEmailDuplicate, true); | ||
|
||
return { | ||
execute, | ||
loading, | ||
error, | ||
data, | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,53 @@ | ||
import { useMemo } from "react"; | ||
import { instance, useAsync, mapFoldersData } from "@/src/util"; | ||
import { FolderRawData } from "@/src/type"; | ||
|
||
/** | ||
* useGetFolders 훅은 사용자 폴더 데이터를 가져와서 매핑된 폴더 데이터 배열을 반환합니다. | ||
* | ||
* @returns 훅의 반환 객체입니다. | ||
* @returns return.loading - 폴더 데이터를 가져오는 요청의 로딩 상태입니다. | ||
* @returns return.error - 폴더 데이터를 가져오는 요청 중 발생한 오류입니다. | ||
* @returns return.data - 매핑되고 정렬된 폴더 데이터 배열입니다. | ||
* @returns return.data[].id - 폴더의 고유 ID입니다. | ||
* @returns return.data[].createdAt - 폴더 생성 일자입니다. | ||
* @returns return.data[].name - 폴더의 이름입니다. | ||
* @returns return.data[].userId - 폴더 소유자의 사용자 ID입니다. | ||
* @returns return.data[].linkCount - 폴더에 포함된 링크의 개수입니다. | ||
* | ||
* @example | ||
* const { loading, error, data } = useGetFolders(); | ||
* | ||
* if (loading) { | ||
* return <div>Loading...</div>; | ||
* } | ||
* | ||
* if (error) { | ||
* return <div>Error occurred: {error.message}</div>; | ||
* } | ||
* | ||
* return ( | ||
* <div> | ||
* {data.map(folder => ( | ||
* <div key={folder.id}> | ||
* <h1>{folder.name}</h1> | ||
* <p>{folder.createdAt}</p> | ||
* <p>{folder.linkCount} links</p> | ||
* </div> | ||
* ))} | ||
* </div> | ||
* ); | ||
*/ | ||
export const useGetFolders = () => { | ||
const getFolders = () => | ||
instance.get<{ data: FolderRawData[] }>("users/1/folders"); | ||
const { loading, error, data } = useAsync(getFolders); | ||
|
||
const folders = mapFoldersData(data?.data); | ||
const sortedFolders = folders.sort((a, b) => a?.id - b?.id); | ||
const folders = useMemo(() => mapFoldersData(data?.data), [data?.data]); | ||
const sortedFolders = useMemo( | ||
() => folders.sort((a, b) => a?.id - b?.id), | ||
[folders] | ||
); | ||
|
||
return { loading, error, data: sortedFolders }; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,33 @@ | ||
import { useAsync, instance } from "@/src/util"; | ||
import { UserRawData } from "@/src/type"; | ||
|
||
|
||
/** | ||
* useGetUser 훅은 사용자 데이터를 가져와 반환합니다. | ||
* | ||
* @returns 훅의 반환 객체입니다. | ||
* @returns return.loading - 사용자 데이터를 가져오는 요청의 로딩 상태입니다. | ||
* @returns return.error - 사용자 데이터를 가져오는 요청 중 발생한 오류입니다. | ||
* @returns return.data - 가져온 사용자 데이터입니다. | ||
* | ||
* @example | ||
* const { loading, error, data } = useGetUser(); | ||
* | ||
* if (loading) { | ||
* return <div>Loading...</div>; | ||
* } | ||
* | ||
* if (error) { | ||
* return <div>Error occurred: {error.message}</div>; | ||
* } | ||
* | ||
* return ( | ||
* <div> | ||
* <h1>{data.name}</h1> | ||
* <p>{data.email}</p> | ||
* </div> | ||
* ); | ||
*/ | ||
Comment on lines
+4
to
+30
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. 아니 ㅋㅋㅋ 정말 너무 친절한데요 ..? 🫢웬만한 라이브러리보다 친절하군요 ㄷㄷㄷ |
||
export const useGetUser = () => { | ||
const getUser = () => instance.get<{ data: UserRawData }>("sample/user"); | ||
const { loading, error, data } = useAsync(getUser); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { instance, useAsync } from "@/src/util"; | ||
import { useCallback, useEffect } from "react"; | ||
import { Token } from "@/src/type"; | ||
|
||
type UseSignInParams = { email: string; password: string }; | ||
|
||
/** | ||
* useSignIn 훅은 사용자 인증을 처리하고, 토큰을 로컬 스토리지에 저장합니다. | ||
* | ||
* @param params - 사용자 인증에 필요한 이메일과 비밀번호입니다. | ||
* @param params.email - 사용자 이메일 주소입니다. | ||
* @param params.password - 사용자 비밀번호입니다. | ||
* @returns 훅의 반환 객체입니다. | ||
* @returns return.execute - 사용자 인증을 수동으로 실행하는 함수입니다. | ||
* @returns return.loading - 사용자 인증 요청의 로딩 상태입니다. | ||
* @returns return.error - 사용자 인증 요청 중 발생한 오류입니다. | ||
* @returns return.data - 사용자 인증 응답 데이터입니다. | ||
* | ||
* @example | ||
* const { execute, loading, error, data } = useSignIn({ email: "user@example.com", password: "password" }); | ||
* | ||
* const handleSignIn = async () => { | ||
* await execute(); | ||
* }; | ||
* | ||
* useEffect(() => { | ||
* if (data) { | ||
* console.log("로그인 성공:", data); | ||
* } | ||
* }, [data]); | ||
*/ | ||
export const useSignIn = ({ email, password }: UseSignInParams) => { | ||
const signIn = useCallback( | ||
() => | ||
instance.post<{ data: Token }>("sign-in", { | ||
email, | ||
password, | ||
}), | ||
[email, password] | ||
); | ||
const { execute, loading, error, data } = useAsync(signIn, true); | ||
|
||
useEffect(() => { | ||
if (data?.data.accessToken) { | ||
localStorage.setItem("accessToken", data.data.accessToken); | ||
} | ||
}, [data?.data.accessToken]); | ||
|
||
return { | ||
execute, | ||
loading, | ||
error, | ||
data, | ||
}; | ||
}; |
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.
Page에
Layout
컴포넌트 하나만 들어가있군요.Layout
은 "제한된 공간에 요소를 배치"하는 데에 사용되며 보편적으로children
을 가지게 됩니다 ! 혹시,Page
내에Layout
의 요소를 작성하지 않은 이유가 있으실까요?페이지에 직접 컴포넌트를 작성하지 않으신 이유가 궁금합니다 !