summaryrefslogtreecommitdiff
path: root/lib/procurement-rfqs/table/rfq-table-toolbar-actions.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/procurement-rfqs/table/rfq-table-toolbar-actions.tsx')
-rw-r--r--lib/procurement-rfqs/table/rfq-table-toolbar-actions.tsx279
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