350 lines
10 KiB
TypeScript
350 lines
10 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* UnifiedBiz
|
|
*
|
|
* 통합 비즈니스 컴포넌트
|
|
* - flow: 플로우/워크플로우
|
|
* - rack: 랙 구조
|
|
* - map: 맵/위치
|
|
* - numbering: 채번 규칙
|
|
* - category: 카테고리 관리
|
|
* - mapping: 데이터 매핑
|
|
* - related-buttons: 관련 데이터 버튼
|
|
*/
|
|
|
|
import React, { forwardRef } from "react";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { cn } from "@/lib/utils";
|
|
import { UnifiedBizProps } from "@/types/unified-components";
|
|
import {
|
|
GitBranch,
|
|
LayoutGrid,
|
|
MapPin,
|
|
Hash,
|
|
FolderTree,
|
|
Link2,
|
|
FileText,
|
|
ArrowRight
|
|
} from "lucide-react";
|
|
|
|
/**
|
|
* 플로우 컴포넌트 (플레이스홀더)
|
|
* 실제 구현은 기존 FlowWidget과 연동
|
|
*/
|
|
const FlowBiz = forwardRef<HTMLDivElement, {
|
|
config?: Record<string, unknown>;
|
|
className?: string;
|
|
}>(({ config, className }, ref) => {
|
|
return (
|
|
<Card ref={ref} className={className}>
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="text-base flex items-center gap-2">
|
|
<GitBranch className="h-4 w-4" />
|
|
플로우
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="h-48 border-2 border-dashed rounded-lg flex items-center justify-center text-muted-foreground">
|
|
<div className="text-center">
|
|
<GitBranch className="h-8 w-8 mx-auto mb-2" />
|
|
<p className="text-sm">플로우 디자이너</p>
|
|
<p className="text-xs">기존 FlowWidget과 연동</p>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
});
|
|
FlowBiz.displayName = "FlowBiz";
|
|
|
|
/**
|
|
* 랙 구조 컴포넌트 (플레이스홀더)
|
|
* 실제 구현은 기존 RackStructure와 연동
|
|
*/
|
|
const RackBiz = forwardRef<HTMLDivElement, {
|
|
config?: Record<string, unknown>;
|
|
className?: string;
|
|
}>(({ config, className }, ref) => {
|
|
return (
|
|
<Card ref={ref} className={className}>
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="text-base flex items-center gap-2">
|
|
<LayoutGrid className="h-4 w-4" />
|
|
랙 구조
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="h-48 border-2 border-dashed rounded-lg flex items-center justify-center text-muted-foreground">
|
|
<div className="text-center">
|
|
<LayoutGrid className="h-8 w-8 mx-auto mb-2" />
|
|
<p className="text-sm">랙 구조 뷰어</p>
|
|
<p className="text-xs">기존 RackStructure와 연동</p>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
});
|
|
RackBiz.displayName = "RackBiz";
|
|
|
|
/**
|
|
* 맵 컴포넌트 (플레이스홀더)
|
|
*/
|
|
const MapBiz = forwardRef<HTMLDivElement, {
|
|
config?: Record<string, unknown>;
|
|
className?: string;
|
|
}>(({ config, className }, ref) => {
|
|
return (
|
|
<Card ref={ref} className={className}>
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="text-base flex items-center gap-2">
|
|
<MapPin className="h-4 w-4" />
|
|
위치 맵
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="h-48 border-2 border-dashed rounded-lg flex items-center justify-center text-muted-foreground">
|
|
<div className="text-center">
|
|
<MapPin className="h-8 w-8 mx-auto mb-2" />
|
|
<p className="text-sm">위치 맵 뷰어</p>
|
|
<p className="text-xs">지도 라이브러리 연동 예정</p>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
});
|
|
MapBiz.displayName = "MapBiz";
|
|
|
|
/**
|
|
* 채번 규칙 컴포넌트 (플레이스홀더)
|
|
* 실제 구현은 기존 NumberingRuleComponent와 연동
|
|
*/
|
|
const NumberingBiz = forwardRef<HTMLDivElement, {
|
|
config?: Record<string, unknown>;
|
|
className?: string;
|
|
}>(({ config, className }, ref) => {
|
|
return (
|
|
<Card ref={ref} className={className}>
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="text-base flex items-center gap-2">
|
|
<Hash className="h-4 w-4" />
|
|
채번 규칙
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-3">
|
|
<div className="flex items-center justify-between p-3 bg-muted/50 rounded-lg">
|
|
<div>
|
|
<p className="font-medium text-sm">자동 채번</p>
|
|
<p className="text-xs text-muted-foreground">규칙에 따라 자동 생성</p>
|
|
</div>
|
|
<div className="font-mono text-sm bg-background px-2 py-1 rounded border">
|
|
PO-2024-0001
|
|
</div>
|
|
</div>
|
|
<p className="text-xs text-muted-foreground text-center">
|
|
기존 NumberingRuleComponent와 연동
|
|
</p>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
});
|
|
NumberingBiz.displayName = "NumberingBiz";
|
|
|
|
/**
|
|
* 카테고리 관리 컴포넌트 (플레이스홀더)
|
|
* 실제 구현은 기존 CategoryManager와 연동
|
|
*/
|
|
const CategoryBiz = forwardRef<HTMLDivElement, {
|
|
config?: Record<string, unknown>;
|
|
className?: string;
|
|
}>(({ config, className }, ref) => {
|
|
return (
|
|
<Card ref={ref} className={className}>
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="text-base flex items-center gap-2">
|
|
<FolderTree className="h-4 w-4" />
|
|
카테고리
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-2">
|
|
<div className="pl-0 py-1 px-2 bg-muted/50 rounded">
|
|
<span className="text-sm">대분류</span>
|
|
</div>
|
|
<div className="pl-4 py-1 px-2 text-sm text-muted-foreground">
|
|
└ 중분류
|
|
</div>
|
|
<div className="pl-8 py-1 px-2 text-sm text-muted-foreground">
|
|
└ 소분류
|
|
</div>
|
|
<p className="text-xs text-muted-foreground text-center mt-3">
|
|
기존 CategoryManager와 연동
|
|
</p>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
});
|
|
CategoryBiz.displayName = "CategoryBiz";
|
|
|
|
/**
|
|
* 데이터 매핑 컴포넌트 (플레이스홀더)
|
|
*/
|
|
const MappingBiz = forwardRef<HTMLDivElement, {
|
|
config?: Record<string, unknown>;
|
|
className?: string;
|
|
}>(({ config, className }, ref) => {
|
|
return (
|
|
<Card ref={ref} className={className}>
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="text-base flex items-center gap-2">
|
|
<Link2 className="h-4 w-4" />
|
|
데이터 매핑
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex items-center gap-4 justify-center p-4">
|
|
<div className="text-center">
|
|
<div className="w-20 h-20 border-2 rounded-lg flex items-center justify-center mb-2">
|
|
<FileText className="h-6 w-6 text-muted-foreground" />
|
|
</div>
|
|
<p className="text-xs text-muted-foreground">소스</p>
|
|
</div>
|
|
<ArrowRight className="h-6 w-6 text-muted-foreground" />
|
|
<div className="text-center">
|
|
<div className="w-20 h-20 border-2 rounded-lg flex items-center justify-center mb-2">
|
|
<FileText className="h-6 w-6 text-muted-foreground" />
|
|
</div>
|
|
<p className="text-xs text-muted-foreground">대상</p>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
});
|
|
MappingBiz.displayName = "MappingBiz";
|
|
|
|
/**
|
|
* 관련 데이터 버튼 컴포넌트 (플레이스홀더)
|
|
*/
|
|
const RelatedButtonsBiz = forwardRef<HTMLDivElement, {
|
|
config?: Record<string, unknown>;
|
|
className?: string;
|
|
}>(({ config, className }, ref) => {
|
|
const buttons = (config?.buttons as Array<{ label: string; icon?: string }>) || [
|
|
{ label: "관련 주문" },
|
|
{ label: "관련 출고" },
|
|
{ label: "이력 보기" },
|
|
];
|
|
|
|
return (
|
|
<div ref={ref} className={cn("flex flex-wrap gap-2", className)}>
|
|
{buttons.map((button, index) => (
|
|
<Button key={index} variant="outline" size="sm">
|
|
{button.label}
|
|
</Button>
|
|
))}
|
|
</div>
|
|
);
|
|
});
|
|
RelatedButtonsBiz.displayName = "RelatedButtonsBiz";
|
|
|
|
/**
|
|
* 메인 UnifiedBiz 컴포넌트
|
|
*/
|
|
export const UnifiedBiz = forwardRef<HTMLDivElement, UnifiedBizProps>(
|
|
(props, ref) => {
|
|
const {
|
|
id,
|
|
label,
|
|
style,
|
|
size,
|
|
config: configProp,
|
|
} = props;
|
|
|
|
// config가 없으면 기본값 사용
|
|
const config = configProp || { type: "flow" as const };
|
|
|
|
// 타입별 비즈니스 컴포넌트 렌더링
|
|
const renderBiz = () => {
|
|
const bizConfig = config.config || {};
|
|
const bizType = config.type || "flow";
|
|
|
|
switch (bizType) {
|
|
case "flow":
|
|
return <FlowBiz config={bizConfig} />;
|
|
|
|
case "rack":
|
|
return <RackBiz config={bizConfig} />;
|
|
|
|
case "map":
|
|
return <MapBiz config={bizConfig} />;
|
|
|
|
case "numbering":
|
|
return <NumberingBiz config={bizConfig} />;
|
|
|
|
case "category":
|
|
return <CategoryBiz config={bizConfig} />;
|
|
|
|
case "mapping":
|
|
return <MappingBiz config={bizConfig} />;
|
|
|
|
case "related-buttons":
|
|
return <RelatedButtonsBiz config={bizConfig} />;
|
|
|
|
default:
|
|
return (
|
|
<div className="p-4 border rounded text-center text-muted-foreground">
|
|
알 수 없는 비즈니스 타입: {config.type}
|
|
</div>
|
|
);
|
|
}
|
|
};
|
|
|
|
const showLabel = label && style?.labelDisplay !== false;
|
|
const componentWidth = size?.width || style?.width;
|
|
const componentHeight = size?.height || style?.height;
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
id={id}
|
|
className="flex flex-col"
|
|
style={{
|
|
width: componentWidth,
|
|
height: componentHeight,
|
|
}}
|
|
>
|
|
{showLabel && (
|
|
<Label
|
|
htmlFor={id}
|
|
style={{
|
|
fontSize: style?.labelFontSize,
|
|
color: style?.labelColor,
|
|
fontWeight: style?.labelFontWeight,
|
|
marginBottom: style?.labelMarginBottom,
|
|
}}
|
|
className="text-sm font-medium flex-shrink-0"
|
|
>
|
|
{label}
|
|
</Label>
|
|
)}
|
|
<div className="flex-1 min-h-0">
|
|
{renderBiz()}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
);
|
|
|
|
UnifiedBiz.displayName = "UnifiedBiz";
|
|
|
|
export default UnifiedBiz;
|
|
|