From 182d310a9e7a2cf4c797b3495cfdb440d00c5cde Mon Sep 17 00:00:00 2001 From: chansol Date: Tue, 4 Mar 2025 17:47:44 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=8C=80=EB=B6=84=EB=A5=98=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20?= =?UTF-8?q?=EA=B7=B8=EB=A6=AC=EB=93=9C=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/[locale]/community/council/page.tsx | 24 +-- components/layout/pageLayout/CategoryGrid.tsx | 140 ++++++++++++++++ .../pageLayout/MajorCategoryPageLayout.tsx | 156 ++---------------- 3 files changed, 167 insertions(+), 153 deletions(-) create mode 100644 components/layout/pageLayout/CategoryGrid.tsx diff --git a/app/[locale]/community/council/page.tsx b/app/[locale]/community/council/page.tsx index e06d9e03..6673b8ac 100644 --- a/app/[locale]/community/council/page.tsx +++ b/app/[locale]/community/council/page.tsx @@ -1,4 +1,5 @@ -import MajorCategoryPageLayout from '@/components/layout/pageLayout/MajorCategoryPageLayout'; +import Header from '@/components/layout/header/Header'; +import CategoryGrid from '@/components/layout/pageLayout/CategoryGrid'; import PageTitle from '@/components/layout/pageLayout/PageTitle'; import { council } from '@/constants/segmentNode'; import { getMetadata } from '@/utils/metadata'; @@ -13,16 +14,15 @@ export async function generateMetadata(props: { params: Promise<{ locale: string export default async function CouncilPage() { return ( - - } - /> +
+
+ + +
); } diff --git a/components/layout/pageLayout/CategoryGrid.tsx b/components/layout/pageLayout/CategoryGrid.tsx new file mode 100644 index 00000000..40c72529 --- /dev/null +++ b/components/layout/pageLayout/CategoryGrid.tsx @@ -0,0 +1,140 @@ +'use client'; + +import { useTranslations } from 'next-intl'; +import { useState } from 'react'; + +import { SegmentNode } from '@/constants/segmentNode'; +import { useRouter } from '@/i18n/routing'; +import { getPath } from '@/utils/page'; + +import ENG_NAMES from '../../../messages/en.json'; + +// TODO: RootItem을 클릭했을 때 LeafItem이 보이도록 자동 스크롤 +export default function CategoryGrid({ + currentPage, + theme, +}: { + currentPage: SegmentNode; + theme: 'light' | 'dark'; +}) { + const t = useTranslations('Nav'); + + // 학사 및 교과 등에서 소분류 선택 처리용 state + const [selectedCategory, setSelectedCategory] = useState(null); + const router = useRouter(); + + return ( +
+
+ {currentPage.children!.map((subpage, index) => ( + + subpage.isPage ? router.push(getPath(subpage)) : setSelectedCategory(subpage) + } + isSelected={selectedCategory == subpage} + isLight={theme === 'light'} + isPage={subpage.isPage} + /> + ))} +
+ + {selectedCategory && !selectedCategory.isPage && ( +
+ {selectedCategory.children!.map((subpage, index) => ( + router.push(getPath(subpage))} + /> + ))} +
+ )} +
+ ); +} + +interface RootItemProps { + title: string; + isPage: boolean; + isSelected?: boolean; + onClick: () => void; + isLight?: boolean; +} + +function RootItem({ title, isPage, isSelected, isLight, onClick }: RootItemProps) { + const bgColor = isSelected ? 'bg-main-orange-dark' : isLight ? 'bg-neutral-50' : 'bg-neutral-100'; + + return ( + + ); +} +interface LeafItemProps { + title: string; + onClick: () => void; +} + +function LeafItem({ title, onClick }: LeafItemProps) { + return ( + + ); +} + +interface DetailItemProps { + title: string; + hasArrow: boolean; + bgColor: string; + hoverColor?: string; + borderColor?: string; + onClick: () => void; +} + +function DetailItem({ + title, + hasArrow, + bgColor, + hoverColor, + borderColor, + onClick, +}: DetailItemProps) { + const hoverBgColor = hoverColor ? `hover:${hoverColor}` : 'hover:bg-main-orange-dark'; + + return ( +
+
+

+ {title} +

+

+ {ENG_NAMES.Nav[title as keyof typeof ENG_NAMES.Nav] ?? ''} +

+
+ {hasArrow && ( +
+ + arrow_forward + +
+ )} +
+ ); +} diff --git a/components/layout/pageLayout/MajorCategoryPageLayout.tsx b/components/layout/pageLayout/MajorCategoryPageLayout.tsx index fa5d98a0..8fa29648 100644 --- a/components/layout/pageLayout/MajorCategoryPageLayout.tsx +++ b/components/layout/pageLayout/MajorCategoryPageLayout.tsx @@ -1,32 +1,23 @@ 'use client'; import { useTranslations } from 'next-intl'; -import { ReactNode, useState } from 'react'; import HTMLViewer from '@/components/form/html/HTMLViewer'; -import { SegmentNode } from '@/constants/segmentNode'; -import { useRouter } from '@/i18n/routing'; import useCurrentSegmentNode from '@/utils/hooks/useCurrentSegmentNode'; -import { getPath } from '@/utils/page'; -import ENG_NAMES from '../../../messages/en.json'; import Header from '../header/Header'; +import CategoryGrid from './CategoryGrid'; interface GuidePageLayoutProps { title?: string; subtitle?: string; description?: string; - theme?: 'light' | 'dark'; - titleComponent?: ReactNode; } -// TODO: RootItem을 클릭했을 때 LeafItem이 보이도록 자동 스크롤 export default function MajorCategoryPageLayout({ title, subtitle = '', description = '', - theme = 'dark', - titleComponent, }: GuidePageLayoutProps) { const t = useTranslations('Nav'); const currentPage = useCurrentSegmentNode(); @@ -34,62 +25,27 @@ export default function MajorCategoryPageLayout({ // TODO: messages.json에 번역 파일 추가 title ||= t(currentPage.name); - // 학사 및 교과 등에서 소분류 선택 처리용 state - const [selectedCategory, setSelectedCategory] = useState(null); - const router = useRouter(); - return (
- {titleComponent || ( -
-
{subtitle}
-
- {title} -
- {description && ( - - )} -
- )} -
-
- {currentPage.children!.map((subpage, index) => ( - - subpage.isPage ? router.push(getPath(subpage)) : setSelectedCategory(subpage) - } - isSelected={selectedCategory == subpage} - isLight={theme === 'light'} - isPage={subpage.isPage} - /> - ))} +
+
{subtitle}
+
+ {title}
- - {selectedCategory && !selectedCategory.isPage && ( -
- {selectedCategory.children!.map((subpage, index) => ( - router.push(getPath(subpage))} - /> - ))} -
+ {description && ( + // 웹버전 description + )}
+ {description && ( -
+ // 모바일 버전 description +
); } - -interface RootItemProps { - title: string; - isPage: boolean; - isSelected?: boolean; - onClick: () => void; - isLight?: boolean; -} - -function RootItem({ title, isPage, isSelected, isLight, onClick }: RootItemProps) { - const bgColor = isSelected ? 'bg-main-orange-dark' : isLight ? 'bg-neutral-50' : 'bg-neutral-100'; - - return ( - - ); -} -interface LeafItemProps { - title: string; - onClick: () => void; -} - -function LeafItem({ title, onClick }: LeafItemProps) { - return ( - - ); -} - -interface DetailItemProps { - title: string; - hasArrow: boolean; - bgColor: string; - hoverColor?: string; - borderColor?: string; - onClick: () => void; -} - -function DetailItem({ - title, - hasArrow, - bgColor, - hoverColor, - borderColor, - onClick, -}: DetailItemProps) { - const hoverBgColor = hoverColor ? `hover:${hoverColor}` : 'hover:bg-main-orange-dark'; - - return ( -
-
-

- {title} -

-

- {ENG_NAMES.Nav[title as keyof typeof ENG_NAMES.Nav] ?? ''} -

-
- {hasArrow && ( -
- - arrow_forward - -
- )} -
- ); -}