// components/purchase-requests/create-rfq-dialog.tsx "use client"; import * as React from "react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Badge } from "@/components/ui/badge"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { FileText, Package, AlertCircle, CheckCircle, User, ChevronsUpDown, Check, Loader2, Info } from "lucide-react"; import { toast } from "sonner"; import { cn } from "@/lib/utils"; import type { PurchaseRequestView } from "@/db/schema"; import { approvePurchaseRequestsAndCreateRfqs } from "../service"; import { getPUsersForFilter } from "@/lib/rfq-last/service"; import { useRouter } from "next/navigation"; interface CreateRfqDialogProps { requests: PurchaseRequestView[]; open: boolean; onOpenChange: (open: boolean) => void; onSuccess?: () => void; } export function CreateRfqDialog({ requests, open, onOpenChange, onSuccess, }: CreateRfqDialogProps) { const [isLoading, setIsLoading] = React.useState(false); const [userPopoverOpen, setUserPopoverOpen] = React.useState(false); const [users, setUsers] = React.useState([]); const [selectedUser, setSelectedUser] = React.useState(null); const [isLoadingUsers, setIsLoadingUsers] = React.useState(false); const [userSearchTerm, setUserSearchTerm] = React.useState(""); const router = useRouter(); // 유저 목록 로드 React.useEffect(() => { const loadUsers = async () => { setIsLoadingUsers(true); try { const userList = await getPUsersForFilter(); setUsers(userList); } catch (error) { console.log("사용자 목록 로드 오류:", error); toast.error("사용자 목록을 불러오는데 실패했습니다"); } finally { setIsLoadingUsers(false); } }; if (open) { loadUsers(); } }, [open]); // 검색된 사용자 필터링 const filteredUsers = React.useMemo(() => { if (!userSearchTerm) return users; return users.filter(user => user.name.toLowerCase().includes(userSearchTerm.toLowerCase()) || user.userCode?.toLowerCase().includes(userSearchTerm.toLowerCase()) ); }, [users, userSearchTerm]); // 유효한 요청만 필터링 (이미 RFQ 생성된 것 제외) const validRequests = requests.filter(r => r.status !== "RFQ생성완료"); const invalidRequests = requests.filter(r => r.status === "RFQ생성완료"); const handleSelectUser = (user: any) => { setSelectedUser(user); setUserPopoverOpen(false); }; const handleSubmit = async () => { if (validRequests.length === 0) { toast.error("RFQ를 생성할 수 있는 구매 요청이 없습니다"); return; } try { setIsLoading(true); const requestIds = validRequests.map(r => r.id); const results = await approvePurchaseRequestsAndCreateRfqs( requestIds, selectedUser?.id ); const successCount = results.filter(r => r.success).length; const skipCount = results.filter(r => r.skipped).length; if (successCount > 0) { toast.success(`${successCount}개의 RFQ가 생성되었습니다`); } if (skipCount > 0) { toast.info(`${skipCount}개는 이미 RFQ가 생성되어 건너뛰었습니다`); } onOpenChange(false); onSuccess?.(); router.refresh() } catch (error) { console.error("RFQ 생성 오류:", error); toast.error("RFQ 생성 중 오류가 발생했습니다"); } finally { setIsLoading(false); } }; const handleClose = () => { if (!isLoading) { setSelectedUser(null); setUserSearchTerm(""); onOpenChange(false); } }; return ( RFQ 생성 선택한 구매 요청을 기반으로 RFQ를 생성합니다. {invalidRequests.length > 0 && " 이미 RFQ가 생성된 항목은 제외됩니다."}
{/* 경고 메시지 */} {invalidRequests.length > 0 && ( {invalidRequests.length}개 항목은 이미 RFQ가 생성되어 제외됩니다. )} {/* 구매 담당자 선택 */}
검색 결과가 없습니다 {filteredUsers.map((user) => ( handleSelectUser(user)} className="flex items-center justify-between" > {user.name} {user.userCode && ( ({user.userCode}) )} ))}

구매 담당자를 선택하지 않으면 나중에 지정할 수 있습니다

{/* RFQ 생성 대상 목록 */}
요청번호 요청제목 프로젝트 패키지 품목 첨부 {validRequests.length === 0 ? ( RFQ를 생성할 수 있는 구매 요청이 없습니다 ) : ( validRequests.map((request) => ( {request.requestCode}
{request.requestTitle}
{request.projectCode}
{request.packageNo}
{request.itemCount > 0 && ( {request.itemCount} )} {request.attachmentCount > 0 && ( {request.attachmentCount} )}
)) )}
{/* 안내 메시지 */}
  • RFQ 생성 시 구매 요청의 첨부파일이 자동으로 이관됩니다
  • 구매 요청 상태가 "RFQ생성완료"로 변경됩니다
  • 각 구매 요청별로 개별 RFQ가 생성됩니다
); }