import React, { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { Badge } from "@/components/ui/badge"; import { toast } from "sonner"; import { BatchAPI, BatchJob, BatchConfig } from "@/lib/api/batch"; import { ExternalDbConnectionAPI } from "@/lib/api/externalDbConnection"; // BatchJobModal에서 사용하던 config_json 구조 확장 interface RestApiConfigJson { sourceConnectionId?: number; targetConnectionId?: number; targetTable?: string; // REST API 관련 설정 apiUrl?: string; apiKey?: string; endpoint?: string; httpMethod?: string; apiBody?: string; // POST 요청용 Body // 매핑 정보 등 mappings?: any[]; } interface AdvancedBatchModalProps { isOpen: boolean; onClose: () => void; onSave: () => void; job?: BatchJob | null; initialType?: "rest_to_db" | "db_to_rest"; // 초기 진입 시 타입 지정 } export default function AdvancedBatchModal({ isOpen, onClose, onSave, job, initialType = "rest_to_db", }: AdvancedBatchModalProps) { // 기본 BatchJob 정보 관리 const [formData, setFormData] = useState>({ job_name: "", description: "", job_type: initialType === "rest_to_db" ? "rest_to_db" : "db_to_rest", schedule_cron: "", is_active: "Y", config_json: {}, }); // 상세 설정 (config_json 내부 값) 관리 const [configData, setConfigData] = useState({ httpMethod: "GET", // 기본값 apiBody: "", }); const [isLoading, setIsLoading] = useState(false); const [connections, setConnections] = useState([]); // 내부/외부 DB 연결 목록 const [targetTables, setTargetTables] = useState([]); // 대상 테이블 목록 (DB가 타겟일 때) const [schedulePresets, setSchedulePresets] = useState>([]); // 모달 열릴 때 초기화 useEffect(() => { if (isOpen) { loadConnections(); loadSchedulePresets(); if (job) { // 수정 모드 setFormData({ ...job, config_json: job.config_json || {}, }); // 기존 config_json 내용을 상태로 복원 const savedConfig = job.config_json as RestApiConfigJson; setConfigData({ ...savedConfig, httpMethod: savedConfig.httpMethod || "GET", apiBody: savedConfig.apiBody || "", }); // 타겟 연결이 있으면 테이블 목록 로드 if (savedConfig.targetConnectionId) { loadTables(savedConfig.targetConnectionId); } } else { // 생성 모드 setFormData({ job_name: "", description: "", job_type: initialType === "rest_to_db" ? "rest_to_db" : "db_to_rest", // props로 받은 타입 우선 schedule_cron: "", is_active: "Y", config_json: {}, }); setConfigData({ httpMethod: "GET", apiBody: "", }); } } }, [isOpen, job, initialType]); const loadConnections = async () => { try { // 외부 DB 연결 목록 조회 (내부 DB 포함) const list = await ExternalDbConnectionAPI.getConnections({ is_active: "Y" }); setConnections(list); } catch (error) { console.error("연결 목록 조회 오류:", error); toast.error("연결 목록을 불러오는데 실패했습니다."); } }; const loadTables = async (connectionId: number) => { try { const result = await ExternalDbConnectionAPI.getTables(connectionId); if (result.success && result.data) { setTargetTables(result.data); } } catch (error) { console.error("테이블 목록 조회 오류:", error); } }; const loadSchedulePresets = async () => { try { const presets = await BatchAPI.getSchedulePresets(); setSchedulePresets(presets); } catch (error) { console.error("스케줄 프리셋 조회 오류:", error); } }; // 폼 제출 핸들러 const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!formData.job_name) { toast.error("배치명을 입력해주세요."); return; } // REST API URL 필수 체크 if (!configData.apiUrl) { toast.error("API 서버 URL을 입력해주세요."); return; } // 타겟 DB 연결 필수 체크 (REST -> DB 인 경우) if (formData.job_type === "rest_to_db" && !configData.targetConnectionId) { toast.error("데이터를 저장할 대상 DB 연결을 선택해주세요."); return; } setIsLoading(true); try { // 최종 저장할 데이터 조립 const finalJobData = { ...formData, config_json: { ...configData, // 추가적인 메타데이터가 필요하다면 여기에 포함 }, }; if (job?.id) { await BatchAPI.updateBatchJob(job.id, finalJobData); toast.success("배치 작업이 수정되었습니다."); } else { await BatchAPI.createBatchJob(finalJobData as BatchJob); toast.success("배치 작업이 생성되었습니다."); } onSave(); onClose(); } catch (error) { console.error("배치 저장 오류:", error); toast.error(error instanceof Error ? error.message : "저장에 실패했습니다."); } finally { setIsLoading(false); } }; return ( 고급 배치 생성
{/* 1. 기본 정보 섹션 */}

기본 정보

{formData.job_type === "rest_to_db" ? "🌐 REST API → 💾 DB" : "💾 DB → 🌐 REST API"}

{formData.job_type === "rest_to_db" ? "REST API에서 데이터를 가져와 데이터베이스에 저장합니다." : "데이터베이스의 데이터를 REST API로 전송합니다."}

setFormData(prev => ({ ...prev, schedule_cron: e.target.value }))} placeholder="예: 0 12 * * *" className="text-sm" />
setFormData(prev => ({ ...prev, job_name: e.target.value }))} placeholder="배치명을 입력하세요" className="mt-1" />