feat: [생산현황판] 절곡 탭 depth 구조 — 재공품 하위 탭 분리

- 절곡 계열 공정을 부모(절곡) + 하위(가이드레일/케이스/하단마감재/기타) 구조로 그룹화
- 상위 탭에서 절곡 선택 시 하위 탭 표시
- TabOption에 children 필드 추가
- 재공품 라벨 간소화: "절곡 (재공품-가이드레일)" → "가이드레일"
This commit is contained in:
김보곤
2026-03-22 17:16:37 +09:00
parent 2af2a6760e
commit 610d12f4d3
2 changed files with 74 additions and 20 deletions

View File

@@ -57,13 +57,34 @@ export default function ProductionDashboard() {
const result = await getProcessOptions();
if (result.success) {
setProcessOptions(result.data);
// 동적 탭 옵션 생성: 전체 + 공정 목록
// 동적 탭 옵션 생성: 전체 + 공정 목록 (절곡 계열은 하위 탭으로 그룹화)
const bendingParent: TabOption[] = [];
const bendingChildren: TabOption[] = [];
const otherTabs: TabOption[] = [];
for (const p of result.data) {
if (p.name.startsWith('절곡')) {
if (p.name === '절곡') {
bendingParent.push({ value: p.code, label: p.name });
} else {
// "절곡 (재공품-가이드레일)" → "가이드레일"
const shortLabel = p.name.replace(/^절곡\s*\(재공품-?/, '').replace(/\)$/, '') || p.name;
bendingChildren.push({ value: p.code, label: shortLabel });
}
} else {
otherTabs.push({ value: p.code, label: p.name });
}
}
// 절곡 부모에 하위 탭 연결
const bendingTab: TabOption | null = bendingParent.length > 0
? { ...bendingParent[0], children: bendingChildren.length > 0 ? bendingChildren : undefined }
: null;
const dynamicTabs: TabOption[] = [
{ value: 'all', label: '전체' },
...result.data.map((p) => ({
value: p.code,
label: p.name,
})),
...otherTabs,
...(bendingTab ? [bendingTab] : []),
];
setTabOptions(dynamicTabs);
} else {
@@ -170,21 +191,53 @@ export default function ProductionDashboard() {
</div>
</div>
{/* 공정별 탭 (동적 생성) */}
<div className="overflow-x-auto -mx-3 px-3 md:mx-0 md:px-0">
<Tabs value={selectedTab} onValueChange={setSelectedTab}>
<TabsList className="w-max">
{isLoadingProcesses ? (
<TabsTrigger value="all" className="px-6"></TabsTrigger>
) : (
tabOptions.map((tab) => (
<TabsTrigger key={tab.value} value={tab.value} className="px-4 sm:px-6">
{tab.label}
</TabsTrigger>
))
)}
</TabsList>
</Tabs>
{/* 공정별 탭 (동적 생성, 절곡은 depth 구조) */}
<div className="space-y-1">
<div className="overflow-x-auto -mx-3 px-3 md:mx-0 md:px-0">
<Tabs value={
// 하위 탭 선택 시 부모 탭을 활성화
tabOptions.find(t => t.children?.some(c => c.value === selectedTab))?.value || selectedTab
} onValueChange={(v) => {
// 하위 탭이 있는 부모 선택 시 부모 값으로 설정
setSelectedTab(v);
}}>
<TabsList className="w-max">
{isLoadingProcesses ? (
<TabsTrigger value="all" className="px-6"></TabsTrigger>
) : (
tabOptions.map((tab) => (
<TabsTrigger key={tab.value} value={tab.value} className="px-4 sm:px-6">
{tab.label}
</TabsTrigger>
))
)}
</TabsList>
</Tabs>
</div>
{/* 하위 탭 (절곡 재공품 세분화) */}
{(() => {
const parentTab = tabOptions.find(t => t.children && t.children.length > 0 &&
(t.value === selectedTab || t.children.some(c => c.value === selectedTab))
);
if (!parentTab?.children) return null;
return (
<div className="overflow-x-auto -mx-3 px-3 md:mx-0 md:px-0">
<Tabs value={selectedTab} onValueChange={setSelectedTab}>
<TabsList className="w-max h-8 bg-gray-100">
<TabsTrigger value={parentTab.value} className="px-3 text-xs h-7">
</TabsTrigger>
{parentTab.children.map((sub) => (
<TabsTrigger key={sub.value} value={sub.value} className="px-3 text-xs h-7">
{sub.label}
</TabsTrigger>
))}
</TabsList>
</Tabs>
</div>
);
})()}
</div>
{/* 로딩 상태 */}

View File

@@ -97,6 +97,7 @@ export interface DashboardStats {
export interface TabOption {
value: string; // 'all' 또는 process_code
label: string; // '전체' 또는 process_name
children?: TabOption[]; // 하위 탭 (절곡 → 재공품 세분화)
}
// 상태 라벨