"use client"; import React, { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Checkbox } from "@/components/ui/checkbox"; import { Search, Loader2 } from "lucide-react"; import { useEntitySearch } from "../entity-search-input/useEntitySearch"; import { ItemSelectionModalProps } from "./types"; export function ItemSelectionModal({ open, onOpenChange, sourceTable, sourceColumns, sourceSearchFields = [], multiSelect = true, filterCondition = {}, modalTitle, alreadySelected = [], uniqueField, onSelect, columnLabels = {}, }: ItemSelectionModalProps) { const [localSearchText, setLocalSearchText] = useState(""); const [selectedItems, setSelectedItems] = useState([]); const { results, loading, error, search, clearSearch } = useEntitySearch({ tableName: sourceTable, searchFields: sourceSearchFields.length > 0 ? sourceSearchFields : sourceColumns, filterCondition, }); // 모달 열릴 때 초기 검색 useEffect(() => { if (open) { console.log("🚪 모달 열림 - uniqueField:", uniqueField, "multiSelect:", multiSelect); search("", 1); // 빈 검색어로 전체 목록 조회 setSelectedItems([]); } else { clearSearch(); setLocalSearchText(""); setSelectedItems([]); } }, [open]); const handleSearch = () => { search(localSearchText, 1); }; const handleToggleItem = (item: any) => { const itemValue = uniqueField ? item[uniqueField] : undefined; console.log("🖱️ 행 클릭:", { item, uniqueField, itemValue, currentSelected: selectedItems.length, selectedValues: uniqueField ? selectedItems.map(s => s[uniqueField]) : [] }); if (!multiSelect) { setSelectedItems([item]); return; } // uniqueField 값이 undefined인 경우 객체 참조로 비교 if (uniqueField && (itemValue === undefined || itemValue === null)) { console.warn(`⚠️ uniqueField "${uniqueField}"의 값이 undefined입니다. 객체 참조로 비교합니다.`); const itemIsSelected = selectedItems.includes(item); console.log("📊 선택 상태 (객체 참조):", itemIsSelected); if (itemIsSelected) { const newSelected = selectedItems.filter((selected) => selected !== item); console.log("➖ 제거 후:", newSelected.length); setSelectedItems(newSelected); } else { console.log("➕ 추가"); setSelectedItems([...selectedItems, item]); } return; } const itemIsSelected = selectedItems.some((selected) => { if (!uniqueField) { return selected === item; } const selectedValue = selected[uniqueField]; if (selectedValue === undefined || selectedValue === null) { return false; } return selectedValue === itemValue; }); console.log("📊 선택 상태:", itemIsSelected); if (itemIsSelected) { const newSelected = selectedItems.filter((selected) => { if (!uniqueField) { return selected !== item; } const selectedValue = selected[uniqueField]; if (selectedValue === undefined || selectedValue === null) { return true; } return selectedValue !== itemValue; }); console.log("➖ 제거 후:", newSelected.length); setSelectedItems(newSelected); } else { console.log("➕ 추가"); setSelectedItems([...selectedItems, item]); } }; const handleConfirm = () => { onSelect(selectedItems); onOpenChange(false); }; // 이미 추가된 항목인지 확인 const isAlreadyAdded = (item: any): boolean => { if (!uniqueField) return false; return alreadySelected.some( (selected) => selected[uniqueField] === item[uniqueField] ); }; // 이미 추가된 항목 제외한 결과 필터링 const filteredResults = results.filter((item) => !isAlreadyAdded(item)); // 선택된 항목인지 확인 const isSelected = (item: any): boolean => { if (!uniqueField) { return selectedItems.includes(item); } const itemValue = item[uniqueField]; // uniqueField 값이 undefined인 경우 객체 참조로 비교 if (itemValue === undefined || itemValue === null) { return selectedItems.includes(item); } const result = selectedItems.some((selected) => { const selectedValue = selected[uniqueField]; // selectedValue도 undefined면 안전하게 처리 if (selectedValue === undefined || selectedValue === null) { return false; } const isMatch = selectedValue === itemValue; if (isMatch) { console.log("✅ 매칭 발견:", { selectedValue, itemValue, uniqueField }); } return isMatch; }); return result; }; // 유효한 컬럼만 필터링 const validColumns = sourceColumns.filter(col => col != null && col !== ""); const totalColumns = validColumns.length + (multiSelect ? 1 : 0); return ( {modalTitle} 항목을 검색하고 선택하세요 {multiSelect && " (다중 선택 가능)"} {/* 검색 입력 */}
setLocalSearchText(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") { handleSearch(); } }} className="h-8 text-xs sm:h-10 sm:text-sm" />
{/* 선택된 항목 수 */} {selectedItems.length > 0 && (
{selectedItems.length}개 항목 선택됨 {uniqueField && ( ({selectedItems.map(item => item[uniqueField]).join(", ")}) )}
)} {/* 오류 메시지 */} {error && (
{error}
)} {/* 검색 결과 테이블 */}
{multiSelect && ( )} {validColumns.map((col) => ( ))} {loading && filteredResults.length === 0 ? ( ) : filteredResults.length === 0 ? ( ) : ( filteredResults.map((item, index) => { const selected = isSelected(item); const uniqueFieldValue = uniqueField ? item[uniqueField] : undefined; const itemKey = (uniqueFieldValue !== undefined && uniqueFieldValue !== null) ? uniqueFieldValue : `item-${index}`; return ( handleToggleItem(item)} > {multiSelect && ( )} {validColumns.map((col) => ( ))} ); }) )}
선택 {columnLabels[col] || col}

검색 중...

{results.length > 0 ? "모든 항목이 이미 추가되었습니다" : "검색 결과가 없습니다"}
{ // 체크박스 영역 클릭을 행 클릭으로 전파 e.stopPropagation(); handleToggleItem(item); }} >
{item[col] || "-"}
); }