Merge pull request '[fix] 하단 nav 버튼 추가' (#3) from feature/report into master

Reviewed-on: #3
pull/4/head
minheon 2026-04-01 02:19:44 +00:00
commit 603ea4eb35
1 changed files with 46 additions and 13 deletions

View File

@ -2,21 +2,51 @@ import { useLocation, useNavigate } from "react-router-dom";
import ChevronLeftIcon from "@/assets/home/chevron-left.svg?react"; import ChevronLeftIcon from "@/assets/home/chevron-left.svg?react";
import ChevronRightIcon from "@/assets/home/chevron-right.svg?react"; import ChevronRightIcon from "@/assets/home/chevron-right.svg?react";
const PAGE_FLOW = [ /** 리포트 라우트가 `report/:id`일 때 점/플로우에서 이동할 기본 경로 */
{ path: "/", label: "홈" }, const DEFAULT_REPORT_NAV_PATH = "/report/demo";
{ path: "/report", label: "마케팅 분석" },
{ path: "/plan", label: "콘텐츠 기획" }, type FlowStep = {
{ path: "/studio", label: "콘텐츠 제작" }, id: string;
{ path: "/channels", label: "채널 연결" }, label: string;
{ path: "/distribute", label: "콘텐츠 배포" }, /** 이전·다음·점 클릭 시 `navigate`에 넣을 경로 */
{ path: "/performance", label: "성과 관리" }, navigatePath: string;
isActive: (pathname: string) => boolean;
};
const PAGE_FLOW: FlowStep[] = [
{ id: "home", label: "홈", navigatePath: "/", isActive: (p) => p === "/" },
{
id: "report",
label: "마케팅 분석",
navigatePath: DEFAULT_REPORT_NAV_PATH,
isActive: (p) => p === "/report" || p.startsWith("/report/"),
},
{ id: "plan", label: "콘텐츠 기획", navigatePath: "/plan", isActive: (p) => p === "/plan" },
{ id: "studio", label: "콘텐츠 제작", navigatePath: "/studio", isActive: (p) => p === "/studio" },
{ id: "channels", label: "채널 연결", navigatePath: "/channels", isActive: (p) => p === "/channels" },
{
id: "distribute",
label: "콘텐츠 배포",
navigatePath: "/distribute",
isActive: (p) => p === "/distribute",
},
{
id: "performance",
label: "성과 관리",
navigatePath: "/performance",
isActive: (p) => p === "/performance",
},
]; ];
function flowIndexForPathname(pathname: string): number {
return PAGE_FLOW.findIndex((step) => step.isActive(pathname));
}
export function PageNavigator() { export function PageNavigator() {
const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const currentIndex = PAGE_FLOW.findIndex((p) => p.path === location.pathname); const currentIndex = flowIndexForPathname(location.pathname);
if (currentIndex === -1) return null; if (currentIndex === -1) return null;
const prev = currentIndex > 0 ? PAGE_FLOW[currentIndex - 1] : null; const prev = currentIndex > 0 ? PAGE_FLOW[currentIndex - 1] : null;
@ -29,7 +59,8 @@ export function PageNavigator() {
> >
{/* 이전 페이지 */} {/* 이전 페이지 */}
<button <button
onClick={() => prev && navigate(prev.path)} type="button"
onClick={() => prev && navigate(prev.navigatePath)}
disabled={!prev} disabled={!prev}
aria-label={prev ? `이전: ${prev.label}` : "이전 페이지 없음"} aria-label={prev ? `이전: ${prev.label}` : "이전 페이지 없음"}
className="body-14-medium flex items-center gap-2 px-3 py-2 rounded-full text-neutral-70 transition-all hover:bg-neutral-20 hover:text-navy-900 disabled:opacity-30 disabled:cursor-not-allowed cursor-pointer" className="body-14-medium flex items-center gap-2 px-3 py-2 rounded-full text-neutral-70 transition-all hover:bg-neutral-20 hover:text-navy-900 disabled:opacity-30 disabled:cursor-not-allowed cursor-pointer"
@ -42,8 +73,9 @@ export function PageNavigator() {
<div className="flex items-center gap-2 px-2"> <div className="flex items-center gap-2 px-2">
{PAGE_FLOW.map((page, i) => ( {PAGE_FLOW.map((page, i) => (
<button <button
key={page.path} key={page.id}
onClick={() => navigate(page.path)} type="button"
onClick={() => navigate(page.navigatePath)}
title={page.label} title={page.label}
aria-label={page.label} aria-label={page.label}
className={`rounded-full transition-all cursor-pointer ${ className={`rounded-full transition-all cursor-pointer ${
@ -57,7 +89,8 @@ export function PageNavigator() {
{/* 다음 페이지 */} {/* 다음 페이지 */}
<button <button
onClick={() => next && navigate(next.path)} type="button"
onClick={() => next && navigate(next.navigatePath)}
disabled={!next} disabled={!next}
aria-label={next ? `다음: ${next.label}` : "다음 페이지 없음"} aria-label={next ? `다음: ${next.label}` : "다음 페이지 없음"}
className="body-14-medium flex items-center gap-2 px-3 py-2 rounded-full text-neutral-70 transition-all hover:bg-neutral-20 hover:text-navy-900 disabled:opacity-30 disabled:cursor-not-allowed cursor-pointer" className="body-14-medium flex items-center gap-2 px-3 py-2 rounded-full text-neutral-70 transition-all hover:bg-neutral-20 hover:text-navy-900 disabled:opacity-30 disabled:cursor-not-allowed cursor-pointer"