diff options
Diffstat (limited to 'lib/b-rfq/initial/initial-rfq-detail-toolbar-actions.tsx')
| -rw-r--r-- | lib/b-rfq/initial/initial-rfq-detail-toolbar-actions.tsx | 287 |
1 files changed, 0 insertions, 287 deletions
diff --git a/lib/b-rfq/initial/initial-rfq-detail-toolbar-actions.tsx b/lib/b-rfq/initial/initial-rfq-detail-toolbar-actions.tsx deleted file mode 100644 index c26bda28..00000000 --- a/lib/b-rfq/initial/initial-rfq-detail-toolbar-actions.tsx +++ /dev/null @@ -1,287 +0,0 @@ -"use client" - -import * as React from "react" -import { type Table } from "@tanstack/react-table" -import { useRouter } from "next/navigation" -import { toast } from "sonner" -import { Button } from "@/components/ui/button" -import { - Download, - Mail, - RefreshCw, - Settings, - Trash2, - FileText, - CheckCircle2, - Loader -} from "lucide-react" -import { AddInitialRfqDialog } from "./add-initial-rfq-dialog" -import { DeleteInitialRfqDialog } from "./delete-initial-rfq-dialog" -import { ShortListConfirmDialog } from "./short-list-confirm-dialog" -import { InitialRfqDetailView } from "@/db/schema" -import { sendBulkInitialRfqEmails } from "../service" - -interface InitialRfqDetailTableToolbarActionsProps { - table: Table<InitialRfqDetailView> - rfqId?: number - onRefresh?: () => void // 데이터 새로고침 콜백 -} - -export function InitialRfqDetailTableToolbarActions({ - table, - rfqId, - onRefresh -}: InitialRfqDetailTableToolbarActionsProps) { - const router = useRouter() - - // 선택된 행들 가져오기 - const selectedRows = table.getFilteredSelectedRowModel().rows - const selectedDetails = selectedRows.map((row) => row.original) - const selectedCount = selectedRows.length - - // 상태 관리 - const [showDeleteDialog, setShowDeleteDialog] = React.useState(false) - const [showShortListDialog, setShowShortListDialog] = React.useState(false) - const [isEmailSending, setIsEmailSending] = React.useState(false) - - // 전체 벤더 리스트 가져오기 (ShortList 확정용) - const allVendors = table.getRowModel().rows.map(row => row.original) - -const handleBulkEmail = async () => { - if (selectedCount === 0) return - - setIsEmailSending(true) - - try { - const initialRfqIds = selectedDetails - .map(detail => detail.initialRfqId) - .filter((id): id is number => id !== null); - - if (initialRfqIds.length === 0) { - toast.error("유효한 RFQ ID가 없습니다.") - return - } - - const result = await sendBulkInitialRfqEmails({ - initialRfqIds, - language: "en" // 기본 영어, 필요시 사용자 설정으로 변경 - }) - - if (result.success) { - toast.success(result.message) - - // 에러가 있다면 별도 알림 - if (result.errors && result.errors.length > 0) { - setTimeout(() => { - toast.warning(`일부 오류 발생: ${result.errors?.join(', ')}`) - }, 1000) - } - - // 선택 해제 - table.toggleAllRowsSelected(false) - - // 데이터 새로고침 - if (onRefresh) { - onRefresh() - } - } else { - toast.error(result.message || "RFQ 발송에 실패했습니다.") - } - - } catch (error) { - console.error("Email sending error:", error) - toast.error("RFQ 발송 중 오류가 발생했습니다.") - } finally { - setIsEmailSending(false) - } - } - - const handleBulkDelete = () => { - // DRAFT가 아닌 상태의 RFQ 확인 - const nonDraftRfqs = selectedDetails.filter( - detail => detail.initialRfqStatus !== "DRAFT" - ) - - if (nonDraftRfqs.length > 0) { - const statusMessages = { - "Init. RFQ Sent": "이미 발송된", - "S/L Decline": "Short List 거절 처리된", - "Init. RFQ Answered": "답변 완료된" - } - - const nonDraftStatuses = [...new Set(nonDraftRfqs.map(rfq => rfq.initialRfqStatus))] - const statusText = nonDraftStatuses - .map(status => statusMessages[status as keyof typeof statusMessages] || status) - .join(", ") - - toast.error( - `${statusText} RFQ는 삭제할 수 없습니다. DRAFT 상태의 RFQ만 삭제 가능합니다.` - ) - return - } - - setShowDeleteDialog(true) - } - - // S/L 확정 버튼 클릭 - const handleSlConfirm = () => { - if (!rfqId || allVendors.length === 0) { - toast.error("S/L 확정할 벤더가 없습니다.") - return - } - - // 진행 가능한 상태 확인 - const validVendors = allVendors.filter(vendor => - vendor.initialRfqStatus === "Init. RFQ Answered" || - vendor.initialRfqStatus === "Init. RFQ Sent" - ) - - if (validVendors.length === 0) { - toast.error("S/L 확정이 가능한 벤더가 없습니다. (RFQ 발송 또는 응답 완료된 벤더만 가능)") - return - } - - setShowShortListDialog(true) - } - - // 초기 RFQ 추가 성공 시 처리 - const handleAddSuccess = () => { - // 선택 해제 - table.toggleAllRowsSelected(false) - - // 데이터 새로고침 - if (onRefresh) { - onRefresh() - } else { - // fallback으로 페이지 새로고침 - setTimeout(() => { - window.location.reload() - }, 1000) - } - } - - // 삭제 성공 시 처리 - const handleDeleteSuccess = () => { - // 선택 해제 - table.toggleAllRowsSelected(false) - setShowDeleteDialog(false) - - // 데이터 새로고침 - if (onRefresh) { - onRefresh() - } - } - - // Short List 확정 성공 시 처리 - const handleShortListSuccess = () => { - // 선택 해제 - table.toggleAllRowsSelected(false) - setShowShortListDialog(false) - - // 데이터 새로고침 - if (onRefresh) { - onRefresh() - } - - // 최종 RFQ 페이지로 이동 - if (rfqId) { - toast.success("Short List가 확정되었습니다. 최종 RFQ 페이지로 이동합니다.") - setTimeout(() => { - router.push(`/evcp/b-rfq/${rfqId}`) - }, 1500) - } - } - - // 선택된 항목 중 첫 번째를 기본값으로 사용 - const defaultValues = selectedCount > 0 ? selectedDetails[0] : undefined - - const canDelete = selectedDetails.every(detail => detail.initialRfqStatus === "DRAFT") - const draftCount = selectedDetails.filter(detail => detail.initialRfqStatus === "DRAFT").length - - // S/L 확정 가능한 벤더 수 - const validForShortList = allVendors.filter(vendor => - vendor.initialRfqStatus === "Init. RFQ Answered" || - vendor.initialRfqStatus === "Init. RFQ Sent" - ).length - - return ( - <> - <div className="flex items-center gap-2"> - {/** 선택된 항목이 있을 때만 표시되는 액션들 */} - {selectedCount > 0 && ( - <> - <Button - variant="outline" - size="sm" - onClick={handleBulkEmail} - className="h-8" - disabled={isEmailSending} - > - {isEmailSending ? <Loader className="mr-2 h-4 w-4 animate-spin" /> : <Mail className="mr-2 h-4 w-4" />} - RFQ 발송 ({selectedCount}) - </Button> - - <Button - variant="outline" - size="sm" - onClick={handleBulkDelete} - className="h-8 text-red-600 hover:text-red-700" - disabled={!canDelete || selectedCount === 0} - title={!canDelete ? "DRAFT 상태의 RFQ만 삭제할 수 있습니다" : ""} - > - <Trash2 className="mr-2 h-4 w-4" /> - 삭제 ({draftCount}/{selectedCount}) - </Button> - </> - )} - - {/* S/L 확정 버튼 */} - {rfqId && ( - <Button - variant="default" - size="sm" - onClick={handleSlConfirm} - className="h-8" - disabled={validForShortList === 0} - title={validForShortList === 0 ? "S/L 확정이 가능한 벤더가 없습니다" : `${validForShortList}개 벤더 중 Short List 선택`} - > - <CheckCircle2 className="mr-2 h-4 w-4" /> - S/L 확정 ({validForShortList}) - </Button> - )} - - {/* 초기 RFQ 추가 버튼 */} - {rfqId && ( - <AddInitialRfqDialog - rfqId={rfqId} - onSuccess={handleAddSuccess} - defaultValues={defaultValues} - /> - )} - </div> - - {/* 삭제 다이얼로그 */} - <DeleteInitialRfqDialog - open={showDeleteDialog} - onOpenChange={setShowDeleteDialog} - initialRfqs={selectedDetails} - showTrigger={false} - onSuccess={handleDeleteSuccess} - /> - - {/* Short List 확정 다이얼로그 */} - {rfqId && ( - <ShortListConfirmDialog - open={showShortListDialog} - onOpenChange={setShowShortListDialog} - rfqId={rfqId} - vendors={allVendors.filter(vendor => - vendor.initialRfqStatus === "Init. RFQ Answered" || - vendor.initialRfqStatus === "Init. RFQ Sent" - )} - onSuccess={handleShortListSuccess} - /> - )} - </> - ) -}
\ No newline at end of file |
