diff options
Diffstat (limited to 'lib/procurement-rfqs/table/rfq-table-toolbar-actions.tsx')
| -rw-r--r-- | lib/procurement-rfqs/table/rfq-table-toolbar-actions.tsx | 279 |
1 files changed, 0 insertions, 279 deletions
diff --git a/lib/procurement-rfqs/table/rfq-table-toolbar-actions.tsx b/lib/procurement-rfqs/table/rfq-table-toolbar-actions.tsx deleted file mode 100644 index 26725797..00000000 --- a/lib/procurement-rfqs/table/rfq-table-toolbar-actions.tsx +++ /dev/null @@ -1,279 +0,0 @@ -"use client" - -import * as React from "react" -import { type Table } from "@tanstack/react-table" -import { ClipboardList, Download, Send, Lock, Upload } from "lucide-react" -import { toast } from "sonner" - -import { exportTableToExcel } from "@/lib/export" -import { Button } from "@/components/ui/button" -import { ProcurementRfqsView } from "@/db/schema" -import { PrDetailsDialog } from "./pr-item-dialog" -import { sealRfq, sendRfq, getPORfqs, fetchExternalRfqs } from "../services" - -// total 필드 추가하여 타입 정의 수정 -type PORfqsReturn = Awaited<ReturnType<typeof getPORfqs>> - -interface RFQTableToolbarActionsProps { - table: Table<ProcurementRfqsView>; - // 타입 수정 - localData?: PORfqsReturn; - setLocalData?: React.Dispatch<React.SetStateAction<PORfqsReturn>>; - onSuccess?: () => void; -} - -export function RFQTableToolbarActions({ - table, - localData, - setLocalData, - onSuccess -}: RFQTableToolbarActionsProps) { - // 다이얼로그 열림/닫힘 상태 관리 - const [dialogOpen, setDialogOpen] = React.useState(false) - const [isProcessing, setIsProcessing] = React.useState(false) - - // 선택된 RFQ 가져오기 - const getSelectedRfq = (): ProcurementRfqsView | null => { - const selectedRows = table.getFilteredSelectedRowModel().rows - if (selectedRows.length === 1) { - return selectedRows[0].original - } - return null - } - - // 선택된 RFQ - const selectedRfq = getSelectedRfq() - - // PR 상세보기 버튼 클릭 핸들러 - const handleViewPrDetails = () => { - const rfq = getSelectedRfq() - if (!rfq) { - toast.warning("RFQ를 선택해주세요") - return - } - - if (!rfq.prItemsCount || rfq.prItemsCount <= 0) { - toast.warning("선택한 RFQ에 PR 항목이 없습니다") - return - } - - setDialogOpen(true) - } - - // RFQ 밀봉 버튼 클릭 핸들러 - const handleSealRfq = async () => { - const rfq = getSelectedRfq() - if (!rfq) { - toast.warning("RFQ를 선택해주세요") - return - } - - // 이미 밀봉된 RFQ인 경우 - if (rfq.rfqSealedYn) { - toast.warning("이미 밀봉된 RFQ입니다") - return - } - - try { - setIsProcessing(true) - - // 낙관적 UI 업데이트 (로컬 데이터 먼저 갱신) - if (localData?.data && setLocalData) { - // 로컬 데이터에서 해당 행 찾기 - const rowIndex = localData.data.findIndex(row => row.id === rfq.id); - if (rowIndex >= 0) { - // 불변성을 유지하면서 로컬 데이터 업데이트 - 타입 안전하게 복사 - const newData = [...localData.data] as ProcurementRfqsView[]; - newData[rowIndex] = { ...newData[rowIndex], rfqSealedYn: "Y" }; - - // 전체 데이터 구조 복사하여 업데이트, total 필드가 있다면 유지 - setLocalData({ - ...localData, - data: newData ?? [], - pageCount: localData.pageCount, - total: localData.total ?? 0 - }); - } - } - - const result = await sealRfq(rfq.id) - - if (result.success) { - toast.success("RFQ가 성공적으로 밀봉되었습니다") - // 데이터 리프레시 - onSuccess?.() - } else { - toast.error(result.message || "RFQ 밀봉 중 오류가 발생했습니다") - - // 서버 요청 실패 시 낙관적 업데이트 되돌리기 - if (localData?.data && setLocalData) { - const rowIndex = localData.data.findIndex(row => row.id === rfq.id); - if (rowIndex >= 0) { - const newData = [...localData.data] as ProcurementRfqsView[]; - newData[rowIndex] = { ...newData[rowIndex], rfqSealedYn: rfq.rfqSealedYn }; // 원래 값으로 복원 - setLocalData({ - ...localData, - data: newData ?? [], - pageCount: localData.pageCount, - total: localData.total ?? 0 - }); - } - } - } - } catch (error) { - console.error("RFQ 밀봉 오류:", error) - toast.error("RFQ 밀봉 중 오류가 발생했습니다") - - // 에러 발생 시 낙관적 업데이트 되돌리기 - if (localData?.data && setLocalData) { - const rowIndex = localData.data.findIndex(row => row.id === rfq.id); - if (rowIndex >= 0) { - const newData = [...localData.data] as ProcurementRfqsView[]; - newData[rowIndex] = { ...newData[rowIndex], rfqSealedYn: rfq.rfqSealedYn }; // 원래 값으로 복원 - setLocalData({ - ...localData, - data: newData ?? [], - pageCount: localData.pageCount, - total: localData.total ?? 0 - }); - } - } - } finally { - setIsProcessing(false) - } - } - - // RFQ 전송 버튼 클릭 핸들러 - const handleSendRfq = async () => { - const rfq = getSelectedRfq() - if (!rfq) { - toast.warning("RFQ를 선택해주세요") - return - } - - // 전송 가능한 상태인지 확인 - if (rfq.status !== "RFQ Vendor Assignned" && rfq.status !== "RFQ Sent") { - toast.warning("벤더가 할당된 RFQ이거나 전송한 적이 있는 RFQ만 전송할 수 있습니다") - return - } - - try { - setIsProcessing(true) - - const result = await sendRfq(rfq.id) - - if (result.success) { - toast.success("RFQ가 성공적으로 전송되었습니다") - // 데이터 리프레시 - onSuccess?.() - } else { - toast.error(result.message || "RFQ 전송 중 오류가 발생했습니다") - } - } catch (error) { - console.error("RFQ 전송 오류:", error) - toast.error("RFQ 전송 중 오류가 발생했습니다") - } finally { - setIsProcessing(false) - } - } - - const handleFetchExternalRfqs = async () => { - try { - setIsProcessing(true); - - const result = await fetchExternalRfqs(); - - if (result.success) { - toast.success(result.message || "외부 RFQ를 성공적으로 가져왔습니다"); - // 데이터 리프레시 - onSuccess?.() - } else { - toast.error(result.message || "외부 RFQ를 가져오는 중 오류가 발생했습니다"); - } - } catch (error) { - console.error("외부 RFQ 가져오기 오류:", error); - toast.error("외부 RFQ를 가져오는 중 오류가 발생했습니다"); - } finally { - setIsProcessing(false); - } - }; - - return ( - <> - <div className="flex items-center gap-2"> - <Button - variant="outline" - size="sm" - onClick={() => - exportTableToExcel(table, { - filename: "rfq", - excludeColumns: ["select", "actions"], - }) - } - className="gap-2" - > - <Download className="size-4" aria-hidden="true" /> - <span className="hidden sm:inline">Export</span> - </Button> - {/* RFQ 가져오기 버튼 */} - <Button - variant="outline" - size="sm" - onClick={handleFetchExternalRfqs} - className="gap-2" - disabled={isProcessing} - > - <Upload className="size-4" aria-hidden="true" /> - <span className="hidden sm:inline">RFQ 가져오기</span> - </Button> - - {/* PR 상세보기 버튼 */} - <Button - variant="outline" - size="sm" - onClick={handleViewPrDetails} - className="gap-2" - disabled={!selectedRfq || !(selectedRfq.prItemsCount && selectedRfq.prItemsCount > 0)} - > - <ClipboardList className="size-4" aria-hidden="true" /> - <span className="hidden sm:inline">PR 상세보기</span> - </Button> - - {/* RFQ 밀봉 버튼 */} - <Button - variant="outline" - size="sm" - onClick={handleSealRfq} - className="gap-2" - disabled={!selectedRfq || selectedRfq.rfqSealedYn === "Y" || selectedRfq.status !== "RFQ Sent" || isProcessing} - > - <Lock className="size-4" aria-hidden="true" /> - <span className="hidden sm:inline">RFQ 밀봉</span> - </Button> - - {/* RFQ 전송 버튼 */} - <Button - variant="outline" - size="sm" - onClick={handleSendRfq} - className="gap-2" - disabled={ - !selectedRfq || - (selectedRfq.status !== "RFQ Vendor Assignned" && selectedRfq.status !== "RFQ Sent") || - isProcessing - } - > - <Send className="size-4" aria-hidden="true" /> - <span className="hidden sm:inline">RFQ 전송</span> - </Button> - </div> - - {/* PR 상세정보 다이얼로그 */} - <PrDetailsDialog - open={dialogOpen} - onOpenChange={setDialogOpen} - selectedRfq={selectedRfq} - /> - </> - ) -}
\ No newline at end of file |
