From 8e70ba35379d21d89704f1095b7fd32bf286525d Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Thu, 2 Oct 2025 14:08:33 +0900 Subject: (김준회) ITB 및 일반견적 선택시 구매담당자 선택을 구매그룹코드로 처리하도록 변경, 오라클 연결 불가한 경우 하드코딩된 폴백데이터 제공처리 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/rfq-last/table/rfq-assign-pic-dialog.tsx | 279 ++++++++------------------- 1 file changed, 80 insertions(+), 199 deletions(-) (limited to 'lib/rfq-last/table/rfq-assign-pic-dialog.tsx') diff --git a/lib/rfq-last/table/rfq-assign-pic-dialog.tsx b/lib/rfq-last/table/rfq-assign-pic-dialog.tsx index 94dde779..9ca34ccd 100644 --- a/lib/rfq-last/table/rfq-assign-pic-dialog.tsx +++ b/lib/rfq-last/table/rfq-assign-pic-dialog.tsx @@ -10,36 +10,15 @@ import { DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, -} from "@/components/ui/command"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/components/ui/popover"; -import { Check, ChevronsUpDown, Loader2, User, Users } from "lucide-react"; -import { cn } from "@/lib/utils"; +import { Loader2, Users } from "lucide-react"; import { toast } from "sonner"; -import { getPUsersForFilter } from "@/lib/rfq-last/service"; import { assignPicToRfqs } from "../service"; import { Badge } from "@/components/ui/badge"; import { Alert, AlertDescription } from "@/components/ui/alert"; - -interface User { - id: number; - name: string | null; - userCode: string | null; - deptName: string | null; - isAbsent: boolean | null; - isDeletedOnNonSap: boolean | null; - email?: string; -} +import { + PurchaseGroupCodeSingleSelector, + PurchaseGroupCodeWithUser +} from "@/components/common/selectors/purchase-group-code"; interface RfqAssignPicDialogProps { open: boolean; @@ -56,12 +35,9 @@ export function RfqAssignPicDialog({ selectedRfqCodes, onSuccess, }: RfqAssignPicDialogProps) { - const [users, setUsers] = React.useState([] as User[]); - const [isLoadingUsers, setIsLoadingUsers] = React.useState(false); const [isAssigning, setIsAssigning] = React.useState(false); - const [selectedUser, setSelectedUser] = React.useState(null); - const [userPopoverOpen, setUserPopoverOpen] = React.useState(false); - const [userSearchTerm, setUserSearchTerm] = React.useState(""); + const [selectedCode, setSelectedCode] = React.useState(undefined); + const [selectorOpen, setSelectorOpen] = React.useState(false); // ITB만 필터링 (rfqCode가 "I"로 시작하는 것) const itbCodes = React.useMemo(() => { @@ -72,50 +48,36 @@ export function RfqAssignPicDialog({ return selectedRfqIds.filter((id, index) => selectedRfqCodes[index]?.startsWith("I")); }, [selectedRfqIds, selectedRfqCodes]); - // 유저 목록 로드 + // 다이얼로그 열릴 때 초기화 React.useEffect(() => { - const loadUsers = async () => { - setIsLoadingUsers(true); - try { - const userList = await getPUsersForFilter(); - setUsers(userList as User[]); - } catch (error) { - console.log("사용자 목록 로드 오류:", error); - toast.error("사용자 목록을 불러오는데 실패했습니다"); - } finally { - setIsLoadingUsers(false); - } - }; - if (open) { - loadUsers(); - // 다이얼로그 열릴 때 초기화 - setSelectedUser(null); - setUserSearchTerm(""); + setSelectedCode(undefined); } }, [open]); - // 유저 검색 - const filteredUsers = React.useMemo(() => { - if (!userSearchTerm || !userSearchTerm.trim()) return users; - - const searchTerm = userSearchTerm.trim(); - return users.filter( - (user) => - (user.name && user.name.includes(searchTerm)) || - (user.userCode && user.userCode.toLowerCase().includes(searchTerm.toLowerCase())) || - (user.deptName && user.deptName.includes(searchTerm)) - ); - }, [users, userSearchTerm]); - - const handleSelectUser = (user: User) => { - setSelectedUser(user); - setUserPopoverOpen(false); + const handleCodeSelect = (code: PurchaseGroupCodeWithUser) => { + setSelectedCode(code); + + // 유저 정보가 없는 경우 toast로 알림 + if (!code.user) { + toast.warning( + `해당 구매그룹코드(${code.PURCHASE_GROUP_CODE})의 사번 정보의 유저가 없습니다`, + { + description: `사번: ${code.EMPLOYEE_NUMBER}`, + duration: 5000, + } + ); + } }; const handleAssign = async () => { - if (!selectedUser) { - toast.error("담당자를 선택해주세요"); + if (!selectedCode) { + toast.error("구매그룹코드를 선택해주세요"); + return; + } + + if (!selectedCode.user) { + toast.error("선택한 구매그룹코드에 연결된 사용자가 없습니다"); return; } @@ -128,7 +90,7 @@ export function RfqAssignPicDialog({ try { const result = await assignPicToRfqs({ rfqIds: itbIds, - picUserId: selectedUser.id, + picUserId: selectedCode.user.id, }); if (result.success) { @@ -196,144 +158,63 @@ export function RfqAssignPicDialog({ )} - {/* 담당자 선택 */} + {/* 구매 담당자 선택 (구매그룹코드) */}
- - - - - - - - - - 검색 결과가 없습니다 - { - // 마우스 휠 스크롤이 제대로 작동하도록 이벤트 전파 허용 - e.stopPropagation(); - }} - > - {filteredUsers.map((user) => ( - handleSelectUser(user)} - className="flex items-center justify-between" - > -
-
- - {user.name || '이름 없음'} - {user.userCode && ( - - ({user.userCode}) - - )} - {(user.isAbsent || user.isDeletedOnNonSap) && ( -
- {user.isAbsent && ( - - 휴직 - - )} - {user.isDeletedOnNonSap && ( - - 퇴직 - - )} -
- )} -
- {user.deptName && ( - - {user.deptName} - - )} -
- -
- ))} -
-
-
-
-
- {selectedUser && ( -
-
-

- 선택한 담당자: {selectedUser.name || '이름 없음'} - {selectedUser.userCode && ` (${selectedUser.userCode})`} -

- {(selectedUser.isAbsent || selectedUser.isDeletedOnNonSap) && ( -
- {selectedUser.isAbsent && ( - - 휴직 - - )} - {selectedUser.isDeletedOnNonSap && ( - - 퇴직 - - )} + {!selectedCode.user && ( +
+ ⚠️ 연결된 사용자가 없습니다
)}
- {selectedUser.deptName && ( -

{selectedUser.deptName}

- )} -
+ ) : ( + + 구매그룹코드를 선택하세요 + + )} + + + {selectedCode && !selectedCode.user && ( + + + 선택한 구매그룹코드에 연결된 사용자가 없습니다. 다른 구매그룹코드를 선택해주세요. + + )}
+ {/* 구매그룹코드 선택 다이얼로그 */} + +