ui 수정 및 시현할 기능 업데이트
This commit is contained in:
@@ -273,7 +273,7 @@ const ActionConditionBuilder: React.FC<ActionConditionBuilderProps> = ({
|
||||
.map((column) => (
|
||||
<SelectItem key={`from_${column.columnName}`} value={`from.${column.columnName}`}>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-blue-600">📤</span>
|
||||
<span className="text-primary">📤</span>
|
||||
<span>{column.displayName || column.columnName}</span>
|
||||
<Badge variant="outline" className="text-xs">
|
||||
{column.webType || column.dataType}
|
||||
@@ -359,7 +359,7 @@ const ActionConditionBuilder: React.FC<ActionConditionBuilderProps> = ({
|
||||
|
||||
{/* 선택된 날짜 타입에 대한 설명 */}
|
||||
{mapping.value?.startsWith("#") && mapping.value !== "#custom" && (
|
||||
<div className="text-muted-foreground rounded bg-blue-50 p-2 text-xs">
|
||||
<div className="text-muted-foreground rounded bg-accent p-2 text-xs">
|
||||
{mapping.value === "#NOW" && "⏰ 현재 날짜와 시간이 저장됩니다"}
|
||||
{mapping.value === "#TODAY" && "📅 현재 날짜 (00:00:00)가 저장됩니다"}
|
||||
{mapping.value === "#YESTERDAY" && "📅 어제 날짜가 저장됩니다"}
|
||||
@@ -497,7 +497,7 @@ const ActionConditionBuilder: React.FC<ActionConditionBuilderProps> = ({
|
||||
.map((column) => (
|
||||
<SelectItem key={`from_${column.columnName}`} value={`from.${column.columnName}`}>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-blue-600">📤</span>
|
||||
<span className="text-primary">📤</span>
|
||||
<span>{column.displayName || column.columnName}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
@@ -625,7 +625,7 @@ const ActionConditionBuilder: React.FC<ActionConditionBuilderProps> = ({
|
||||
.map((column) => (
|
||||
<SelectItem key={`from_${column.columnName}`} value={`from.${column.columnName}`}>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-blue-600">📤</span>
|
||||
<span className="text-primary">📤</span>
|
||||
<span>{column.displayName || column.columnName}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
|
||||
@@ -80,7 +80,7 @@ export const ConnectionStep: React.FC<ConnectionStepProps> = ({
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">
|
||||
연결 선택
|
||||
</h2>
|
||||
<p className="text-gray-600">
|
||||
<p className="text-muted-foreground">
|
||||
데이터를 가져올 연결과 저장할 연결을 선택하세요
|
||||
</p>
|
||||
</div>
|
||||
@@ -89,8 +89,8 @@ export const ConnectionStep: React.FC<ConnectionStepProps> = ({
|
||||
{/* FROM 연결 */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
|
||||
<span className="text-blue-600 font-bold">1</span>
|
||||
<div className="w-8 h-8 bg-primary/20 rounded-full flex items-center justify-center">
|
||||
<span className="text-primary font-bold">1</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">FROM 연결</h3>
|
||||
<span className="text-sm text-gray-500">(데이터 소스)</span>
|
||||
@@ -102,20 +102,20 @@ export const ConnectionStep: React.FC<ConnectionStepProps> = ({
|
||||
key={connection.id}
|
||||
className={`p-4 rounded-lg border-2 cursor-pointer transition-all duration-200 ${
|
||||
selectedFrom === connection.id
|
||||
? "border-blue-500 bg-blue-50 shadow-md"
|
||||
? "border-primary bg-accent shadow-md"
|
||||
: "border-gray-200 bg-white hover:border-blue-300 hover:bg-blue-25"
|
||||
}`}
|
||||
onClick={() => handleFromSelect(connection.id)}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<Database className="w-6 h-6 text-blue-600" />
|
||||
<Database className="w-6 h-6 text-primary" />
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-gray-900">{connection.name}</h4>
|
||||
<p className="text-sm text-gray-600">{connection.type}</p>
|
||||
<p className="text-sm text-muted-foreground">{connection.type}</p>
|
||||
<p className="text-xs text-gray-500">{connection.host}:{connection.port}</p>
|
||||
</div>
|
||||
{selectedFrom === connection.id && (
|
||||
<CheckCircle className="w-5 h-5 text-blue-600" />
|
||||
<CheckCircle className="w-5 h-5 text-primary" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -155,7 +155,7 @@ export const ConnectionStep: React.FC<ConnectionStepProps> = ({
|
||||
<Database className="w-6 h-6 text-green-600" />
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-gray-900">{connection.name}</h4>
|
||||
<p className="text-sm text-gray-600">{connection.type}</p>
|
||||
<p className="text-sm text-muted-foreground">{connection.type}</p>
|
||||
<p className="text-xs text-gray-500">{connection.host}:{connection.port}</p>
|
||||
</div>
|
||||
{selectedTo === connection.id && (
|
||||
|
||||
@@ -148,7 +148,7 @@ const ControlConditionStep: React.FC<ControlConditionStepProps> = ({ state, acti
|
||||
<CardContent className="flex h-full flex-col overflow-hidden p-0">
|
||||
<div className="min-h-0 flex-1 space-y-6 overflow-y-auto p-4">
|
||||
{/* 제어 실행 조건 안내 */}
|
||||
<div className="rounded-lg border border-blue-200 bg-blue-50 p-4">
|
||||
<div className="rounded-lg border border-primary/20 bg-accent p-4">
|
||||
<h4 className="mb-2 text-sm font-medium text-blue-800">제어 실행 조건이란?</h4>
|
||||
<div className="space-y-1 text-sm text-blue-700">
|
||||
<p>
|
||||
@@ -363,7 +363,7 @@ const ControlConditionStep: React.FC<ControlConditionStepProps> = ({ state, acti
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => actions.deleteControlCondition(index)}
|
||||
className="text-red-600 hover:text-red-700"
|
||||
className="text-destructive hover:text-red-700"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
@@ -71,14 +71,14 @@ export const FieldMappingStep: React.FC<FieldMappingStepProps> = ({
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">
|
||||
필드 매핑
|
||||
</h2>
|
||||
<p className="text-gray-600">
|
||||
<p className="text-muted-foreground">
|
||||
소스 테이블의 필드를 대상 테이블의 필드에 드래그하여 매핑하세요
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 매핑 통계 */}
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<div className="bg-blue-50 p-4 rounded-lg border border-blue-200">
|
||||
<div className="bg-accent p-4 rounded-lg border border-primary/20">
|
||||
<div className="text-2xl font-bold text-blue-900">{fieldMappings.length}</div>
|
||||
<div className="text-sm text-blue-700">총 매핑</div>
|
||||
</div>
|
||||
@@ -88,7 +88,7 @@ export const FieldMappingStep: React.FC<FieldMappingStepProps> = ({
|
||||
</div>
|
||||
<div className="text-sm text-green-700">유효한 매핑</div>
|
||||
</div>
|
||||
<div className="bg-red-50 p-4 rounded-lg border border-red-200">
|
||||
<div className="bg-destructive/10 p-4 rounded-lg border border-destructive/20">
|
||||
<div className="text-2xl font-bold text-red-900">
|
||||
{fieldMappings.filter(m => !m.isValid).length}
|
||||
</div>
|
||||
@@ -107,8 +107,8 @@ export const FieldMappingStep: React.FC<FieldMappingStepProps> = ({
|
||||
{/* FROM 테이블 필드들 */}
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-semibold text-gray-900 flex items-center gap-2">
|
||||
<div className="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center">
|
||||
<span className="text-blue-600 font-bold text-sm">FROM</span>
|
||||
<div className="w-6 h-6 bg-primary/20 rounded-full flex items-center justify-center">
|
||||
<span className="text-primary font-bold text-sm">FROM</span>
|
||||
</div>
|
||||
{fromTable?.name} 필드들
|
||||
</h3>
|
||||
@@ -122,13 +122,13 @@ export const FieldMappingStep: React.FC<FieldMappingStepProps> = ({
|
||||
className={`p-3 rounded-lg border-2 cursor-move transition-all duration-200 ${
|
||||
isFieldMapped(field.name)
|
||||
? "border-green-300 bg-green-50 opacity-60"
|
||||
: "border-blue-200 bg-blue-50 hover:border-blue-400 hover:bg-blue-100"
|
||||
: "border-primary/20 bg-accent hover:border-blue-400 hover:bg-primary/20"
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">{field.name}</div>
|
||||
<div className="text-sm text-gray-600">{field.type}</div>
|
||||
<div className="text-sm text-muted-foreground">{field.type}</div>
|
||||
{field.primaryKey && (
|
||||
<span className="text-xs bg-yellow-100 text-yellow-800 px-2 py-1 rounded">
|
||||
PK
|
||||
@@ -170,7 +170,7 @@ export const FieldMappingStep: React.FC<FieldMappingStepProps> = ({
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">{field.name}</div>
|
||||
<div className="text-sm text-gray-600">{field.type}</div>
|
||||
<div className="text-sm text-muted-foreground">{field.type}</div>
|
||||
{field.primaryKey && (
|
||||
<span className="text-xs bg-yellow-100 text-yellow-800 px-2 py-1 rounded">
|
||||
PK
|
||||
@@ -196,7 +196,7 @@ export const FieldMappingStep: React.FC<FieldMappingStepProps> = ({
|
||||
{fieldMappings.find(m => m.toField.name === field.name)?.isValid ? (
|
||||
<CheckCircle className="w-5 h-5 text-green-600" />
|
||||
) : (
|
||||
<AlertCircle className="w-5 h-5 text-red-600" />
|
||||
<AlertCircle className="w-5 h-5 text-destructive" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@@ -213,7 +213,7 @@ export const FieldMappingStep: React.FC<FieldMappingStepProps> = ({
|
||||
<div className="flex justify-between">
|
||||
<button
|
||||
onClick={onBack}
|
||||
className="flex items-center gap-2 px-6 py-3 rounded-lg font-medium text-gray-600 bg-gray-100 hover:bg-gray-200 transition-all duration-200"
|
||||
className="flex items-center gap-2 px-6 py-3 rounded-lg font-medium text-muted-foreground bg-gray-100 hover:bg-gray-200 transition-all duration-200"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
이전 단계
|
||||
|
||||
@@ -150,7 +150,7 @@ const MultiActionConfigStep: React.FC<MultiActionConfigStepProps> = ({
|
||||
const getLogicalOperatorColor = (operator: string) => {
|
||||
switch (operator) {
|
||||
case "AND":
|
||||
return "bg-blue-100 text-blue-800";
|
||||
return "bg-primary/20 text-blue-800";
|
||||
case "OR":
|
||||
return "bg-orange-100 text-orange-800";
|
||||
default:
|
||||
@@ -271,7 +271,7 @@ const MultiActionConfigStep: React.FC<MultiActionConfigStepProps> = ({
|
||||
|
||||
{/* 그룹 간 논리 연산자 선택 */}
|
||||
{actionGroups.length > 1 && (
|
||||
<div className="rounded-md border bg-blue-50 p-3">
|
||||
<div className="rounded-md border bg-accent p-3">
|
||||
<div className="mb-2 flex items-center gap-2">
|
||||
<h4 className="text-sm font-medium text-blue-900">그룹 간 실행 조건</h4>
|
||||
</div>
|
||||
@@ -649,9 +649,9 @@ const MultiActionConfigStep: React.FC<MultiActionConfigStepProps> = ({
|
||||
</div>
|
||||
|
||||
{/* 그룹 로직 설명 */}
|
||||
<div className="mt-4 rounded-md bg-blue-50 p-3">
|
||||
<div className="mt-4 rounded-md bg-accent p-3">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 text-blue-600" />
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 text-primary" />
|
||||
<div className="text-sm">
|
||||
<div className="font-medium text-blue-900">{group.logicalOperator} 조건 그룹</div>
|
||||
<div className="text-blue-700">
|
||||
|
||||
@@ -71,7 +71,7 @@ const RightPanel: React.FC<RightPanelProps> = ({ state, actions }) => {
|
||||
{/* 헤더 */}
|
||||
<div className="flex-shrink-0 px-4 py-2">
|
||||
<div className="flex items-center gap-3 border-b pb-2">
|
||||
<Globe className="h-5 w-5 text-blue-600" />
|
||||
<Globe className="h-5 w-5 text-primary" />
|
||||
<h2 className="text-lg font-semibold">외부 호출 설정</h2>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-1 text-sm">
|
||||
@@ -89,7 +89,7 @@ const RightPanel: React.FC<RightPanelProps> = ({ state, actions }) => {
|
||||
value={state.relationshipName || ""}
|
||||
onChange={(e) => actions.setRelationshipName(e.target.value)}
|
||||
placeholder="외부호출 관계의 이름을 입력하세요"
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-primary focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -99,7 +99,7 @@ const RightPanel: React.FC<RightPanelProps> = ({ state, actions }) => {
|
||||
onChange={(e) => actions.setDescription(e.target.value)}
|
||||
placeholder="외부호출의 용도나 설명을 입력하세요"
|
||||
rows={2}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-primary focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,7 @@ export const StepProgress: React.FC<StepProgressProps> = ({
|
||||
? "bg-green-500 text-white"
|
||||
: step.id === currentStep
|
||||
? "bg-orange-500 text-white"
|
||||
: "bg-gray-200 text-gray-600"
|
||||
: "bg-gray-200 text-muted-foreground"
|
||||
}`}
|
||||
>
|
||||
{step.id < currentStep ? (
|
||||
@@ -52,7 +52,7 @@ export const StepProgress: React.FC<StepProgressProps> = ({
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className={`text-xs ${
|
||||
step.id <= currentStep ? "text-gray-600" : "text-gray-400"
|
||||
step.id <= currentStep ? "text-muted-foreground" : "text-gray-400"
|
||||
}`}>
|
||||
{step.description}
|
||||
</p>
|
||||
|
||||
@@ -90,7 +90,7 @@ export const TableStep: React.FC<TableStepProps> = ({
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">
|
||||
테이블 선택
|
||||
</h2>
|
||||
<p className="text-gray-600">
|
||||
<p className="text-muted-foreground">
|
||||
소스 테이블과 대상 테이블을 선택하세요
|
||||
</p>
|
||||
</div>
|
||||
@@ -99,7 +99,7 @@ export const TableStep: React.FC<TableStepProps> = ({
|
||||
<div className="bg-gray-50 rounded-lg p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<Database className="w-5 h-5 text-blue-600" />
|
||||
<Database className="w-5 h-5 text-primary" />
|
||||
<span className="font-medium text-gray-900">{fromConnection?.name}</span>
|
||||
<span className="text-sm text-gray-500">→</span>
|
||||
<Database className="w-5 h-5 text-green-600" />
|
||||
@@ -112,8 +112,8 @@ export const TableStep: React.FC<TableStepProps> = ({
|
||||
{/* FROM 테이블 */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
|
||||
<span className="text-blue-600 font-bold">1</span>
|
||||
<div className="w-8 h-8 bg-primary/20 rounded-full flex items-center justify-center">
|
||||
<span className="text-primary font-bold">1</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">소스 테이블</h3>
|
||||
<span className="text-sm text-gray-500">(FROM)</span>
|
||||
@@ -125,20 +125,20 @@ export const TableStep: React.FC<TableStepProps> = ({
|
||||
key={table.name}
|
||||
className={`p-4 rounded-lg border-2 cursor-pointer transition-all duration-200 ${
|
||||
selectedFromTable === table.name
|
||||
? "border-blue-500 bg-blue-50 shadow-md"
|
||||
? "border-primary bg-accent shadow-md"
|
||||
: "border-gray-200 bg-white hover:border-blue-300 hover:bg-blue-25"
|
||||
}`}
|
||||
onClick={() => handleFromTableSelect(table.name)}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<Table className="w-6 h-6 text-blue-600" />
|
||||
<Table className="w-6 h-6 text-primary" />
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-gray-900">{table.name}</h4>
|
||||
<p className="text-sm text-gray-600">{table.columns.length}개 컬럼</p>
|
||||
<p className="text-sm text-muted-foreground">{table.columns.length}개 컬럼</p>
|
||||
<p className="text-xs text-gray-500">{table.rowCount?.toLocaleString()}개 행</p>
|
||||
</div>
|
||||
{selectedFromTable === table.name && (
|
||||
<CheckCircle className="w-5 h-5 text-blue-600" />
|
||||
<CheckCircle className="w-5 h-5 text-primary" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -171,7 +171,7 @@ export const TableStep: React.FC<TableStepProps> = ({
|
||||
<Table className="w-6 h-6 text-green-600" />
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-gray-900">{table.name}</h4>
|
||||
<p className="text-sm text-gray-600">{table.columns.length}개 컬럼</p>
|
||||
<p className="text-sm text-muted-foreground">{table.columns.length}개 컬럼</p>
|
||||
<p className="text-xs text-gray-500">{table.rowCount?.toLocaleString()}개 행</p>
|
||||
</div>
|
||||
{selectedToTable === table.name && (
|
||||
@@ -188,7 +188,7 @@ export const TableStep: React.FC<TableStepProps> = ({
|
||||
<div className="flex justify-between">
|
||||
<button
|
||||
onClick={onBack}
|
||||
className="flex items-center gap-2 px-6 py-3 rounded-lg font-medium text-gray-600 bg-gray-100 hover:bg-gray-200 transition-all duration-200"
|
||||
className="flex items-center gap-2 px-6 py-3 rounded-lg font-medium text-muted-foreground bg-gray-100 hover:bg-gray-200 transition-all duration-200"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
이전 단계
|
||||
|
||||
@@ -128,9 +128,9 @@ const FieldColumn: React.FC<FieldColumnProps> = ({
|
||||
: isMapped
|
||||
? "border-green-500 bg-green-50 shadow-sm"
|
||||
: isBlockedDropTarget
|
||||
? "border-red-400 bg-red-50 shadow-md"
|
||||
? "border-red-400 bg-destructive/10 shadow-md"
|
||||
: isDropTarget
|
||||
? "border-blue-400 bg-blue-50 shadow-md"
|
||||
? "border-blue-400 bg-accent shadow-md"
|
||||
: "border-border hover:bg-muted/50 hover:shadow-sm"
|
||||
} `}
|
||||
draggable={type === "from" && !isMapped}
|
||||
|
||||
@@ -311,7 +311,7 @@ const FieldMappingCanvas: React.FC<FieldMappingCanvasProps> = ({
|
||||
</div>
|
||||
|
||||
{/* 매핑 규칙 안내 */}
|
||||
<div className="mt-4 rounded-lg border border-blue-200 bg-blue-50 p-3">
|
||||
<div className="mt-4 rounded-lg border border-primary/20 bg-accent p-3">
|
||||
<h4 className="mb-2 text-sm font-medium">📋 매핑 규칙</h4>
|
||||
<div className="text-muted-foreground space-y-1 text-xs">
|
||||
<p>✅ 1:N 매핑 허용 (하나의 소스 필드를 여러 대상 필드에 매핑)</p>
|
||||
|
||||
Reference in New Issue
Block a user