diff options
| author | joonhoekim <26rote@gmail.com> | 2025-09-29 20:57:09 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-09-29 20:57:09 +0900 |
| commit | b33d6909064b9aeba77e6b05f3dbabce7b551b6b (patch) | |
| tree | b8910dcc45f9ea3f9b6129fa2c01849d2c6a3d7a /lib/rfq-last | |
| parent | 8438c05efc7a141e349c5d6416ad08156b4c0775 (diff) | |
(김준회) ITB 구매담당자 지정 관련 요구사항 처리
- 오류수정(스크롤, 검색)
- 휴직, 퇴직 정보추가
Diffstat (limited to 'lib/rfq-last')
| -rw-r--r-- | lib/rfq-last/service.ts | 5 | ||||
| -rw-r--r-- | lib/rfq-last/table/rfq-assign-pic-dialog.tsx | 99 |
2 files changed, 81 insertions, 23 deletions
diff --git a/lib/rfq-last/service.ts b/lib/rfq-last/service.ts index 2baf1f46..8eed9bee 100644 --- a/lib/rfq-last/service.ts +++ b/lib/rfq-last/service.ts @@ -254,6 +254,8 @@ export async function getRfqAllAttachments(rfqId: number) { } } } + + // 사용자 목록 조회 (필터용), 견적담당자, 구매담당자 export async function getPUsersForFilter() { @@ -263,6 +265,9 @@ export async function getPUsersForFilter() { id: users.id, name: users.name, userCode: users.userCode, + deptName: users.deptName, + isAbsent: users.isAbsent, + isDeletedOnNonSap: users.isDeletedOnNonSap, }) .from(users) .where(and(eq(users.isActive, true), isNotNull(users.userCode,))) diff --git a/lib/rfq-last/table/rfq-assign-pic-dialog.tsx b/lib/rfq-last/table/rfq-assign-pic-dialog.tsx index 89dda979..94dde779 100644 --- a/lib/rfq-last/table/rfq-assign-pic-dialog.tsx +++ b/lib/rfq-last/table/rfq-assign-pic-dialog.tsx @@ -33,8 +33,11 @@ import { Alert, AlertDescription } from "@/components/ui/alert"; interface User { id: number; - name: string; - userCode?: string; + name: string | null; + userCode: string | null; + deptName: string | null; + isAbsent: boolean | null; + isDeletedOnNonSap: boolean | null; email?: string; } @@ -53,7 +56,7 @@ export function RfqAssignPicDialog({ selectedRfqCodes, onSuccess, }: RfqAssignPicDialogProps) { - const [users, setUsers] = React.useState<User[]>([]); + const [users, setUsers] = React.useState<User[]>([] as User[]); const [isLoadingUsers, setIsLoadingUsers] = React.useState(false); const [isAssigning, setIsAssigning] = React.useState(false); const [selectedUser, setSelectedUser] = React.useState<User | null>(null); @@ -75,7 +78,7 @@ export function RfqAssignPicDialog({ setIsLoadingUsers(true); try { const userList = await getPUsersForFilter(); - setUsers(userList); + setUsers(userList as User[]); } catch (error) { console.log("사용자 목록 로드 오류:", error); toast.error("사용자 목록을 불러오는데 실패했습니다"); @@ -94,13 +97,14 @@ export function RfqAssignPicDialog({ // 유저 검색 const filteredUsers = React.useMemo(() => { - if (!userSearchTerm) return users; - - const lowerSearchTerm = userSearchTerm.toLowerCase(); + if (!userSearchTerm || !userSearchTerm.trim()) return users; + + const searchTerm = userSearchTerm.trim(); return users.filter( (user) => - user.name.toLowerCase().includes(lowerSearchTerm) || - user.userCode?.toLowerCase().includes(lowerSearchTerm) + (user.name && user.name.includes(searchTerm)) || + (user.userCode && user.userCode.toLowerCase().includes(searchTerm.toLowerCase())) || + (user.deptName && user.deptName.includes(searchTerm)) ); }, [users, userSearchTerm]); @@ -233,30 +237,58 @@ export function RfqAssignPicDialog({ </Button> </PopoverTrigger> <PopoverContent className="w-[460px] p-0"> - <Command> + <Command shouldFilter={false}> <CommandInput - placeholder="이름 또는 코드로 검색..." + placeholder="이름, 구매그룹코드 또는 부서로 검색..." value={userSearchTerm} onValueChange={setUserSearchTerm} /> <CommandList className="max-h-[300px]"> <CommandEmpty>검색 결과가 없습니다</CommandEmpty> - <CommandGroup> + <CommandGroup + className="overflow-y-auto" + onWheel={(e) => { + // 마우스 휠 스크롤이 제대로 작동하도록 이벤트 전파 허용 + e.stopPropagation(); + }} + > {filteredUsers.map((user) => ( <CommandItem key={user.id} + value={`${user.name || ''} ${user.userCode || ''} ${user.deptName || ''}`} onSelect={() => handleSelectUser(user)} className="flex items-center justify-between" > - <span className="flex items-center gap-2"> - <User className="h-4 w-4" /> - {user.name} - {user.userCode && ( - <span className="text-muted-foreground text-sm"> - ({user.userCode}) + <div className="flex flex-col gap-1"> + <div className="flex items-center gap-2"> + <User className="h-4 w-4" /> + <span>{user.name || '이름 없음'}</span> + {user.userCode && ( + <span className="text-muted-foreground text-sm"> + ({user.userCode}) + </span> + )} + {(user.isAbsent || user.isDeletedOnNonSap) && ( + <div className="flex gap-1"> + {user.isAbsent && ( + <Badge variant="outline" className="text-xs px-1 py-0"> + 휴직 + </Badge> + )} + {user.isDeletedOnNonSap && ( + <Badge variant="outline" className="text-xs px-1 py-0"> + 퇴직 + </Badge> + )} + </div> + )} + </div> + {user.deptName && ( + <span className="text-xs text-muted-foreground"> + {user.deptName} </span> )} - </span> + </div> <Check className={cn( "h-4 w-4", @@ -273,10 +305,31 @@ export function RfqAssignPicDialog({ </PopoverContent> </Popover> {selectedUser && ( - <p className="text-xs text-muted-foreground"> - 선택한 담당자: {selectedUser.name} - {selectedUser.userCode && ` (${selectedUser.userCode})`} - </p> + <div className="text-xs text-muted-foreground"> + <div className="flex items-center gap-2"> + <p> + 선택한 담당자: {selectedUser.name || '이름 없음'} + {selectedUser.userCode && ` (${selectedUser.userCode})`} + </p> + {(selectedUser.isAbsent || selectedUser.isDeletedOnNonSap) && ( + <div className="flex gap-1"> + {selectedUser.isAbsent && ( + <Badge variant="outline" className="text-xs px-1 py-0 border-orange-300 text-orange-700 bg-orange-50"> + 휴직 + </Badge> + )} + {selectedUser.isDeletedOnNonSap && ( + <Badge variant="outline" className="text-xs px-1 py-0 border-red-300 text-red-700 bg-red-50"> + 퇴직 + </Badge> + )} + </div> + )} + </div> + {selectedUser.deptName && ( + <p>{selectedUser.deptName}</p> + )} + </div> )} </div> </div> |
