"use client"; import React, { useState, useCallback, useEffect, useMemo } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { roleAPI, RoleGroup } from "@/lib/api/role"; import { useAuth } from "@/hooks/useAuth"; import { AlertCircle, Check, ChevronsUpDown } from "lucide-react"; import { cn } from "@/lib/utils"; import { companyAPI } from "@/lib/api/company"; interface RoleFormModalProps { isOpen: boolean; onClose: () => void; onSuccess?: () => void; editingRole?: RoleGroup | null; } /** * 권한 그룹 생성/수정 모달 * * 기능: * - 권한 그룹 생성 (authName, authCode, companyCode) * - 권한 그룹 수정 (authName, authCode, status) * - 유효성 검사 * * shadcn/ui 표준 모달 디자인 적용 */ export function RoleFormModal({ isOpen, onClose, onSuccess, editingRole }: RoleFormModalProps) { const { user: currentUser } = useAuth(); const isEditMode = !!editingRole; // 최고 관리자 여부 const isSuperAdmin = currentUser?.companyCode === "*" && currentUser?.userType === "SUPER_ADMIN"; // 폼 데이터 const [formData, setFormData] = useState({ authName: "", authCode: "", companyCode: currentUser?.companyCode || "", status: "active", }); // 상태 관리 const [isLoading, setIsLoading] = useState(false); const [showAlert, setShowAlert] = useState(false); const [alertMessage, setAlertMessage] = useState(""); const [alertType, setAlertType] = useState<"success" | "error" | "info">("info"); // 회사 목록 (최고 관리자용) const [companies, setCompanies] = useState>([]); const [isLoadingCompanies, setIsLoadingCompanies] = useState(false); const [companyComboOpen, setCompanyComboOpen] = useState(false); // 폼 유효성 검사 const isFormValid = useMemo(() => { return formData.authName.trim() !== "" && formData.authCode.trim() !== "" && formData.companyCode.trim() !== ""; }, [formData]); // 알림 표시 const displayAlert = useCallback((message: string, type: "success" | "error" | "info") => { setAlertMessage(message); setAlertType(type); setShowAlert(true); setTimeout(() => setShowAlert(false), 3000); }, []); // 회사 목록 로드 (최고 관리자만) const loadCompanies = useCallback(async () => { if (!isSuperAdmin) return; setIsLoadingCompanies(true); try { // companyAPI.getList()는 Promise를 반환하므로 직접 사용 const companies = await companyAPI.getList(); console.log("📋 회사 목록 로드 성공:", companies); setCompanies(companies); } catch (error) { console.error("❌ 회사 목록 로드 오류:", error); displayAlert("회사 목록을 불러오는데 실패했습니다.", "error"); } finally { setIsLoadingCompanies(false); } }, [isSuperAdmin, displayAlert]); // 초기화 useEffect(() => { if (isOpen) { // 최고 관리자이고 생성 모드일 때만 회사 목록 로드 if (isSuperAdmin && !isEditMode) { loadCompanies(); } if (isEditMode && editingRole) { // 수정 모드: 기존 데이터 로드 setFormData({ authName: editingRole.authName || "", authCode: editingRole.authCode || "", companyCode: editingRole.companyCode || "", status: editingRole.status || "active", }); } else { // 생성 모드: 초기화 setFormData({ authName: "", authCode: "", companyCode: currentUser?.companyCode || "", status: "active", }); } setShowAlert(false); } }, [isOpen, isEditMode, editingRole, currentUser?.companyCode, isSuperAdmin, loadCompanies]); // 입력 핸들러 const handleInputChange = useCallback((field: string, value: string) => { setFormData((prev) => ({ ...prev, [field]: value })); }, []); // 제출 핸들러 const handleSubmit = useCallback(async () => { if (!isFormValid) { displayAlert("모든 필수 항목을 입력해주세요.", "error"); return; } setIsLoading(true); try { let response; if (isEditMode && editingRole) { // 수정 response = await roleAPI.update(editingRole.objid, { authName: formData.authName, authCode: formData.authCode, status: formData.status, }); } else { // 생성 response = await roleAPI.create({ authName: formData.authName, authCode: formData.authCode, companyCode: formData.companyCode, }); } if (response.success) { displayAlert(isEditMode ? "권한 그룹이 수정되었습니다." : "권한 그룹이 생성되었습니다.", "success"); setTimeout(() => { onClose(); onSuccess?.(); }, 1500); } else { displayAlert(response.message || "작업에 실패했습니다.", "error"); } } catch (error) { console.error("권한 그룹 저장 오류:", error); displayAlert("권한 그룹 저장 중 오류가 발생했습니다.", "error"); } finally { setIsLoading(false); } }, [isFormValid, isEditMode, editingRole, formData, onClose, onSuccess, displayAlert]); // Enter 키 핸들러 const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === "Enter" && isFormValid && !isLoading) { handleSubmit(); } }, [isFormValid, isLoading, handleSubmit], ); return ( {isEditMode ? "권한 그룹 수정" : "권한 그룹 생성"}
{/* 권한 그룹명 */}
handleInputChange("authName", e.target.value)} onKeyDown={handleKeyDown} placeholder="예: 영업팀 권한" className="h-8 text-xs sm:h-10 sm:text-sm" disabled={isLoading} />
{/* 권한 코드 */}
handleInputChange("authCode", e.target.value)} onKeyDown={handleKeyDown} placeholder="예: SALES_TEAM (영문/숫자/언더스코어만)" className="h-8 text-xs sm:h-10 sm:text-sm" disabled={isLoading} />

시스템 내부에서 사용되는 고유 코드입니다. 영문 대문자, 숫자, 언더스코어만 사용하세요.

{/* 회사 (수정 모드에서는 비활성화) */} {isEditMode ? (

회사 코드는 수정할 수 없습니다.

) : (
{isSuperAdmin ? ( <> {isLoadingCompanies ? "로딩 중..." : "회사를 찾을 수 없습니다."} {companies.map((company) => ( { handleInputChange("companyCode", company.company_code); setCompanyComboOpen(false); }} className="text-xs sm:text-sm" >
{company.company_name} {company.company_code}
))}

모든 회사에 권한 그룹을 생성할 수 있습니다.

) : ( <>

자신의 회사에만 권한 그룹을 생성할 수 있습니다.

)}
)} {/* 상태 (수정 모드에서만 표시) */} {isEditMode && (
)} {/* 알림 메시지 */} {showAlert && (
{alertType === "error" && } {alertMessage}
)}
); }