"use client"; import React, { useState, useEffect } from "react"; 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 { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { toast } from "sonner"; import { ExternalCallConfigAPI, ExternalCallConfig, CALL_TYPE_OPTIONS, API_TYPE_OPTIONS, ACTIVE_STATUS_OPTIONS, } from "@/lib/api/externalCallConfig"; interface ExternalCallConfigModalProps { isOpen: boolean; onClose: () => void; onSave: () => void; editingConfig?: ExternalCallConfig | null; } export function ExternalCallConfigModal({ isOpen, onClose, onSave, editingConfig }: ExternalCallConfigModalProps) { const [loading, setLoading] = useState(false); const [formData, setFormData] = useState>({ config_name: "", call_type: "rest-api", api_type: "discord", description: "", is_active: "Y", config_data: {}, }); // Discord 설정 상태 const [discordSettings, setDiscordSettings] = useState({ webhookUrl: "", username: "", avatarUrl: "", }); // Slack 설정 상태 const [slackSettings, setSlackSettings] = useState({ webhookUrl: "", channel: "", username: "", }); // 카카오톡 설정 상태 const [kakaoSettings, setKakaoSettings] = useState({ accessToken: "", templateId: "", }); // 일반 API 설정 상태 const [genericSettings, setGenericSettings] = useState({ url: "", method: "POST", headers: "{}", timeout: "30000", }); // 편집 모드일 때 기존 데이터 로드 useEffect(() => { if (isOpen && editingConfig) { setFormData({ config_name: editingConfig.config_name, call_type: editingConfig.call_type, api_type: editingConfig.api_type, description: editingConfig.description || "", is_active: editingConfig.is_active || "Y", config_data: editingConfig.config_data, }); // API 타입별 설정 데이터 로드 const configData = editingConfig.config_data as any; if (editingConfig.api_type === "discord") { setDiscordSettings({ webhookUrl: configData.webhookUrl || "", username: configData.username || "", avatarUrl: configData.avatarUrl || "", }); } else if (editingConfig.api_type === "slack") { setSlackSettings({ webhookUrl: configData.webhookUrl || "", channel: configData.channel || "", username: configData.username || "", }); } else if (editingConfig.api_type === "kakao-talk") { setKakaoSettings({ accessToken: configData.accessToken || "", templateId: configData.templateId || "", }); } else if (editingConfig.api_type === "generic") { setGenericSettings({ url: configData.url || "", method: configData.method || "POST", headers: JSON.stringify(configData.headers || {}, null, 2), timeout: String(configData.timeout || 30000), }); } } else if (isOpen && !editingConfig) { // 새 설정 추가 시 초기화 setFormData({ config_name: "", call_type: "rest-api", api_type: "discord", description: "", is_active: "Y", config_data: {}, }); setDiscordSettings({ webhookUrl: "", username: "", avatarUrl: "" }); setSlackSettings({ webhookUrl: "", channel: "", username: "" }); setKakaoSettings({ accessToken: "", templateId: "" }); setGenericSettings({ url: "", method: "POST", headers: "{}", timeout: "30000" }); } }, [isOpen, editingConfig]); // 호출 타입 변경 시 API 타입 초기화 const handleCallTypeChange = (callType: string) => { setFormData((prev) => ({ ...prev, call_type: callType, api_type: callType === "rest-api" ? "discord" : undefined, })); }; // config_data 생성 const generateConfigData = () => { const { api_type } = formData; switch (api_type) { case "discord": return { webhookUrl: discordSettings.webhookUrl, username: discordSettings.username || "ERP 시스템", avatarUrl: discordSettings.avatarUrl || null, }; case "slack": return { webhookUrl: slackSettings.webhookUrl, channel: slackSettings.channel, username: slackSettings.username || "ERP Bot", }; case "kakao-talk": return { accessToken: kakaoSettings.accessToken, templateId: kakaoSettings.templateId, }; case "generic": try { return { url: genericSettings.url, method: genericSettings.method, headers: JSON.parse(genericSettings.headers), timeout: parseInt(genericSettings.timeout), }; } catch (error) { throw new Error("헤더 JSON 형식이 올바르지 않습니다."); } default: return {}; } }; // 폼 검증 const validateForm = () => { if (!formData.config_name?.trim()) { toast.error("설정 이름을 입력해주세요."); return false; } if (!formData.call_type) { toast.error("호출 타입을 선택해주세요."); return false; } // REST API인 경우 API 타입별 검증 if (formData.call_type === "rest-api") { switch (formData.api_type) { case "discord": if (!discordSettings.webhookUrl.trim()) { toast.error("Discord 웹훅 URL을 입력해주세요."); return false; } break; case "slack": if (!slackSettings.webhookUrl.trim()) { toast.error("Slack 웹훅 URL을 입력해주세요."); return false; } break; case "kakao-talk": if (!kakaoSettings.accessToken.trim()) { toast.error("카카오톡 액세스 토큰을 입력해주세요."); return false; } break; case "generic": if (!genericSettings.url.trim()) { toast.error("API URL을 입력해주세요."); return false; } try { JSON.parse(genericSettings.headers); } catch { toast.error("헤더 JSON 형식이 올바르지 않습니다."); return false; } break; } } return true; }; // 저장 처리 const handleSave = async () => { if (!validateForm()) return; try { setLoading(true); const configData = generateConfigData(); const saveData = { ...formData, config_data: configData, }; let response; if (editingConfig?.id) { response = await ExternalCallConfigAPI.updateConfig(editingConfig.id, saveData); } else { response = await ExternalCallConfigAPI.createConfig(saveData as any); } if (response.success) { toast.success(editingConfig ? "외부 호출 설정이 수정되었습니다." : "외부 호출 설정이 생성되었습니다."); onSave(); } else { toast.error(response.message || "저장 실패"); } } catch (error) { console.error("외부 호출 설정 저장 오류:", error); toast.error("저장 중 오류가 발생했습니다."); } finally { setLoading(false); } }; return ( {editingConfig ? "외부 호출 설정 편집" : "새 외부 호출 설정"}
{/* 기본 정보 */}
setFormData((prev) => ({ ...prev, config_name: e.target.value }))} placeholder="예: 개발팀 Discord" />