Skip to content

Commit aab636f

Browse files
authored
Merge pull request #96 from part3-4team-Taskify/feature/Gnb
[Refactor, Feat] Gnb: 헤더 기본 출력 기능 추가
2 parents 6818c20 + 0d8165b commit aab636f

File tree

6 files changed

+121
-28
lines changed

6 files changed

+121
-28
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from "react";
2+
import HeaderDashboard from "@/components/gnb/HeaderDashboard";
3+
import SideMenu from "@/components/sideMenu/SideMenu";
4+
import { DashboardType } from "@/types/dashboard";
5+
import { TEAM_ID } from "@/constants/team";
6+
7+
interface DashboardLayoutProps {
8+
children: React.ReactNode;
9+
dashboardList: DashboardType[];
10+
dashboardId?: string | string[];
11+
}
12+
13+
const DashboardLayout = ({
14+
children,
15+
dashboardList,
16+
dashboardId,
17+
}: DashboardLayoutProps) => {
18+
return (
19+
<div className="flex h-screen overflow-hidden">
20+
<SideMenu teamId={TEAM_ID} dashboardList={dashboardList} />
21+
<div className="flex flex-col flex-1">
22+
<HeaderDashboard variant="dashboard" dashboardId={dashboardId} />
23+
<div className="overflow-auto flex-1 px-[50px] pt-[10px] pb-10">
24+
{children}
25+
</div>
26+
</div>
27+
</div>
28+
);
29+
};
30+
31+
export default DashboardLayout;

src/components/gnb/HeaderDashboard.tsx

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import React, { useState, useEffect } from "react";
22
import { useRouter } from "next/router";
3+
import SkeletonUser from "@/shared/skeletonUser";
34
import Image from "next/image";
4-
import SkeletonUser from "../../shared/skeletonUser";
5-
import { MemberType, UserType } from "../../types/users";
5+
import { MemberType, UserType } from "@/types/users";
66
import { getMembers } from "@/api/members";
77
import { getUserInfo } from "@/api/user";
88
import { getDashboardById } from "@/api/dashboards";
99
import { TEAM_ID } from "@/constants/team";
10-
import RandomProfile from "../table/member/RandomProfile";
11-
import InviteDashboard from "../modal/InviteDashboard";
10+
import RandomProfile from "@/components/table/member/RandomProfile";
11+
import InviteDashboard from "@/components/modal/InviteDashboard";
1212

1313
interface HeaderDashboardProps {
1414
variant?: "mydashboard" | "dashboard" | "mypage";
@@ -27,7 +27,11 @@ const HeaderDashboard: React.FC<HeaderDashboardProps> = ({
2727
const router = useRouter();
2828
const [user, setUser] = useState<UserType | null>(null);
2929
const [members, setMembers] = useState<MemberType[]>([]);
30-
const [dashboardTitle, setDashboardTitle] = useState();
30+
const [dashboard, setDashboard] = useState<{
31+
title: string;
32+
createdByMe: boolean;
33+
} | null>(null);
34+
const [errorMessage, setErrorMessage] = useState("");
3135
const [isLoading, setIsLoading] = useState(true);
3236

3337
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -45,7 +49,8 @@ const HeaderDashboard: React.FC<HeaderDashboardProps> = ({
4549
const user = await getUserInfo({ teamId: TEAM_ID });
4650
setUser(user);
4751
} catch (error) {
48-
console.log("유저 정보 불러오기 실패", error);
52+
console.error("유저 정보 불러오기 실패", error);
53+
setErrorMessage("유저 정보를 불러오지 못했습니다.");
4954
} finally {
5055
setIsLoading(false);
5156
}
@@ -62,6 +67,7 @@ const HeaderDashboard: React.FC<HeaderDashboardProps> = ({
6267
setMembers(members);
6368
} catch (error) {
6469
console.error("멤버 불러오기 실패:", error);
70+
setErrorMessage("멤버 정보를 불러오지 못했습니다.");
6571
} finally {
6672
setIsLoading(false);
6773
}
@@ -73,46 +79,66 @@ const HeaderDashboard: React.FC<HeaderDashboardProps> = ({
7379

7480
/*대시보드 이름 api 호출*/
7581
useEffect(() => {
76-
const fetchDashboardTitle = async () => {
82+
const fetchDashboard = async () => {
7783
if (variant === "dashboard" && dashboardId) {
7884
try {
79-
const dashboard = await getDashboardById({
85+
const dashboardData = await getDashboardById({
8086
teamId: TEAM_ID,
8187
dashboardId: Number(dashboardId),
8288
});
83-
setDashboardTitle(dashboard.title);
89+
setDashboard(dashboardData);
8490
} catch (error) {
85-
console.error("대시보드 타이틀 불러오기 실패", error);
91+
console.error("대시보드 정보 불러오기 실패", error);
92+
setErrorMessage("대시보드를 불러오지 못했습니다.");
93+
} finally {
94+
setIsLoading(false);
8695
}
8796
}
8897
};
89-
fetchDashboardTitle();
98+
fetchDashboard();
9099
}, [variant, dashboardId]);
91100

92-
const title =
93-
variant === "mypage"
94-
? "계정 관리"
95-
: variant === "dashboard" && dashboardTitle
96-
? dashboardTitle
97-
: "내 대시보드";
101+
/*헤더 종류에 따라 다른 제목 표시*/
102+
const title = (() => {
103+
if (variant === "mypage") return "계정 관리";
104+
if (variant === "dashboard" && dashboard?.title) return dashboard.title;
105+
return "내 대시보드";
106+
})();
98107

99108
return (
100109
<header className="w-full h-[60px] md:h-[70px] flex items-center justify-center bg-white border-b-[1px] border-b-[#D9D9D9]">
101110
<div className="w-full flex items-center justify-between pl-[4vw]">
102-
<div className="flex items-center gap-[8px]">
103-
<p
104-
className={`text-base text-black3 font-bold md:text-xl
105-
${variant === "mydashboard" ? "block" : "hidden lg:block"}`}
106-
>
107-
{title}
111+
{errorMessage && (
112+
<p className="text-sm text-[var(--color-red)] px-4 py-2">
113+
{errorMessage}
108114
</p>
115+
)}
116+
<div className="flex items-center gap-[8px]">
117+
<p className="text-base text-black3 font-bold md:text-xl">{title}</p>
118+
{dashboard?.createdByMe && (
119+
<Image
120+
src="/svgs/crown.svg"
121+
alt="왕관 아이콘"
122+
width={22}
123+
height={22}
124+
className="inline-block"
125+
unoptimized
126+
priority
127+
/>
128+
)}
109129
</div>
110130

111131
<div className="flex items-center">
112132
{/*관리 / 초대하기 버튼*/}
113133
<div className="flex gap-[6px] md:gap-[16px] pr-[40px]">
114134
<button
115-
onClick={() => router.push(`/dashboard/${dashboardId}/edit`)}
135+
onClick={() => {
136+
if (dashboardId) {
137+
router.push(`/dashboard/${dashboardId}/edit`);
138+
} else {
139+
router.push("mydashboard");
140+
}
141+
}}
116142
className="flex items-center justify-center w-[49px] h-[30px] md:w-[85px] md:h-[36px] lg:w-[88px] lg:h-[40px] rounded-[8px] border border-[#D9D9D9] gap-[10px] cursor-pointer"
117143
>
118144
<Image

src/pages/404.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ export default function Custom404() {
3030
</div>
3131
);
3232
}
33+
34+
Custom404.hideHeader = true;

src/pages/_app.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
1-
import "@/styles/globals.css";
21
import type { AppProps } from "next/app";
2+
import { useRouter } from "next/router";
3+
import HeaderDefault from "@/components/gnb/HeaderDefault";
4+
import "@/styles/globals.css";
35

46
export default function App({ Component, pageProps }: AppProps) {
5-
return <Component {...pageProps} />;
7+
const router = useRouter();
8+
const pathname = router.pathname;
9+
10+
const isDashboardPage = pathname.startsWith("/dashboard");
11+
// 헤더 숨길 페이지
12+
const noHeaderRoutes = ["/login", "/signup", "/mydashboard", "/mypage"];
13+
const isHeaderHidden =
14+
(Component as any).hideHeader ||
15+
noHeaderRoutes.includes(pathname) ||
16+
isDashboardPage;
17+
18+
// 상황별 헤더 분기
19+
const isLandingPage = pathname === "/";
20+
21+
const renderHeader = () => {
22+
if (isHeaderHidden) return null;
23+
if (isLandingPage) return <HeaderDefault variant="black" />;
24+
return <HeaderDefault />;
25+
};
26+
27+
return (
28+
<>
29+
{renderHeader()}
30+
<Component {...pageProps} />
31+
</>
32+
);
633
}

src/pages/index.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useEffect, useState } from "react";
22

33
import Footer from "@/components/landing/Footer";
4-
import LandingHeader from "@/components/gnb/HeaderDefault";
54
import LandingMain from "@/components/landing/LandingMain";
65

76
export default function Home() {
@@ -21,7 +20,6 @@ export default function Home() {
2120

2221
return (
2322
<>
24-
<LandingHeader variant="black" />
2523
<LandingMain />
2624
<Footer />
2725
</>

src/types/dashboard.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface DashboardType {
2+
id: number;
3+
title: string;
4+
color: string;
5+
createdAt: string;
6+
updatedAt: string;
7+
createdByMe: boolean;
8+
userId: number;
9+
}

0 commit comments

Comments
 (0)