summaryrefslogtreecommitdiff
path: root/lib/basic-contract/template
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-17 05:39:58 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-17 05:39:58 +0000
commitc54e2acaed641b7ae2c1a7304b08626f9ca973db (patch)
tree3f4dc361fc6267e2fb50d8488f40d4bbe4efd5e2 /lib/basic-contract/template
parent6c11fccc84f4c84fa72ee01f9caad9f76f35cea2 (diff)
(임수민) 기본계약 폐기하기, 수정하기 수정
Diffstat (limited to 'lib/basic-contract/template')
-rw-r--r--lib/basic-contract/template/basic-contract-template.tsx12
-rw-r--r--lib/basic-contract/template/basicContract-table-toolbar-actions.tsx34
-rw-r--r--lib/basic-contract/template/dispose-documents-dialog.tsx122
3 files changed, 163 insertions, 5 deletions
diff --git a/lib/basic-contract/template/basic-contract-template.tsx b/lib/basic-contract/template/basic-contract-template.tsx
index 8ac421f5..ba24187b 100644
--- a/lib/basic-contract/template/basic-contract-template.tsx
+++ b/lib/basic-contract/template/basic-contract-template.tsx
@@ -14,6 +14,7 @@ import { getColumns } from "./basic-contract-template-columns";
import { DeleteTemplatesDialog } from "./delete-basicContract-dialog";
import { UpdateTemplateSheet } from "./update-basicContract-sheet";
import { CreateRevisionDialog } from "./create-revision-dialog";
+import { DisposeDocumentsDialog } from "./dispose-documents-dialog";
import { TemplateTableToolbarActions } from "./basicContract-table-toolbar-actions";
import { BasicContractTemplate } from "@/db/schema";
@@ -104,6 +105,17 @@ export function BasicContractTemplateTable({ promises }: BasicTemplateTableProps
router.refresh();
}}
/>
+
+ <DisposeDocumentsDialog
+ open={rowAction?.type === "dispose" || rowAction?.type === "restore"}
+ onOpenChange={() => setRowAction(null)}
+ documents={rowAction?.row.original ? [rowAction?.row.original] : []}
+ showTrigger={false}
+ onSuccess={() => {
+ setRowAction(null);
+ router.refresh();
+ }}
+ />
</>
);
} \ No newline at end of file
diff --git a/lib/basic-contract/template/basicContract-table-toolbar-actions.tsx b/lib/basic-contract/template/basicContract-table-toolbar-actions.tsx
index 439fea26..850dc0a5 100644
--- a/lib/basic-contract/template/basicContract-table-toolbar-actions.tsx
+++ b/lib/basic-contract/template/basicContract-table-toolbar-actions.tsx
@@ -9,6 +9,7 @@ import { exportTableToExcel } from "@/lib/export"
import { Button } from "@/components/ui/button"
import { DeleteTemplatesDialog } from "./delete-basicContract-dialog"
import { AddTemplateDialog } from "./add-basic-contract-template-dialog"
+import { DisposeDocumentsDialog } from "./dispose-documents-dialog"
import { BasicContractTemplate } from "@/db/schema"
interface TemplateTableToolbarActionsProps {
@@ -17,16 +18,39 @@ interface TemplateTableToolbarActionsProps {
export function TemplateTableToolbarActions({ table }: TemplateTableToolbarActionsProps) {
// 파일 input을 숨기고, 버튼 클릭 시 참조해 클릭하는 방식
-
+ const selectedRows = table.getFilteredSelectedRowModel().rows
+ const selectedDocuments = selectedRows.map((row) => row.original)
+
+ // 선택된 문서들의 상태 확인
+ const hasActiveDocuments = selectedDocuments.some(doc => doc.status === 'ACTIVE')
+ const hasDisposedDocuments = selectedDocuments.some(doc => doc.status === 'DISPOSED')
return (
<div className="flex items-center gap-2">
{/** 1) 선택된 로우가 있으면 삭제 다이얼로그 */}
- {table.getFilteredSelectedRowModel().rows.length > 0 ? (
+ {selectedRows.length > 0 ? (
<DeleteTemplatesDialog
- templates={table
- .getFilteredSelectedRowModel()
- .rows.map((row) => row.original)}
+ templates={selectedDocuments}
+ onSuccess={() => table.toggleAllRowsSelected(false)}
+ />
+ ) : null}
+
+ {/** 2) 선택된 활성 문서가 있으면 폐기 다이얼로그 */}
+ {selectedRows.length > 0 && hasActiveDocuments ? (
+ <DisposeDocumentsDialog
+ open={false}
+ onOpenChange={() => {}}
+ documents={selectedDocuments.filter(doc => doc.status === 'ACTIVE')}
+ onSuccess={() => table.toggleAllRowsSelected(false)}
+ />
+ ) : null}
+
+ {/** 3) 선택된 폐기 문서가 있으면 복구 다이얼로그 */}
+ {selectedRows.length > 0 && hasDisposedDocuments ? (
+ <DisposeDocumentsDialog
+ open={false}
+ onOpenChange={() => {}}
+ documents={selectedDocuments.filter(doc => doc.status === 'DISPOSED')}
onSuccess={() => table.toggleAllRowsSelected(false)}
/>
) : null}
diff --git a/lib/basic-contract/template/dispose-documents-dialog.tsx b/lib/basic-contract/template/dispose-documents-dialog.tsx
new file mode 100644
index 00000000..1154c246
--- /dev/null
+++ b/lib/basic-contract/template/dispose-documents-dialog.tsx
@@ -0,0 +1,122 @@
+"use client"
+
+import * as React from "react"
+import { toast } from "sonner"
+import { Trash2, RotateCcw } from "lucide-react"
+
+import { Button } from "@/components/ui/button"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
+import { BasicContractTemplate } from "@/db/schema"
+import { disposeDocuments, restoreDocuments } from "../actions"
+
+interface DisposeDocumentsDialogProps {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ documents: BasicContractTemplate[]
+ showTrigger?: boolean
+ onSuccess?: () => void
+}
+
+export function DisposeDocumentsDialog({
+ open,
+ onOpenChange,
+ documents,
+ showTrigger = true,
+ onSuccess,
+}: DisposeDocumentsDialogProps) {
+ const [isLoading, setIsLoading] = React.useState(false)
+
+ const isDisposeAction = documents.some(doc => doc.status === 'ACTIVE')
+ const actionText = isDisposeAction ? '폐기' : '복구'
+ const actionIcon = isDisposeAction ? Trash2 : RotateCcw
+
+ const handleAction = async () => {
+ if (documents.length === 0) return
+
+ setIsLoading(true)
+ try {
+ const documentIds = documents.map(doc => doc.id)
+
+ if (isDisposeAction) {
+ await disposeDocuments(documentIds)
+ toast.success(`${documents.length}개의 문서가 폐기되었습니다.`)
+ } else {
+ await restoreDocuments(documentIds)
+ toast.success(`${documents.length}개의 문서가 복구되었습니다.`)
+ }
+
+ onSuccess?.()
+ onOpenChange(false)
+ } catch (error) {
+ console.error(`${actionText} 처리 오류:`, error)
+ toast.error(`${actionText} 처리 중 오류가 발생했습니다.`)
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ {showTrigger && (
+ <Button variant="outline" size="sm">
+ {React.createElement(actionIcon, { className: "mr-2 h-4 w-4" })}
+ {actionText}하기
+ </Button>
+ )}
+ <DialogContent className="sm:max-w-[425px]">
+ <DialogHeader>
+ <DialogTitle className="flex items-center gap-2">
+ {React.createElement(actionIcon, { className: "h-5 w-5" })}
+ 문서 {actionText}
+ </DialogTitle>
+ <DialogDescription>
+ 선택한 {documents.length}개의 문서를 {actionText}하시겠습니까?
+ {isDisposeAction
+ ? ' 폐기된 문서는 복구할 수 있습니다.'
+ : ' 복구된 문서는 다시 사용할 수 있습니다.'
+ }
+ </DialogDescription>
+ </DialogHeader>
+
+ <div className="py-4">
+ <div className="space-y-2">
+ {documents.map((doc) => (
+ <div key={doc.id} className="flex items-center p-2 bg-muted rounded">
+ <div>
+ <p className="font-medium">{doc.templateName}</p>
+ <p className="text-sm text-muted-foreground">
+ {doc.fileName} • v{doc.revision}
+ </p>
+ </div>
+ </div>
+ ))}
+ </div>
+ </div>
+
+ <DialogFooter>
+ <Button
+ variant="outline"
+ onClick={() => onOpenChange(false)}
+ disabled={isLoading}
+ >
+ 취소
+ </Button>
+ <Button
+ onClick={handleAction}
+ disabled={isLoading}
+ variant={isDisposeAction ? "destructive" : "default"}
+ >
+ {isLoading ? "처리 중..." : `${actionText}하기`}
+ </Button>
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ )
+}