"use client"; import React, { useState, useEffect, useCallback } 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 { Switch } from "@/components/ui/switch"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Filter, Plus, RefreshCw, Search, Pencil, Trash2 } from "lucide-react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { toast } from "sonner"; import { cascadingConditionApi, CascadingCondition, CONDITION_OPERATORS, } from "@/lib/api/cascadingCondition"; import { cascadingRelationApi } from "@/lib/api/cascadingRelation"; export default function ConditionTab() { // 목록 상태 const [conditions, setConditions] = useState([]); const [relations, setRelations] = useState>([]); const [loading, setLoading] = useState(true); const [searchText, setSearchText] = useState(""); // 모달 상태 const [isModalOpen, setIsModalOpen] = useState(false); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [editingCondition, setEditingCondition] = useState(null); const [deletingConditionId, setDeletingConditionId] = useState(null); // 폼 데이터 const [formData, setFormData] = useState>({ relationType: "RELATION", relationCode: "", conditionName: "", conditionField: "", conditionOperator: "EQ", conditionValue: "", filterColumn: "", filterValues: "", priority: 0, }); // 목록 로드 const loadConditions = useCallback(async () => { setLoading(true); try { const response = await cascadingConditionApi.getList(); if (response.success && response.data) { setConditions(response.data); } } catch (error) { console.error("조건 목록 로드 실패:", error); toast.error("조건 목록을 불러오는데 실패했습니다."); } finally { setLoading(false); } }, []); // 연쇄 관계 목록 로드 const loadRelations = useCallback(async () => { try { const response = await cascadingRelationApi.getList("Y"); if (response.success && response.data) { setRelations(response.data); } } catch (error) { console.error("연쇄 관계 목록 로드 실패:", error); } }, []); useEffect(() => { loadConditions(); loadRelations(); }, [loadConditions, loadRelations]); // 필터된 목록 const filteredConditions = conditions.filter( (c) => c.conditionName?.toLowerCase().includes(searchText.toLowerCase()) || c.relationCode?.toLowerCase().includes(searchText.toLowerCase()) || c.conditionField?.toLowerCase().includes(searchText.toLowerCase()) ); // 모달 열기 (생성) const handleOpenCreate = () => { setEditingCondition(null); setFormData({ relationType: "RELATION", relationCode: "", conditionName: "", conditionField: "", conditionOperator: "EQ", conditionValue: "", filterColumn: "", filterValues: "", priority: 0, }); setIsModalOpen(true); }; // 모달 열기 (수정) const handleOpenEdit = (condition: CascadingCondition) => { setEditingCondition(condition); setFormData({ relationType: condition.relationType || "RELATION", relationCode: condition.relationCode, conditionName: condition.conditionName, conditionField: condition.conditionField, conditionOperator: condition.conditionOperator, conditionValue: condition.conditionValue, filterColumn: condition.filterColumn, filterValues: condition.filterValues, priority: condition.priority || 0, }); setIsModalOpen(true); }; // 삭제 확인 const handleDeleteConfirm = (conditionId: number) => { setDeletingConditionId(conditionId); setIsDeleteDialogOpen(true); }; // 삭제 실행 const handleDelete = async () => { if (!deletingConditionId) return; try { const response = await cascadingConditionApi.delete(deletingConditionId); if (response.success) { toast.success("조건부 규칙이 삭제되었습니다."); loadConditions(); } else { toast.error(response.error || "삭제에 실패했습니다."); } } catch (error) { toast.error("삭제 중 오류가 발생했습니다."); } finally { setIsDeleteDialogOpen(false); setDeletingConditionId(null); } }; // 저장 const handleSave = async () => { // 유효성 검사 if (!formData.relationCode || !formData.conditionName || !formData.conditionField) { toast.error("필수 항목을 모두 입력해주세요."); return; } if (!formData.conditionValue || !formData.filterColumn || !formData.filterValues) { toast.error("조건 값, 필터 컬럼, 필터 값을 모두 입력해주세요."); return; } try { let response; if (editingCondition) { response = await cascadingConditionApi.update(editingCondition.conditionId!, formData); } else { response = await cascadingConditionApi.create(formData); } if (response.success) { toast.success(editingCondition ? "수정되었습니다." : "생성되었습니다."); setIsModalOpen(false); loadConditions(); } else { toast.error(response.error || "저장에 실패했습니다."); } } catch (error) { toast.error("저장 중 오류가 발생했습니다."); } }; // 연산자 라벨 찾기 const getOperatorLabel = (operator: string) => { return CONDITION_OPERATORS.find((op) => op.value === operator)?.label || operator; }; return (
{/* 검색 */}
setSearchText(e.target.value)} className="pl-10" />
{/* 목록 */}
조건부 필터 규칙 특정 필드 값에 따라 드롭다운 옵션을 필터링합니다. (총 {filteredConditions.length}개)
{loading ? (
로딩 중...
) : filteredConditions.length === 0 ? (
{searchText ? "검색 결과가 없습니다." : "등록된 조건부 필터 규칙이 없습니다."}
예시: 상태별 품목 필터
"상태" 필드가 "활성"일 때만 "품목" 드롭다운에 활성 품목만 표시
예시: 유형별 옵션 필터
"유형" 필드가 "입고"일 때 "창고" 드롭다운에 입고 가능 창고만 표시
) : ( 연쇄 관계 조건명 조건 필터 상태 작업 {filteredConditions.map((condition) => ( {condition.relationCode} {condition.conditionName}
{condition.conditionField} {getOperatorLabel(condition.conditionOperator)} {condition.conditionValue}
{condition.filterColumn} = {condition.filterValues}
{condition.isActive === "Y" ? "활성" : "비활성"}
))}
)}
{/* 생성/수정 모달 */} {editingCondition ? "조건부 규칙 수정" : "조건부 규칙 생성"} 특정 필드 값에 따라 드롭다운 옵션을 필터링하는 규칙을 설정합니다.
{/* 연쇄 관계 선택 */}
{/* 조건명 */}
setFormData({ ...formData, conditionName: e.target.value })} placeholder="예: 활성 품목만 표시" />
{/* 조건 설정 */}

조건 설정

setFormData({ ...formData, conditionField: e.target.value })} placeholder="예: status" className="h-9 text-sm" />
setFormData({ ...formData, conditionValue: e.target.value })} placeholder="예: active" className="h-9 text-sm" />

폼의 "{formData.conditionField || "필드"}" 값이 "{formData.conditionValue || "값"}"일 때 필터 적용

{/* 필터 설정 */}

필터 설정

setFormData({ ...formData, filterColumn: e.target.value })} placeholder="예: status" className="h-9 text-sm" />
setFormData({ ...formData, filterValues: e.target.value })} placeholder="예: active,pending" className="h-9 text-sm" />

드롭다운 옵션 중 "{formData.filterColumn || "컬럼"}"이 "{formData.filterValues || "값"}"인 항목만 표시

{/* 우선순위 */}
setFormData({ ...formData, priority: Number(e.target.value) })} placeholder="높을수록 먼저 적용" className="w-32" />

여러 조건이 일치할 경우 우선순위가 높은 규칙이 적용됩니다.

{/* 삭제 확인 다이얼로그 */} 조건부 규칙 삭제 이 조건부 규칙을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다. 취소 삭제
); }