ERP-node/frontend/components/screen/config-panels/ImprovedButtonControlConfig...

282 lines
9.9 KiB
TypeScript

"use client";
import React, { useState, useEffect } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import {
Settings,
GitBranch,
Clock,
Zap,
Info
} from "lucide-react";
import { ComponentData, ButtonDataflowConfig } from "@/types/screen";
import { apiClient } from "@/lib/api/client";
interface ImprovedButtonControlConfigPanelProps {
component: ComponentData;
onUpdateProperty: (path: string, value: any) => void;
}
interface RelationshipOption {
id: string;
name: string;
sourceTable: string;
targetTable: string;
category: string;
}
/**
* 🔥 단순화된 버튼 제어 설정 패널
*
* 관계 실행만 지원:
* - 관계 선택 및 실행 타이밍 설정
* - 관계 내부에 데이터 저장/외부호출 로직 포함
*/
export const ImprovedButtonControlConfigPanel: React.FC<ImprovedButtonControlConfigPanelProps> = ({
component,
onUpdateProperty,
}) => {
const config = component.webTypeConfig || {};
const dataflowConfig = config.dataflowConfig || {};
// 🔥 State 관리
const [relationships, setRelationships] = useState<RelationshipOption[]>([]);
const [loading, setLoading] = useState(false);
// 🔥 관계 목록 로딩
useEffect(() => {
if (config.enableDataflowControl) {
loadRelationships();
}
}, [config.enableDataflowControl]);
/**
* 🔥 전체 관계 목록 로드 (관계도별 구분 없이)
*/
const loadRelationships = async () => {
try {
setLoading(true);
console.log("🔍 전체 관계 목록 로딩...");
const response = await apiClient.get("/test-button-dataflow/relationships/all");
if (response.data.success && Array.isArray(response.data.data)) {
const relationshipList = response.data.data.map((rel: any) => ({
id: rel.id,
name: rel.name || `${rel.sourceTable}${rel.targetTable}`,
sourceTable: rel.sourceTable,
targetTable: rel.targetTable,
category: rel.category || "데이터 흐름",
}));
setRelationships(relationshipList);
console.log(`✅ 관계 ${relationshipList.length}개 로딩 완료`);
}
} catch (error) {
console.error("❌ 관계 목록 로딩 실패:", error);
setRelationships([]);
} finally {
setLoading(false);
}
};
/**
* 🔥 관계 선택 핸들러
*/
const handleRelationshipSelect = (relationshipId: string) => {
const selectedRelationship = relationships.find(r => r.id === relationshipId);
if (selectedRelationship) {
onUpdateProperty("webTypeConfig.dataflowConfig.relationshipConfig", {
relationshipId: selectedRelationship.id,
relationshipName: selectedRelationship.name,
executionTiming: "after", // 기본값
contextData: {},
});
}
};
/**
* 🔥 제어 타입 변경 핸들러
*/
const handleControlTypeChange = (controlType: string) => {
// 기존 설정 초기화
onUpdateProperty("webTypeConfig.dataflowConfig", {
controlMode: controlType,
relationshipConfig: controlType === "relationship" ? undefined : null,
});
};
return (
<div className="space-y-6">
{/* 🔥 제어관리 활성화 스위치 */}
<div className="flex items-center justify-between rounded-lg border bg-blue-50 p-4">
<div className="flex items-center space-x-2">
<Settings className="h-4 w-4 text-blue-600" />
<div>
<Label className="text-sm font-medium">🎮 </Label>
<p className="mt-1 text-xs text-gray-600"> </p>
</div>
</div>
<Switch
checked={config.enableDataflowControl || false}
onCheckedChange={(checked) => onUpdateProperty("webTypeConfig.enableDataflowControl", checked)}
/>
</div>
{/* 🔥 제어관리가 활성화된 경우에만 설정 표시 */}
{config.enableDataflowControl && (
<Card>
<CardHeader>
<CardTitle> </CardTitle>
</CardHeader>
<CardContent>
<Tabs
value={dataflowConfig.controlMode || "none"}
onValueChange={handleControlTypeChange}
>
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="none"> </TabsTrigger>
<TabsTrigger value="relationship"> </TabsTrigger>
</TabsList>
<TabsContent value="none" className="mt-4">
<div className="text-center py-8 text-gray-500">
<Zap className="h-8 w-8 mx-auto mb-2 opacity-50" />
<p> .</p>
</div>
</TabsContent>
<TabsContent value="relationship" className="mt-4">
<RelationshipSelector
relationships={relationships}
selectedRelationshipId={dataflowConfig.relationshipConfig?.relationshipId}
onSelect={handleRelationshipSelect}
loading={loading}
/>
{dataflowConfig.relationshipConfig && (
<div className="mt-4 space-y-4">
<Separator />
<ExecutionTimingSelector
value={dataflowConfig.relationshipConfig.executionTiming}
onChange={(timing) =>
onUpdateProperty("webTypeConfig.dataflowConfig.relationshipConfig.executionTiming", timing)
}
/>
<div className="rounded bg-blue-50 p-3">
<div className="flex items-start space-x-2">
<Info className="h-4 w-4 text-blue-600 mt-0.5" />
<div className="text-xs text-blue-800">
<p className="font-medium"> :</p>
<p className="mt-1"> , .</p>
</div>
</div>
</div>
</div>
)}
</TabsContent>
</Tabs>
</CardContent>
</Card>
)}
</div>
);
};
/**
* 🔥 관계 선택 컴포넌트
*/
const RelationshipSelector: React.FC<{
relationships: RelationshipOption[];
selectedRelationshipId?: string;
onSelect: (relationshipId: string) => void;
loading: boolean;
}> = ({ relationships, selectedRelationshipId, onSelect, loading }) => {
return (
<div className="space-y-4">
<div className="flex items-center space-x-2">
<GitBranch className="h-4 w-4 text-blue-600" />
<Label> </Label>
</div>
<Select value={selectedRelationshipId || ""} onValueChange={onSelect}>
<SelectTrigger>
<SelectValue placeholder="관계를 선택하세요" />
</SelectTrigger>
<SelectContent>
{loading ? (
<div className="p-4 text-center text-sm text-gray-500"> ...</div>
) : relationships.length === 0 ? (
<div className="p-4 text-center text-sm text-gray-500"> </div>
) : (
relationships.map((rel) => (
<SelectItem key={rel.id} value={rel.id}>
<div className="flex flex-col">
<span className="font-medium">{rel.name}</span>
<span className="text-xs text-muted-foreground">
{rel.sourceTable} {rel.targetTable}
</span>
</div>
</SelectItem>
))
)}
</SelectContent>
</Select>
</div>
);
};
/**
* 🔥 실행 타이밍 선택 컴포넌트
*/
const ExecutionTimingSelector: React.FC<{
value: string;
onChange: (timing: "before" | "after" | "replace") => void;
}> = ({ value, onChange }) => {
return (
<div className="space-y-2">
<div className="flex items-center space-x-2">
<Clock className="h-4 w-4 text-orange-600" />
<Label> </Label>
</div>
<Select value={value} onValueChange={onChange}>
<SelectTrigger>
<SelectValue placeholder="실행 타이밍을 선택하세요" />
</SelectTrigger>
<SelectContent>
<SelectItem value="before">
<div className="flex flex-col">
<span className="font-medium">Before ( )</span>
<span className="text-xs text-muted-foreground"> </span>
</div>
</SelectItem>
<SelectItem value="after">
<div className="flex flex-col">
<span className="font-medium">After ( )</span>
<span className="text-xs text-muted-foreground"> </span>
</div>
</SelectItem>
<SelectItem value="replace">
<div className="flex flex-col">
<span className="font-medium">Replace ( )</span>
<span className="text-xs text-muted-foreground"> </span>
</div>
</SelectItem>
</SelectContent>
</Select>
</div>
);
};