feat: 사이드바 메뉴 클릭 핸들러 작업
This commit is contained in:
@@ -1,11 +1,18 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
import { BaseLayout } from "@common/components/ui";
|
import { BaseLayout } from "@common/components/ui";
|
||||||
|
|
||||||
export default function WithBaseLayout({
|
export default function WithBaseLayout({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return <BaseLayout>{children}</BaseLayout>;
|
const router = useRouter();
|
||||||
|
const pathname = usePathname();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseLayout currentPath={pathname ?? ""} routeHandler={router.push}>
|
||||||
|
{children}
|
||||||
|
</BaseLayout>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,13 @@ import type { QueryClient } from "@tanstack/react-query";
|
|||||||
export function BaseLayout({
|
export function BaseLayout({
|
||||||
children,
|
children,
|
||||||
queryClient,
|
queryClient,
|
||||||
|
currentPath,
|
||||||
|
routeHandler,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
queryClient?: QueryClient;
|
queryClient?: QueryClient;
|
||||||
|
currentPath?: string;
|
||||||
|
routeHandler?: (path: string) => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<QueryProvider client={queryClient}>
|
<QueryProvider client={queryClient}>
|
||||||
@@ -20,7 +24,7 @@ export function BaseLayout({
|
|||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Header />
|
<Header />
|
||||||
<div className="flex h-[calc(100vh-50px)]">
|
<div className="flex h-[calc(100vh-50px)]">
|
||||||
<LNB />
|
<LNB currentPath={currentPath} routeHandler={routeHandler} />
|
||||||
<div className="flex flex-1 flex-col">
|
<div className="flex flex-1 flex-col">
|
||||||
<div className="max-h-[calc(100%-50px)] flex-1 overflow-auto">
|
<div className="max-h-[calc(100%-50px)] flex-1 overflow-auto">
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { ChevronRight } from "lucide-react";
|
import { ChevronRight } from "lucide-react";
|
||||||
import { cn } from "../../lib/utils";
|
import { cn, setCookie } from "../../lib";
|
||||||
import { ENDPOINT, SITE_ID } from "../../config";
|
import { ENDPOINT, SITE_ID } from "../../config";
|
||||||
import { getMenuList, type MenuItem } from "../../api";
|
import { getMenuList, type MenuItem } from "../../api";
|
||||||
import {
|
import {
|
||||||
@@ -19,7 +19,15 @@ import {
|
|||||||
} from "../collapsible";
|
} from "../collapsible";
|
||||||
import { getParentIds } from "./lib";
|
import { getParentIds } from "./lib";
|
||||||
|
|
||||||
export function LNB({ viewOnly }: { viewOnly?: boolean }) {
|
export function LNB({
|
||||||
|
viewOnly,
|
||||||
|
currentPath,
|
||||||
|
routeHandler,
|
||||||
|
}: {
|
||||||
|
viewOnly?: boolean;
|
||||||
|
currentPath?: string;
|
||||||
|
routeHandler?: (path: string) => void;
|
||||||
|
}) {
|
||||||
const { data: menuList } = useQuery({
|
const { data: menuList } = useQuery({
|
||||||
queryKey: [ENDPOINT.CMS_SERVICE.MENU_ROLES],
|
queryKey: [ENDPOINT.CMS_SERVICE.MENU_ROLES],
|
||||||
queryFn: () => getMenuList(SITE_ID),
|
queryFn: () => getMenuList(SITE_ID),
|
||||||
@@ -28,14 +36,31 @@ export function LNB({ viewOnly }: { viewOnly?: boolean }) {
|
|||||||
|
|
||||||
const [openMenuIds, setOpenMenuIds] = useState<number[]>([]);
|
const [openMenuIds, setOpenMenuIds] = useState<number[]>([]);
|
||||||
|
|
||||||
|
function isPathMatched(path: string) {
|
||||||
|
return currentPath === path || currentPath?.startsWith(`${path}/`);
|
||||||
|
}
|
||||||
|
|
||||||
function MenuItem({ item }: { item: MenuItem }) {
|
function MenuItem({ item }: { item: MenuItem }) {
|
||||||
|
const isMatched = isPathMatched(item.urlPath);
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
setCookie("menu-code-key", item.menuCd.toString());
|
||||||
|
routeHandler?.(item.urlPath);
|
||||||
|
};
|
||||||
|
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
return <MenuGroup item={item} />;
|
return <MenuGroup item={item} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarMenuButton className="h-auto py-4 text-[1.4rem] text-label transition-colors hover:bg-accent">
|
<SidebarMenuButton
|
||||||
|
className={cn(
|
||||||
|
"h-auto py-4 text-[1.4rem] text-label transition-colors hover:bg-accent",
|
||||||
|
isMatched && "bg-accent text-primary",
|
||||||
|
)}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
<i className={cn("diveicon ml-2", `di-${item.iconNm}`)} />
|
<i className={cn("diveicon ml-2", `di-${item.iconNm}`)} />
|
||||||
{item.menuKornNm}
|
{item.menuKornNm}
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
@@ -44,7 +69,11 @@ export function LNB({ viewOnly }: { viewOnly?: boolean }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function MenuGroup({ item }: { item: MenuItem }) {
|
function MenuGroup({ item }: { item: MenuItem }) {
|
||||||
const isOpen = openMenuIds.includes(item.menuCd);
|
const hasMatchedChild = item.children?.some((child) =>
|
||||||
|
isPathMatched(child.urlPath),
|
||||||
|
);
|
||||||
|
|
||||||
|
const isOpen = openMenuIds.includes(item.menuCd) || hasMatchedChild;
|
||||||
|
|
||||||
const handleOpenChange = (open: boolean) => {
|
const handleOpenChange = (open: boolean) => {
|
||||||
if (open) {
|
if (open) {
|
||||||
|
|||||||
Reference in New Issue
Block a user