-
Notifications
You must be signed in to change notification settings - Fork 0
카테고리 메뉴 기능 구현 #19
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
Open
JongMany
wants to merge
3
commits into
develop
Choose a base branch
from
feature/product
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
카테고리 메뉴 기능 구현 #19
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| NEXT_PUBLIC_BASE_URL=https://objects-mb.com/ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import { Category } from '@/interfaces/product'; | ||
| import { QueryFunction } from '@tanstack/react-query'; | ||
|
|
||
| const getCategoryList: QueryFunction<Category, [string]> = async ({ | ||
| queryKey, | ||
| }) => { | ||
| const [key] = queryKey; | ||
|
|
||
| const response = await fetch( | ||
| `${process.env.NEXT_PUBLIC_BASE_URL}category/total`, | ||
| { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| next: { tags: [key] }, | ||
| cache: 'force-cache', | ||
| }, | ||
| ); | ||
|
|
||
| if (!response.ok) { | ||
| const errorData = await response.json(); | ||
| throw new Error( | ||
| errorData.message || '카테고리 데이터를 가져오는데 실패했습니다...', | ||
| ); | ||
| } | ||
|
|
||
| return response.json(); | ||
| }; | ||
|
|
||
| export default getCategoryList; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| type Props = { | ||
| params: { | ||
| id: string; | ||
| }; | ||
| }; | ||
| export default function Page({ params }: Props) { | ||
| return <div>카테고리 페이지</div>; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| 'use client'; | ||
|
|
||
| import Image from 'next/image'; | ||
| import { Category } from '../../../public/svgs'; | ||
| import { useState } from 'react'; | ||
| import Depth1 from '@/components/(header)/Depth1'; | ||
|
|
||
| export default function CategoryIcon() { | ||
| const [isHover, setIsHover] = useState(false); | ||
|
|
||
| return ( | ||
| <div | ||
| className="flex justify-center items-center cursor-pointer flex-grow relative" | ||
| onMouseEnter={() => setIsHover(true)} | ||
| onMouseLeave={() => setIsHover(false)} | ||
| > | ||
| <div | ||
| className={`transition-all duration-300 hover:bg-sky-500 hover:text-white group p-2 flex items-center gap-x-2 ${isHover ? 'bg-sky-500 text-white' : ''}`} | ||
| > | ||
| <Image | ||
| src={Category} | ||
| alt="카테고리" | ||
| className={`group-hover:invert transition-all duration-300 ${isHover ? 'invert' : ''}`} | ||
| /> | ||
| <p>카테고리</p> | ||
| </div> | ||
| {isHover && <Depth1 />} | ||
| {/* <Depth1 /> */} | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| 'use client'; | ||
| import Depth2 from '@/components/(header)/Depth2'; | ||
| import { Category } from '@/interfaces/product'; | ||
| import { useQueryClient } from '@tanstack/react-query'; | ||
| import { useState } from 'react'; | ||
|
|
||
| const depth1List = [ | ||
| '패션의류/잡화', | ||
| '뷰티', | ||
| '출산/유아동', | ||
| '식품', | ||
| '주방용품', | ||
| '생활용품', | ||
| '홈인테리어', | ||
| '가전디지털', | ||
| '스포츠/레저', | ||
| '자동차용품', | ||
| '도서/음반/DVD', | ||
| '완구/취미', | ||
| '문구/오피스', | ||
| '반려동물용품', | ||
| '헬스/건강식품', | ||
| ]; | ||
|
|
||
| export default function Depth1() { | ||
| const queryClient = useQueryClient(); | ||
| const depth1 = queryClient.getQueryData<Category>(['category']); | ||
|
|
||
| const [hoverNum, setHoverNum] = useState(0); | ||
|
|
||
| const isHover = !!hoverNum; | ||
| const depth2List = depth1?.data | ||
| ? depth1?.data[hoverNum - 1]?.childCategories | ||
| : []; | ||
|
|
||
| return ( | ||
| <div | ||
| className="absolute top-[34px] left-0 flex text-[1.35rem] z-10 bg-white" | ||
| onMouseLeave={() => setHoverNum(0)} | ||
| > | ||
| <div className="w-48 p-4"> | ||
| <ul className={`flex flex-col gap-y-2`}> | ||
| {depth1?.data.map((menu, idx) => ( | ||
| <li | ||
| key={menu.categoryId} | ||
| onMouseEnter={() => setHoverNum(idx + 1)} | ||
| className={`${hoverNum === idx + 1 ? 'text-sky-500 flex justify-between font-bold' : ''} transition-all duration-150 cursor-pointer `} | ||
| > | ||
| <span>{menu.name}</span> | ||
| <span>{hoverNum === idx + 1 ? '▶' : ''}</span> | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| </div> | ||
| {isHover && <Depth2 depth2List={depth2List} />} | ||
| {/* <Depth2 number={hoverNum} /> */} | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| 'use client'; | ||
| import Depth3 from '@/components/(header)/Depth3'; | ||
| import { ICategory } from '@/interfaces/product'; | ||
| import Link from 'next/link'; | ||
| import { useState } from 'react'; | ||
|
|
||
| type Props = { | ||
| depth2List: ICategory[] | undefined; | ||
| }; | ||
|
|
||
| // const depth2List = ['여성패션', '남성패션', '남녀 공용 의류', '유아동패션']; | ||
|
|
||
| export default function Depth2({ depth2List }: Props) { | ||
| const [hoverNum, setHoverNum] = useState(0); | ||
|
|
||
| const isHover = !!hoverNum; | ||
| console.log(depth2List); | ||
|
Member
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. 불필요한 주석 및 콘솔 로그를 제거해주시면 코드 가독성이 더 좋게 보일 것 같다고 생각해요!
Contributor
Author
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. 넵 이부분도 다시 체크해보겠습니다! |
||
|
|
||
| const depth3List = depth2List | ||
| ? depth2List[hoverNum - 1]?.childCategories | ||
| : []; | ||
|
|
||
| return ( | ||
| <div className="w-[28rem]"> | ||
| <div className=" p-4 h-[100%] "> | ||
| <div className="flex items-start" onMouseLeave={() => setHoverNum(0)}> | ||
| <ul className="flex flex-col gap-y-3 px-4 min-w-[13rem]"> | ||
| {depth2List?.map((menu, idx) => ( | ||
| <li | ||
| key={menu.categoryId} | ||
| onMouseEnter={() => setHoverNum(idx + 1)} | ||
| className={`${hoverNum === idx + 1 ? 'text-sky-500 flex justify-between font-bold' : ''} transition-all duration-150 cursor-pointer `} | ||
| > | ||
| <Link href={`/np/categories/${menu.categoryId}`}> | ||
| <span>{menu.name}</span> | ||
| <span>{hoverNum === idx + 1 ? '▶' : ''}</span> | ||
| </Link> | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| {isHover && <Depth3 depth3List={depth3List} />} | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import { ICategory } from '@/interfaces/product'; | ||
| import Link from 'next/link'; | ||
|
|
||
| type Props = { | ||
| depth3List: ICategory[] | undefined; | ||
| }; | ||
|
|
||
| const depth3List = ['의류', '속옷/잠옷', '신발', '가방/잡화']; | ||
|
|
||
| export default function Depth3({ depth3List }: Props) { | ||
| return ( | ||
| <ul className="flex flex-col gap-y-3 h-[100%] px-4 flex-1"> | ||
| {depth3List?.map((menu, idx) => ( | ||
| <li | ||
| key={menu.categoryId} | ||
| className="hover:text-sky-500 hover:flex hover:justify-between hover:font-bold transition-all duration-150 cursor-pointer" | ||
| > | ||
| <Link href={`/np/categories/${menu.categoryId}`}> | ||
| <span>{menu.name}</span> | ||
| </Link> | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| 'use client'; | ||
|
|
||
| import CategoryIcon from '@/components/(header)/CategoryIcon'; | ||
| import Image from 'next/image'; | ||
| import Link from 'next/link'; | ||
| import { usePathname } from 'next/navigation'; | ||
| import { BridgeLogo, Mypage, ShoppingBasket } from '../../../public/svgs'; | ||
| import { useQueryClient } from '@tanstack/react-query'; | ||
|
|
||
| const EXCLUSION_PATHS = [ | ||
| '/login', | ||
| '/register', | ||
| '/login/findId', | ||
| '/login/findPassword', | ||
| ]; | ||
|
|
||
| export default function Navbar() { | ||
| const path = usePathname(); | ||
|
|
||
| if (EXCLUSION_PATHS.includes(path)) return null; | ||
|
|
||
| return ( | ||
| <header className="flex flex-row w-[100%] h-[10rem] text-[1.6rem] items-center"> | ||
| <div className="flex w-[25%] justify-center items-center"> | ||
| <Image | ||
| src={BridgeLogo} | ||
| alt="브릿지로고" | ||
| className="w-[10rem] h-[7rem]" | ||
| /> | ||
| </div> | ||
| <div className="flex w-[30%]"> | ||
| <CategoryIcon /> | ||
| <Link href="/" className="flex justify-center items-center flex-grow"> | ||
| 컬리추천 | ||
| </Link> | ||
| <Link href="/" className="flex justify-center items-center flex-grow"> | ||
| 신상품 | ||
| </Link> | ||
| <Link href="/" className="flex justify-center items-center flex-grow"> | ||
| 베스트 | ||
| </Link> | ||
| <Link href="/" className="flex justify-center items-center flex-grow"> | ||
| 알뜰쇼핑 | ||
| </Link> | ||
| <Link href="/" className="flex justify-center items-center flex-grow"> | ||
| 특가/혜택 | ||
| </Link> | ||
| </div> | ||
| <div className="flex w-[20%] justify-center items-center"> | ||
| <input | ||
| type="text" | ||
| placeholder="검색어를 입력하세요." | ||
| className="flex w-[90%] h-[40%] border border-[#03BAF2] rounded-full" | ||
| /> | ||
| </div> | ||
| <div className="flex w-[20%] justify-around items-center"> | ||
| <Link href="/register">회원가입</Link> | ||
| <Link href="/login">로그인</Link> | ||
| <Link href="/">고객센터</Link> | ||
| <Image | ||
| src={Mypage} | ||
| alt="마이페이지" | ||
| className="flex w-[3rem] h-[5rem]" | ||
| /> | ||
| <Image | ||
| src={ShoppingBasket} | ||
| alt="장바구니" | ||
| className="flex w-[3rem] h-[5rem]" | ||
| /> | ||
| </div> | ||
| </header> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { Response } from '@/interfaces/response'; | ||
|
|
||
| export interface ICategory { | ||
| categoryId: number; | ||
| parentId: number; | ||
| level: number; | ||
| name: string; | ||
| childCategories?: ICategory[]; | ||
| } | ||
|
|
||
| export interface Category extends Response<ICategory[]> {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './category'; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
깃 이그노어 파일에 .env도 추가해주셔야 합니다 !
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.
넵 제가 체크를 못하고 넘겼네요... 이부분도 고쳐놓도록 할게요!
hover 체크하기에 용이하도록 구현했습니다.
서버에서 넘겨주는 값들이 재귀적으로 속성을 물고 들어가게 되기 때문에 이쪽이 가독성 측면과 유지보수 측면에서 더 나을 것이라는 판단 때문에 Depth를 구분지어 줬습니다.
'use client' 같은 경우는 이벤트 핸들러나 state 관리를 사용해야 하는 경우에 대해서만 사용하는 것을 원칙으로 작성하고 있었습니다.
만약 서버 컴포넌트을 작성하다가 state가 필요할 것 같다 싶으면 해당 부분만 따로 빼서 클라이언트 컴포넌트로 작성했습니다.
또한, 클라이언트 서버에서 백엔드 서버에 요청을 하는 게 더 빠를 가능성이 높고, 보안에 유리하다는 장점이 있기 때문에 최대한 서버에서 데이터를 prefetch 하고, 클라이언트에서 hydration하는 형태로 코드를 작성하고 있습니다!
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.
.env.local 로 통일하면 좋을 것 같습니다. 특별한 기준은 없고, 처음부터 세팅할 때 .env.local로 등록되어 있어서 그걸 활용했는데, 같이 통일하면 좋을 것 같습니다.
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.
그리고 한 가지 궁금한 거 여쭤볼께요~
NEXT_PUBLIC_BASE_URL='https://objects-mb.com'
환경변수 설정할 때 single quote 하는 것과 안 하는 것 둘다 동작은 하는 것 같은데, 혹시 둘의 차이를 아시나요?
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.
보통 환경변수 설정할 때 ''은 안해주는 걸로 알고 있어요!
.env.local로 변경해보겠습니다!
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.
저도 .env.local로 맞추겠습니다!
환경변수 같은 경우에는 공식문서상에서 따옴표를 붙이지 않아서 저도 안붙이는 방향으로 개발하고있습니다.