Skip to content

Commit

Permalink
✨ 대분류 페이지 2차 추가 (#140)
Browse files Browse the repository at this point in the history
* feat: 다차원 대분류 추가

* fix: 2차원 여부 표시

* feat: 입학 대분류 페이지 추가

* feat: 시설 예약 대분류 페이지 추가

* feat: 대분류 아이템 영어 이름 추가

* design: 대분류 제목 패딩 조정

* design: 헤더 색 투명하게 변경
  • Loading branch information
Limchansol authored Mar 1, 2024
1 parent aa6992c commit c0bd4b5
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 26 deletions.
6 changes: 1 addition & 5 deletions app/[locale]/about/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { getAboutDescription } from '@/apis/about';

import MajorCategoryPageLayout from '@/components/layout/pageLayout/MajorCategoryPageLayout';

export default async function AboutPage() {
const description = await getAboutDescription();

return <MajorCategoryPageLayout subtitle="About CSE" description={description} />;
return <MajorCategoryPageLayout subtitle="About CSE" />;
}
5 changes: 5 additions & 0 deletions app/[locale]/academics/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import MajorCategoryPageLayout from '@/components/layout/pageLayout/MajorCategoryPageLayout';

export default async function AcademicsPage() {
return <MajorCategoryPageLayout subtitle="Learning CSE" twoDimensional />;
}
5 changes: 5 additions & 0 deletions app/[locale]/admissions/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import MajorCategoryPageLayout from '@/components/layout/pageLayout/MajorCategoryPageLayout';

export default async function AdmissionsPage() {
return <MajorCategoryPageLayout subtitle="Enroll CSE" twoDimensional />;
}
5 changes: 5 additions & 0 deletions app/[locale]/reservations/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import MajorCategoryPageLayout from '@/components/layout/pageLayout/MajorCategoryPageLayout';

export default async function ReservationsPage() {
return <MajorCategoryPageLayout subtitle="Reserve CSE" twoDimensional />;
}
2 changes: 1 addition & 1 deletion components/layout/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function Header() {
const goToMainPage = () => (window.location.href = '/');

return (
<header className={`bg-[#1f2021] px-[3.75rem] pt-12 pb-[2.44rem] flex justify-between`}>
<header className={`px-[3.75rem] pt-12 pb-[2.44rem] flex justify-between`}>
<div onClick={goToMainPage} className="cursor-pointer">
<HeaderLogo />
</div>
Expand Down
110 changes: 91 additions & 19 deletions components/layout/pageLayout/MajorCategoryPageLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,76 @@
'use client';

import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useTranslations } from 'next-intl';
import React from 'react';
import React, { useState } from 'react';

import HTMLViewer from '@/components/editor/HTMLViewer';

import useCurrentSegmentNode from '@/hooks/useCurrentSegmentNode';

import { getPath } from '@/utils/page';

import ENG_NAMES from '../../../messages/en.json';
import Header from '../header/Header';

interface GuidePageLayoutProps {
title?: string;
subtitle?: string;
description?: string;
twoDimensional?: boolean;
}

export default function MajorCategoryPageLayout({
title,
subtitle = '',
description = '',
twoDimensional = false,
}: GuidePageLayoutProps) {
const t = useTranslations('Nav');
const currentPage = useCurrentSegmentNode();
title ||= t(currentPage.name);
const [selectedCategory, setSelectedCategory] = useState(
twoDimensional ? currentPage.children?.[0] ?? null : null,
);
const router = useRouter();

return (
<div className="bg-neutral-850">
<Header />
<div className="max-w-[80rem] pt-12 pb-[4.5rem] px-[6.25rem]">
<div className="max-w-[80rem] py-12 px-[6.25rem]">
<div className="text-neutral-500 text-[20px] font-light">{subtitle}</div>
<div className="text-white text-[64px] font-semibold tracking-wide mb-8">{title}</div>
<HTMLViewer htmlContent={description} style={{ color: '#f5f5f5' }} />
<div className="text-white text-[64px] font-semibold tracking-wide">{title}</div>
{description && (
<HTMLViewer htmlContent={description} style={{ color: '#f5f5f5' }} margin="mt-8 mb-6" />
)}
</div>
<div className="bg-neutral-900 pt-20 pb-[13.75rem] px-[6.25rem]">
<div className="grid gap-10 grid-cols-[repeat(auto-fill,_300px)]">
<div className="bg-neutral-900 pt-20 pb-[11.25rem] px-[6.25rem]">
<div className="grid gap-10 grid-cols-[repeat(auto-fill,_300px)] mb-10">
{currentPage.children!.map((subpage, index) => (
<DetailItem
<RootItem
key={index}
title={subpage.name}
description={subpage.description ?? ''}
href={getPath(subpage)}
onClick={() =>
subpage.isPage ? router.push(getPath(subpage)) : setSelectedCategory(subpage)
}
isSelected={selectedCategory == subpage}
isPage={subpage.isPage}
/>
))}
</div>
{selectedCategory && !selectedCategory.isPage && (
<div className="grid gap-10 grid-cols-[repeat(auto-fill,_300px)] mb-10">
{selectedCategory.children!.map((subpage, index) => (
<LeafItem
key={index}
title={subpage.name}
description={subpage.description ?? ''}
onClick={() => router.push(getPath(subpage))}
/>
))}
</div>
)}
</div>
</div>
);
Expand All @@ -54,23 +79,70 @@ export default function MajorCategoryPageLayout({
interface DetailItemProps {
title: string;
description: string;
href: string;
hasArrow: boolean;
bgColor: string;
hoverColor?: string;
onClick: () => void;
}

function DetailItem({ title, description, href }: DetailItemProps) {
function DetailItem({ title, hasArrow, bgColor, hoverColor, onClick }: DetailItemProps) {
const hoverBgColor = hoverColor ? `hover:${hoverColor}` : 'hover:bg-main-orange-dark';
return (
<Link href={href}>
<div className="w-[300px] h-[160px] bg-neutral-100 px-7 py-6 hover:bg-main-orange-dark flex flex-col justify-between">
<div>
<h3 className="text-neutral-800 text-[20px] font-medium mb-[16px]">{title}</h3>
<p className="text-neutral-800 text-[16px]">{description}</p>
</div>
<div
className={`w-[300px] h-[160px] ${bgColor} px-7 py-6 ${hoverBgColor} flex flex-col justify-between cursor-pointer`}
onClick={onClick}
>
<div>
<h3 className="text-neutral-800 text-[20px] font-medium mb-2.5">{title}</h3>
<p className="text-neutral-800">
{ENG_NAMES.Nav[title as keyof typeof ENG_NAMES.Nav] ?? ''}
</p>
</div>
{hasArrow && (
<div className="text-end">
<span className="material-symbols-outlined font-extralight text-[32px] text-neutral-800">
arrow_forward
</span>
</div>
</div>
</Link>
)}
</div>
);
}

interface RootItemProps {
title: string;
description: string;
isPage: boolean;
isSelected?: boolean;
onClick: () => void;
}

function RootItem({ title, description, isPage, isSelected, onClick }: RootItemProps) {
return (
<DetailItem
title={title}
description={description}
onClick={onClick}
hasArrow={isPage}
bgColor={isSelected ? 'bg-main-orange-dark' : 'bg-neutral-100'}
/>
);
}
interface LeafItemProps {
title: string;
description: string;
onClick: () => void;
}

function LeafItem({ title, description, onClick }: LeafItemProps) {
return (
<DetailItem
title={title}
description={description}
onClick={onClick}
hasArrow
bgColor="bg-neutral-400"
hoverColor="bg-neutral-500"
/>
);
}
2 changes: 1 addition & 1 deletion utils/page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SegmentNode, admin, main } from '@/types/page';
import { SegmentNode, main } from '@/types/page';

export const getLocationLog = (location: SegmentNode | null): SegmentNode[] => {
if (!(location && location !== main)) return [];
Expand Down

0 comments on commit c0bd4b5

Please sign in to comment.