Skip to content

Commit 29ad497

Browse files
authored
Merge pull request #57 from HelloPy-Korea/release
add coc page
2 parents 9453fa0 + fac8049 commit 29ad497

6 files changed

Lines changed: 841 additions & 25 deletions

File tree

src/App.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
import { QueryClient, QueryClientProvider } from "react-query";
99
import Layout from "@/components/Layout/Layout.tsx";
1010
import { IRoute, Pages } from "@/types/route.ts";
11+
import NotFound from "@/pages/404";
12+
1113
const pages: Pages = import.meta.glob("./pages/**/*.tsx", { eager: true });
1214
const routes: IRoute[] = [];
1315

@@ -41,13 +43,19 @@ const router = createBrowserRouter([
4143
{
4244
path: "/", // Layout의 루트 경로
4345
element: <Layout />,
44-
children: routes.map(({ Element, ErrorBoundary, ...rest }) => ({
45-
...rest,
46-
element: <Element />,
47-
...(ErrorBoundary && {
48-
errorElement: React.createElement(ErrorBoundary),
49-
}),
50-
})),
46+
children: [
47+
...routes.map(({ Element, ErrorBoundary, ...rest }) => ({
48+
...rest,
49+
element: <Element />,
50+
...(ErrorBoundary && {
51+
errorElement: React.createElement(ErrorBoundary),
52+
}),
53+
})),
54+
{
55+
path: "*",
56+
element: <NotFound />,
57+
},
58+
],
5159
},
5260
]);
5361

src/components/AboutTable/AboutTable.tsx

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
11
import { useNavigate } from "react-router-dom";
2+
import { FaThumbtack } from "react-icons/fa";
23

34
interface Column {
45
label: string;
56
value: string;
7+
size: string;
68
}
79

8-
interface AboutTableProps<T> {
10+
interface AboutTableProps<T extends object> {
911
columns: Column[];
1012
data: T[];
13+
moveToDetail: (row: T) => void;
1114
}
1215

13-
export const AboutTable = <T extends { id: number }>({
16+
export const AboutTable = <T extends object>({
1417
columns,
1518
data,
19+
moveToDetail,
1620
}: AboutTableProps<T>) => {
17-
const nav = useNavigate();
18-
const moveToDetail = (row: T) => {
19-
nav(`/board/notice/${row.id}`);
20-
};
21+
22+
// 고정된 항목과 일반 항목을 분리
23+
const pinnedItems = data.filter((item: any) => item.is_pinned);
24+
const normalItems = data.filter((item: any) => !item.is_pinned);
25+
2126

2227
return (
2328
<div className="w-full overflow-x-auto">
2429
<table className="w-full border-collapse border-black/50">
30+
<colgroup>
31+
{columns.map((column, index) => (
32+
<col style={{width: column.size}} key={column.value + "_col_" + index}/>
33+
))}
34+
</colgroup>
35+
2536
<thead className="bg-white text-lg font-medium text-[#343434]">
2637
<tr className="border-b border-black/50">
2738
{columns.map((column, index) => (
@@ -35,9 +46,27 @@ export const AboutTable = <T extends { id: number }>({
3546
</tr>
3647
</thead>
3748
<tbody className="bg-white">
38-
{data.map((row, rowIndex) => (
49+
{/* 고정된 항목 먼저 표시 */}
50+
{pinnedItems.map((row, rowIndex) => (
51+
<tr
52+
key={`pinned-${rowIndex}`}
53+
className="border-b border-black/20 hover:cursor-pointer bg-gray-50"
54+
onClick={() => moveToDetail(row)}
55+
>
56+
{columns.map((column, index) => (
57+
<td
58+
key={index}
59+
className="p-[9px] text-left text-lg font-normal text-[#343434]"
60+
>
61+
{column.value === "pin" ? <FaThumbtack className="text-hellopy-purple-200" /> : String(row[column.value as keyof T] ?? "-")}
62+
</td>
63+
))}
64+
</tr>
65+
))}
66+
{/* 일반 항목 표시 */}
67+
{normalItems.map((row, rowIndex) => (
3968
<tr
40-
key={rowIndex}
69+
key={`normal-${rowIndex}`}
4170
className="border-b border-black/20 hover:cursor-pointer"
4271
onClick={() => moveToDetail(row)}
4372
>

src/components/Header/Header.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ const menuItems = [
2626
{ label: "MD", path: "/about/md" },
2727
],
2828
},
29+
{
30+
label: "COC",
31+
hasDropdown: false,
32+
path: "/coc",
33+
},
2934
/* { label: "NEWS", hasDropdown: false },
3035
{ label: "SUPPORT", hasDropdown: false },
3136
{ label: "COC", hasDropdown: false },*/
@@ -63,13 +68,17 @@ const Header = ({ backgroundColor, textColor }: HeaderProps) => {
6368

6469
{/* 데스크탑 네비게이션 */}
6570
<nav className="relative z-[999] hidden gap-2 md:flex md:gap-10">
66-
{menuItems.map(({ label, hasDropdown, subItems }) => (
71+
{menuItems.map(({ label, hasDropdown, subItems, path }) => (
6772
<div
6873
key={label}
6974
className="relative flex cursor-pointer items-center gap-2"
70-
onClick={() =>
71-
setOpenDropdown(openDropdown === label ? null : label)
72-
}
75+
onClick={() => {
76+
if (hasDropdown) {
77+
setOpenDropdown(label);
78+
} else {
79+
goToMenu(path)
80+
}
81+
}}
7382
>
7483
<HeaderMenu label={label} textColor={textColor} />
7584
{hasDropdown && (
@@ -117,9 +126,9 @@ const Header = ({ backgroundColor, textColor }: HeaderProps) => {
117126
<div key={label} className="relative">
118127
<div
119128
className="flex cursor-pointer items-center justify-between"
120-
onClick={() =>
121-
setOpenDropdown(openDropdown === label ? null : label)
122-
}
129+
onClick={() => {
130+
setOpenDropdown(openDropdown === label ? null : label);
131+
}}
123132
>
124133
<span className="text-lg font-medium">{label}</span>
125134
{hasDropdown && <FaChevronDown className="text-gray-600" />}

src/pages/404.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { useNavigate } from "react-router-dom";
2+
3+
const NotFound = () => {
4+
const navigate = useNavigate();
5+
6+
return (
7+
<div className="flex h-screen w-full flex-col items-center justify-center gap-8">
8+
<div className="text-center">
9+
<h1 className="mb-4 text-6xl font-bold text-hellopy-purple-200">404</h1>
10+
<p className="mb-2 text-2xl font-medium text-black">페이지를 찾을 수 없습니다</p>
11+
<p className="text-base text-gray-600">
12+
요청하신 페이지가 삭제되었거나 잘못된 경로입니다.
13+
</p>
14+
</div>
15+
<button
16+
onClick={() => navigate("/")}
17+
className="rounded-full bg-hellopy-purple-200 px-8 py-3 text-white transition-all hover:bg-hellopy-purple-300"
18+
>
19+
홈으로 돌아가기
20+
</button>
21+
</div>
22+
);
23+
};
24+
25+
export default NotFound;

src/pages/board/notice/index.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import { Container } from "@/components/Container";
1212
import { useState } from "react";
1313

1414
const tableColumns = [
15-
{ label: "번호", value: "id" },
15+
{ label: "번호", value: "id", size:"10%"},
1616
/* { label: "태그", value: "tag" },*/
17-
{ label: "제목", value: "title" },
17+
{ label: "제목", value: "title", size:"80%"},
18+
{ label: "고정", value: "pin", size:"10%"},
1819
/*{ label: "작성일", value: "date" },*/
1920
];
2021

@@ -42,6 +43,10 @@ export const Notice: React.FC = () => {
4243
setPage(val);
4344
};
4445

46+
const moveToDetail = (row: any) => {
47+
nav(`/board/notice/${row.id}`);
48+
};
49+
4550
return (
4651
<>
4752
<div className="align-center dark flex flex-col">
@@ -71,7 +76,7 @@ export const Notice: React.FC = () => {
7176
onTabChange={tabMockData.onTabChange}
7277
/>
7378
{/* REVIEW: "총 N개의 공지가 있습니다" 레이블 어떻게 표시할 건지? */}
74-
<AboutTable columns={tableColumns} data={noticeList} />
79+
<AboutTable columns={tableColumns} data={noticeList} moveToDetail={moveToDetail} />
7580
{/* XXX: AboutTable 테이블 높이가 고정되어 있어서 Pagination 위치가 부자연스러움 */}
7681
{noticeList && noticeList.length > 0 && (
7782
<Pagination

0 commit comments

Comments
 (0)