"use client" import { useEffect, useTransition, useState, useRef } from "react" import { useRouter, useParams } from "next/navigation" import { z } from "zod" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { Search, X } from "lucide-react" import { customAlphabet } from "nanoid" import { Button } from "@/components/ui/button" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Badge } from "@/components/ui/badge" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { cn } from "@/lib/utils" import { EVALUATION_TARGET_FILTER_OPTIONS } from "../validation" // nanoid 생성기 const generateId = customAlphabet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6) // 평가 대상 필터 스키마 정의 const evaluationTargetFilterSchema = z.object({ evaluationYear: z.string().optional(), division: z.string().optional(), status: z.string().optional(), domesticForeign: z.string().optional(), materialType: z.string().optional(), consensusStatus: z.string().optional(), vendorCode: z.string().optional(), vendorName: z.string().optional(), reviewerUserId: z.string().optional(), orderReviewerName: z.string().optional(), procurementReviewerName: z.string().optional(), qualityReviewerName: z.string().optional(), designReviewerName: z.string().optional(), csReviewerName: z.string().optional(), }) type EvaluationTargetFilterFormValues = z.infer interface EvaluationTargetFilterSheetProps { isOpen: boolean; onClose: () => void; onFiltersApply: (filters: any[], joinOperator: "and" | "or") => void; // ✅ 필터 전달 콜백 isLoading?: boolean; } export function EvaluationTargetFilterSheet({ isOpen, onClose, onFiltersApply, isLoading = false }: EvaluationTargetFilterSheetProps) { const router = useRouter() const params = useParams(); const lng = params ? (params.lng as string) : 'ko'; const [isPending, startTransition] = useTransition() const [joinOperator, setJoinOperator] = useState<"and" | "or">("and") // 폼 상태 초기화 const form = useForm({ resolver: zodResolver(evaluationTargetFilterSchema), defaultValues: { evaluationYear: new Date().getFullYear().toString(), division: "", status: "", domesticForeign: "", materialType: "", consensusStatus: "", vendorCode: "", vendorName: "", reviewerUserId: "", orderReviewerName: "", procurementReviewerName: "", qualityReviewerName: "", designReviewerName: "", csReviewerName: "", }, }) // ✅ 폼 제출 핸들러 - 필터 배열 생성 및 전달 async function onSubmit(data: EvaluationTargetFilterFormValues) { startTransition(async () => { try { const newFilters = [] // 필터 생성 로직 if (data.evaluationYear?.trim()) { newFilters.push({ id: "evaluationYear", value: parseInt(data.evaluationYear.trim()), type: "number", operator: "eq", rowId: generateId() }) } if (data.division?.trim()) { newFilters.push({ id: "division", value: data.division.trim(), type: "select", operator: "eq", rowId: generateId() }) } if (data.status?.trim()) { newFilters.push({ id: "status", value: data.status.trim(), type: "select", operator: "eq", rowId: generateId() }) } if (data.domesticForeign?.trim()) { newFilters.push({ id: "domesticForeign", value: data.domesticForeign.trim(), type: "select", operator: "eq", rowId: generateId() }) } if (data.materialType?.trim()) { newFilters.push({ id: "materialType", value: data.materialType.trim(), type: "select", operator: "eq", rowId: generateId() }) } if (data.consensusStatus?.trim()) { newFilters.push({ id: "consensusStatus", value: data.consensusStatus.trim(), type: "select", operator: "eq", rowId: generateId() }) } if (data.vendorCode?.trim()) { newFilters.push({ id: "vendorCode", value: data.vendorCode.trim(), type: "text", operator: "iLike", rowId: generateId() }) } if (data.vendorName?.trim()) { newFilters.push({ id: "vendorName", value: data.vendorName.trim(), type: "text", operator: "iLike", rowId: generateId() }) } if (data.reviewerUserId?.trim()) { newFilters.push({ id: "reviewerUserId", value: parseInt(data.reviewerUserId.trim()), type: "number", operator: "eq", rowId: generateId() }) } if (data.orderReviewerName?.trim()) { newFilters.push({ id: "orderReviewerName", value: data.orderReviewerName.trim(), type: "text", operator: "iLike", rowId: generateId() }) } if (data.procurementReviewerName?.trim()) { newFilters.push({ id: "procurementReviewerName", value: data.procurementReviewerName.trim(), type: "text", operator: "iLike", rowId: generateId() }) } if (data.qualityReviewerName?.trim()) { newFilters.push({ id: "qualityReviewerName", value: data.qualityReviewerName.trim(), type: "text", operator: "iLike", rowId: generateId() }) } if (data.designReviewerName?.trim()) { newFilters.push({ id: "designReviewerName", value: data.designReviewerName.trim(), type: "text", operator: "iLike", rowId: generateId() }) } if (data.csReviewerName?.trim()) { newFilters.push({ id: "csReviewerName", value: data.csReviewerName.trim(), type: "text", operator: "iLike", rowId: generateId() }) } console.log("=== 생성된 필터들 ===", newFilters); console.log("=== 조인 연산자 ===", joinOperator); // ✅ 부모 컴포넌트에 필터 전달 onFiltersApply(newFilters, joinOperator); console.log("=== 필터 적용 완료 ==="); } catch (error) { console.error("평가 대상 필터 적용 오류:", error); } }) } // ✅ 필터 초기화 핸들러 function handleReset() { // 1. 폼 초기화 form.reset({ evaluationYear: "", division: "", status: "", domesticForeign: "", materialType: "", consensusStatus: "", vendorCode: "", vendorName: "", reviewerUserId: "", orderReviewerName: "", procurementReviewerName: "", qualityReviewerName: "", designReviewerName: "", csReviewerName: "", }); // 2. 조인 연산자 초기화 setJoinOperator("and"); // 3. URL 파라미터 초기화 (필터를 빈 배열로 설정) const currentUrl = new URL(window.location.href); const newSearchParams = new URLSearchParams(currentUrl.search); // 필터 관련 파라미터 초기화 newSearchParams.set("filters", JSON.stringify([])); newSearchParams.set("joinOperator", "and"); newSearchParams.set("page", "1"); newSearchParams.delete("search"); // 검색어 제거 // URL 업데이트 router.replace(`${currentUrl.pathname}?${newSearchParams.toString()}`); // 4. 빈 필터 배열 전달 (즉시 UI 업데이트를 위해) onFiltersApply([], "and"); console.log("=== 필터 완전 초기화 완료 ==="); } if (!isOpen) { return null; } return (
{/* Filter Panel Header */}

평가 대상 검색 필터

{/* Join Operator Selection */}
{/* Scrollable content area */}
{/* 평가년도 */} ( 평가년도
{field.value && ( )}
)} /> {/* 구분 */} ( 구분 )} /> {/* 상태 */} ( 상태 )} /> {/* 내외자 구분 */} ( 내외자 구분 )} /> {/* 자재구분 */} ( 자재구분 )} /> {/* 의견 일치 여부 */} ( 의견 일치 여부 )} /> {/* 벤더 코드 */} ( 벤더 코드
{field.value && ( )}
)} /> {/* 벤더명 */} ( 벤더명
{field.value && ( )}
)} /> {/* 담당자 ID */} ( 담당자 ID
{field.value && ( )}
)} /> {/* 발주 담당자명 */} ( 발주 담당자명
{field.value && ( )}
)} /> {/* 조달 담당자명 */} ( 조달 담당자명
{field.value && ( )}
)} /> {/* 품질 담당자명 */} ( 품질 담당자명
{field.value && ( )}
)} /> {/* 설계 담당자명 */} ( 설계 담당자명
{field.value && ( )}
)} /> {/* CS 담당자명 */} ( CS 담당자명
{field.value && ( )}
)} />
{/* Fixed buttons at bottom */}
) }