91 lines
3.2 KiB
TypeScript
91 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { CheckCircle, Circle, ArrowRight } from "lucide-react";
|
|
|
|
// 타입 import
|
|
import { StepProgressProps } from "../types/redesigned";
|
|
|
|
/**
|
|
* 📊 단계 진행 표시
|
|
* - 현재 단계 하이라이트
|
|
* - 완료된 단계 체크 표시
|
|
* - 클릭으로 단계 이동
|
|
*/
|
|
const StepProgress: React.FC<StepProgressProps> = ({ currentStep, completedSteps, onStepClick }) => {
|
|
const steps = [
|
|
{ number: 1, title: "연결 선택", description: "FROM/TO 데이터베이스 연결" },
|
|
{ number: 2, title: "테이블 선택", description: "소스/대상 테이블 선택" },
|
|
{ number: 3, title: "제어 조건", description: "전체 제어 실행 조건 설정" },
|
|
{ number: 4, title: "액션 및 매핑", description: "액션 설정 및 컬럼 매핑" },
|
|
];
|
|
|
|
const getStepStatus = (stepNumber: number) => {
|
|
if (completedSteps.includes(stepNumber)) return "completed";
|
|
if (stepNumber === currentStep) return "current";
|
|
return "pending";
|
|
};
|
|
|
|
const getStepIcon = (stepNumber: number) => {
|
|
const status = getStepStatus(stepNumber);
|
|
|
|
if (status === "completed") {
|
|
return <CheckCircle className="h-5 w-5 text-green-600" />;
|
|
}
|
|
|
|
return (
|
|
<Circle className={`h-5 w-5 ${status === "current" ? "text-primary fill-primary" : "text-muted-foreground"}`} />
|
|
);
|
|
};
|
|
|
|
const canClickStep = (stepNumber: number) => {
|
|
// 현재 단계이거나 완료된 단계만 클릭 가능
|
|
return stepNumber === currentStep || completedSteps.includes(stepNumber);
|
|
};
|
|
|
|
return (
|
|
<div className="mx-auto flex max-w-4xl items-center justify-between">
|
|
{steps.map((step, index) => (
|
|
<React.Fragment key={step.number}>
|
|
{/* 단계 */}
|
|
<div className="flex items-center">
|
|
<Button
|
|
variant="ghost"
|
|
className={`flex h-auto items-center gap-3 p-3 ${
|
|
canClickStep(step.number) ? "hover:bg-muted/50 cursor-pointer" : "cursor-default"
|
|
}`}
|
|
onClick={() => canClickStep(step.number) && onStepClick(step.number as 1 | 2 | 3 | 4 | 5)}
|
|
disabled={!canClickStep(step.number)}
|
|
>
|
|
{/* 아이콘 */}
|
|
<div className="flex-shrink-0">{getStepIcon(step.number)}</div>
|
|
|
|
{/* 텍스트 */}
|
|
<div className="text-left">
|
|
<div
|
|
className={`text-sm font-medium ${
|
|
getStepStatus(step.number) === "current"
|
|
? "text-primary"
|
|
: getStepStatus(step.number) === "completed"
|
|
? "text-foreground"
|
|
: "text-muted-foreground"
|
|
}`}
|
|
>
|
|
{step.title}
|
|
</div>
|
|
<div className="text-muted-foreground text-xs">{step.description}</div>
|
|
</div>
|
|
</Button>
|
|
</div>
|
|
|
|
{/* 화살표 (마지막 단계 제외) */}
|
|
{index < steps.length - 1 && <ArrowRight className="text-muted-foreground mx-2 h-4 w-4" />}
|
|
</React.Fragment>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default StepProgress;
|