"use client"; import { useState, useEffect } from "react"; import { toast } from "sonner"; import { Loader2 } from "lucide-react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Checkbox } from "@/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { menuApi, MenuCopyResult } from "@/lib/api/menu"; import { apiClient } from "@/lib/api/client"; interface MenuCopyDialogProps { menuObjid: number | null; menuName: string | null; open: boolean; onOpenChange: (open: boolean) => void; onCopyComplete?: () => void; } interface Company { company_code: string; company_name: string; } export function MenuCopyDialog({ menuObjid, menuName, open, onOpenChange, onCopyComplete, }: MenuCopyDialogProps) { const [targetCompanyCode, setTargetCompanyCode] = useState(""); const [companies, setCompanies] = useState([]); const [copying, setCopying] = useState(false); const [result, setResult] = useState(null); const [loadingCompanies, setLoadingCompanies] = useState(false); // 화면명 일괄 변경 설정 const [useBulkRename, setUseBulkRename] = useState(false); const [removeText, setRemoveText] = useState(""); const [addPrefix, setAddPrefix] = useState(""); // 카테고리/코드 복사 옵션 const [copyCodeCategory, setCopyCodeCategory] = useState(false); const [copyNumberingRules, setCopyNumberingRules] = useState(false); const [copyCategoryMapping, setCopyCategoryMapping] = useState(false); const [copyTableTypeColumns, setCopyTableTypeColumns] = useState(false); // 회사 목록 로드 useEffect(() => { if (open) { loadCompanies(); // 다이얼로그가 열릴 때마다 초기화 setTargetCompanyCode(""); setResult(null); setUseBulkRename(false); setRemoveText(""); setAddPrefix(""); setCopyCodeCategory(false); setCopyNumberingRules(false); setCopyCategoryMapping(false); setCopyTableTypeColumns(false); } }, [open]); const loadCompanies = async () => { try { setLoadingCompanies(true); const response = await apiClient.get("/admin/companies/db"); if (response.data.success && response.data.data) { // 최고 관리자(*) 회사 제외 const filteredCompanies = response.data.data.filter( (company: Company) => company.company_code !== "*" ); setCompanies(filteredCompanies); } } catch (error) { console.error("회사 목록 조회 실패:", error); toast.error("회사 목록을 불러올 수 없습니다"); } finally { setLoadingCompanies(false); } }; const handleCopy = async () => { if (!menuObjid) { toast.error("메뉴를 선택해주세요"); return; } if (!targetCompanyCode) { toast.error("대상 회사를 선택해주세요"); return; } setCopying(true); setResult(null); try { // 화면명 변환 설정 (사용 중일 때만 전달) const screenNameConfig = useBulkRename && (removeText.trim() || addPrefix.trim()) ? { removeText: removeText.trim() || undefined, addPrefix: addPrefix.trim() || undefined, } : undefined; // 추가 복사 옵션 const additionalCopyOptions = { copyCodeCategory, copyNumberingRules, copyCategoryMapping, copyTableTypeColumns, }; const response = await menuApi.copyMenu( menuObjid, targetCompanyCode, screenNameConfig, additionalCopyOptions ); if (response.success && response.data) { setResult(response.data); toast.success("메뉴 복사 완료!"); // 경고 메시지 표시 if (response.data.warnings && response.data.warnings.length > 0) { response.data.warnings.forEach((warning) => { toast.warning(warning); }); } // 복사 완료 콜백 if (onCopyComplete) { onCopyComplete(); } } else { toast.error(response.message || "메뉴 복사 실패"); } } catch (error: any) { console.error("메뉴 복사 오류:", error); toast.error(error.message || "메뉴 복사 중 오류가 발생했습니다"); } finally { setCopying(false); } }; const handleClose = () => { if (!copying) { onOpenChange(false); } }; return ( 메뉴 복사 "{menuName}" 메뉴와 관련된 모든 리소스를 다른 회사로 복사합니다.
{/* 회사 선택 */} {!result && (
)} {/* 화면명 일괄 변경 설정 */} {!result && (
setUseBulkRename(checked as boolean)} disabled={copying} />
{useBulkRename && (
setRemoveText(e.target.value)} placeholder="예: 탑씰" disabled={copying} className="h-8 text-xs sm:h-10 sm:text-sm" />

화면명에서 이 텍스트를 제거합니다 (예: "탑씰 회사정보" → "회사정보")

setAddPrefix(e.target.value)} placeholder="예: 한신" disabled={copying} className="h-8 text-xs sm:h-10 sm:text-sm" />

화면명 앞에 이 텍스트를 추가합니다 (예: "회사정보" → "한신 회사정보")

)}
)} {/* 추가 복사 옵션 */} {!result && (

추가 복사 옵션 (선택사항):

setCopyCodeCategory(checked as boolean)} disabled={copying} />
setCopyNumberingRules(checked as boolean)} disabled={copying} />
setCopyCategoryMapping(checked as boolean)} disabled={copying} />
setCopyTableTypeColumns(checked as boolean)} disabled={copying} />
)} {/* 복사 항목 안내 */} {!result && (

기본 복사 항목:

  • 메뉴 구조 (하위 메뉴 포함)
  • 화면 + 레이아웃 (모달, 조건부 컨테이너)
  • 플로우 제어 (스텝, 연결)

* 코드, 채번규칙, 카테고리는 위 옵션 선택 시 복사됩니다.

)} {/* 복사 결과 */} {result && (

✅ 복사 완료!

메뉴:{" "} {result.copiedMenus}개
화면:{" "} {result.copiedScreens}개
플로우:{" "} {result.copiedFlows}개
{(result.copiedCodeCategories ?? 0) > 0 && (
코드 카테고리:{" "} {result.copiedCodeCategories}개
)} {(result.copiedCodes ?? 0) > 0 && (
코드:{" "} {result.copiedCodes}개
)} {(result.copiedNumberingRules ?? 0) > 0 && (
채번규칙:{" "} {result.copiedNumberingRules}개
)} {(result.copiedCategoryMappings ?? 0) > 0 && (
카테고리 매핑:{" "} {result.copiedCategoryMappings}개
)} {(result.copiedTableTypeColumns ?? 0) > 0 && (
테이블 타입 설정:{" "} {result.copiedTableTypeColumns}개
)}
)}
{!result && ( )}
); }