From a4bf0d8376962c922da90cd08781893a3658ecc2 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Thu, 6 Nov 2025 09:52:27 +0000 Subject: (최겸) 구매 보완 재실사 자동생성 삭제 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pq/pq-review-table-new/site-visit-dialog.tsx | 189 ++++++++--------------- 1 file changed, 65 insertions(+), 124 deletions(-) (limited to 'lib/pq/pq-review-table-new') diff --git a/lib/pq/pq-review-table-new/site-visit-dialog.tsx b/lib/pq/pq-review-table-new/site-visit-dialog.tsx index a7cc3313..55468499 100644 --- a/lib/pq/pq-review-table-new/site-visit-dialog.tsx +++ b/lib/pq/pq-review-table-new/site-visit-dialog.tsx @@ -1,7 +1,7 @@ "use client" import * as React from "react" -import { CalendarIcon, X, Plus, Trash2, Check, Search } from "lucide-react" +import { CalendarIcon, X, Plus, Trash2 } from "lucide-react" import { useForm, useFieldArray } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { format } from "date-fns" @@ -36,18 +36,9 @@ import { } from "@/components/ui/popover" import { Checkbox } from "@/components/ui/checkbox" import { Badge } from "@/components/ui/badge" -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, -} from "@/components/ui/command" import { toast } from "sonner" import { getSiteVisitRequestAction, getUsersForSiteVisitAction } from "@/lib/site-visit/service" -import { cn } from "@/lib/utils" +import { UserCombobox } from "./user-combobox" import { Dropzone, DropzoneDescription, @@ -183,7 +174,7 @@ interface SiteVisitUser { id: number; name: string; email: string; - deptName: string | null; + department?: string; } // 참석자 섹션 컴포넌트 @@ -204,57 +195,55 @@ function AttendeeSection({ }); const isChecked = form.watch(`shiAttendees.${itemKey}.checked`); - const [isPopoverOpen, setIsPopoverOpen] = React.useState(false); - const [searchQuery, setSearchQuery] = React.useState(""); const [users, setUsers] = React.useState([]); const [isLoadingUsers, setIsLoadingUsers] = React.useState(false); + const [selectedUserId, setSelectedUserId] = React.useState(null); - const loadUsers = React.useCallback(async () => { - setIsLoadingUsers(true); - try { - const result = await getUsersForSiteVisitAction( - searchQuery.trim() || undefined - ); - if (result.success && result.data) { - setUsers(result.data); - } - } catch (error) { - console.error("사용자 목록 로드 오류:", error); - toast.error("사용자 목록을 불러오는데 실패했습니다."); - } finally { - setIsLoadingUsers(false); - } - }, [searchQuery]); - - // 사용자 목록 가져오기 - React.useEffect(() => { - if (isPopoverOpen && isChecked) { - loadUsers(); - } - }, [isPopoverOpen, isChecked, loadUsers]); - - // 검색 쿼리 변경 시 사용자 목록 다시 로드 (debounce) + // Dialog가 열릴 때 사용자 목록 로드 React.useEffect(() => { - if (!isPopoverOpen || !isChecked) return; + if (isChecked && users.length === 0) { + const loadUsers = async () => { + setIsLoadingUsers(true); + try { + const result = await getUsersForSiteVisitAction(); + if (result.success && result.data) { + setUsers(result.data.map((user: any) => ({ + id: user.id, + name: user.name, + email: user.email, + department: user.deptName || undefined, + }))); + } + } catch (error) { + console.error("사용자 목록 로드 오류:", error); + toast.error("사용자 목록을 불러오는데 실패했습니다."); + } finally { + setIsLoadingUsers(false); + } + }; - const timer = setTimeout(() => { loadUsers(); - }, 300); + } + }, [isChecked, users.length]); - return () => clearTimeout(timer); - }, [searchQuery, isPopoverOpen, isChecked, loadUsers]); + const handleUserSelect = (userId: number) => { + // 선택된 사용자 정보 찾기 + const selectedUser = users.find(user => user.id === userId); + if (!selectedUser) return; - const handleUserSelect = (user: SiteVisitUser) => { // 현재 폼의 attendees 값 가져오기 const currentAttendees = form.getValues(`shiAttendees.${itemKey}.attendees`) as Array<{ name: string; department?: string; email: string; - }>; + }> | undefined; - // 이미 선택된 사용자인지 확인 - const existingIndex = currentAttendees.findIndex( - (attendee) => attendee.email === user.email + // undefined이거나 배열이 아닌 경우 빈 배열로 처리 + const attendees = Array.isArray(currentAttendees) ? currentAttendees : []; + + // 이미 선택된 사용자인지 확인 (이메일 기준) + const existingIndex = attendees.findIndex( + (attendee) => attendee.email === selectedUser.email ); if (existingIndex >= 0) { @@ -263,20 +252,14 @@ function AttendeeSection({ } else { // 새로 추가 append({ - name: user.name, - department: user.deptName || "", - email: user.email, + name: selectedUser.name, + department: selectedUser.department || "", + email: selectedUser.email, }); } - }; - - const isUserSelected = (userEmail: string) => { - const currentAttendees = form.getValues(`shiAttendees.${itemKey}.attendees`) as Array<{ - name: string; - department?: string; - email: string; - }>; - return currentAttendees.some((attendee) => attendee.email === userEmail); + + // 선택 초기화 + setSelectedUserId(null); }; return ( @@ -296,7 +279,6 @@ function AttendeeSection({ // 체크 해제 시 참석자 목록 초기화 if (!checked) { form.setValue(`shiAttendees.${itemKey}.attendees` as any, []); - setIsPopoverOpen(false); } }} disabled={isPending} @@ -319,68 +301,27 @@ function AttendeeSection({ {isChecked && (
{/* 사용자 선택 UI */} - - - - - - - - - - {isLoadingUsers ? "로딩 중..." : "검색 결과가 없습니다."} - - - {users.map((user) => { - const selected = isUserSelected(user.email); - return ( - handleUserSelect(user)} - className="cursor-pointer" - > - -
-
- - {user.name} - - {user.deptName && ( - - ({user.deptName}) - - )} -
- - {user.email} - -
-
- ); - })} -
-
-
-
-
+
+
+ +
+ +
{/* 선택된 사용자 목록 */} {fields.length > 0 && ( -- cgit v1.2.3