Files
invyone/frontend/components/screen/ViewTabBar.tsx
T
DDD1542 3eda684787
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m22s
사용자 대시보드 기능강화 및 인비온 스튜디오 메뉴관리 자잘한수정
2026-04-22 18:27:06 +09:00

73 lines
2.1 KiB
TypeScript

"use client";
import { cn } from "@/lib/utils";
import { List, PlusCircle, Pencil } from "lucide-react";
export type ViewType = "list" | "create" | "edit";
interface ViewTab {
id: ViewType;
label: string;
icon: React.ReactNode;
hint: string;
}
const VIEW_TABS: ViewTab[] = [
{ id: "list", label: "목록 화면", icon: <List size={13} />, hint: "목록 + 검색 + 그리드" },
{ id: "create", label: "등록 팝업", icon: <PlusCircle size={13} />, hint: "등록 팝업 편집" },
{ id: "edit", label: "수정 팝업", icon: <Pencil size={13} />, hint: "수정 팝업 편집" },
];
interface ViewTabBarProps {
activeView: ViewType;
onViewChange: (view: ViewType) => void;
/** 각 뷰에 컴포넌트가 있는지 (뱃지 표시용) */
viewCounts?: Record<ViewType, number>;
/**
* 표시할 뷰 탭. 생략 시 전체 표시.
* list 는 항상 포함 (루트). create/edit 는 목록 뷰에
* 해당 actionType 버튼이 배치됐을 때만 포함되는 식으로
* 부모에서 결정한다.
*/
visibleViews?: ViewType[];
}
export function ViewTabBar({
activeView,
onViewChange,
viewCounts,
visibleViews,
}: ViewTabBarProps) {
const tabs = visibleViews
? VIEW_TABS.filter((t) => visibleViews.includes(t.id))
: VIEW_TABS;
const activeTab = tabs.find((t) => t.id === activeView);
return (
<div className="view-tab-bar">
<div className="view-tab-group">
{tabs.map((tab) => {
const count = viewCounts?.[tab.id] ?? 0;
const isActive = tab.id === activeView;
return (
<button
key={tab.id}
type="button"
className={cn("view-tab", isActive && "active")}
onClick={() => onViewChange(tab.id)}
>
{tab.icon}
<span>{tab.label}</span>
{count > 0 && (
<span className="view-tab-badge">{count}</span>
)}
</button>
);
})}
</div>
<span className="view-tab-hint">{activeTab?.hint}</span>
</div>
);
}