From 9da494b0e3bbe7b513521d0915510fe9ee376b8b Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 21 Jul 2025 07:19:52 +0000
Subject: (대표님, 최겸) 작업사항 - 이메일 템플릿, 메일링, 기술영업 요구사항
 반영
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../table/template-table-toolbar-actions.tsx       | 115 +++++++++++++++++++++
 1 file changed, 115 insertions(+)
 create mode 100644 lib/email-template/table/template-table-toolbar-actions.tsx

(limited to 'lib/email-template/table/template-table-toolbar-actions.tsx')

diff --git a/lib/email-template/table/template-table-toolbar-actions.tsx b/lib/email-template/table/template-table-toolbar-actions.tsx
new file mode 100644
index 00000000..a7e107c6
--- /dev/null
+++ b/lib/email-template/table/template-table-toolbar-actions.tsx
@@ -0,0 +1,115 @@
+"use client"
+
+import * as React from "react"
+import { type Table } from "@tanstack/react-table"
+import { Download, Plus, Trash } from "lucide-react"
+
+import { Button } from "@/components/ui/button"
+import { type TemplateListView } from "@/db/schema/template-views"
+import { DeleteTemplateDialog } from "./delete-template-dialog"
+import { toast } from "sonner"
+
+interface TemplateTableToolbarActionsProps {
+  table: Table<TemplateListView>
+  onCreateTemplate: () => void
+}
+
+export function TemplateTableToolbarActions({
+  table,
+  onCreateTemplate,
+}: TemplateTableToolbarActionsProps) {
+  const [showDeleteDialog, setShowDeleteDialog] = React.useState(false)
+
+  const selectedRows = table.getFilteredSelectedRowModel().rows
+  const selectedTemplates = selectedRows.map(row => row.original)
+
+  // CSV 내보내기 함수
+  const exportToCsv = React.useCallback(() => {
+    const headers = ['이름', 'Slug', '카테고리', '변수 개수', '버전', '생성일', '수정일']
+    const csvData = [
+      headers,
+      ...table.getFilteredRowModel().rows.map(row => {
+        const template = row.original
+        return [
+          template.name,
+          template.slug,
+          template.categoryDisplayName || '미분류',
+          template.variableCount.toString(),
+          template.version.toString(),
+          new Date(template.createdAt).toLocaleDateString('ko-KR'),
+          new Date(template.updatedAt).toLocaleDateString('ko-KR'),
+        ]
+      })
+    ]
+
+    const csvContent = csvData.map(row => 
+      row.map(field => `"${field}"`).join(',')
+    ).join('\n')
+
+    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
+    const link = document.createElement('a')
+    
+    if (link.download !== undefined) {
+      const url = URL.createObjectURL(blob)
+      link.setAttribute('href', url)
+      link.setAttribute('download', `templates_${new Date().toISOString().split('T')[0]}.csv`)
+      link.style.visibility = 'hidden'
+      document.body.appendChild(link)
+      link.click()
+      document.body.removeChild(link)
+    }
+
+    toast.success('템플릿 목록이 CSV로 내보내졌습니다.')
+  }, [table])
+
+  return (
+    <div className="flex items-center gap-2">
+      {/* 새 템플릿 생성 버튼 */}
+      <Button 
+        variant="default" 
+        size="sm"
+        onClick={onCreateTemplate}
+      >
+        <Plus className="mr-2 size-4" aria-hidden="true" />
+        새 템플릿
+      </Button>
+
+      {/* CSV 내보내기 버튼 */}
+      <Button 
+        variant="outline" 
+        size="sm"
+        onClick={exportToCsv}
+      >
+        <Download className="mr-2 size-4" aria-hidden="true" />
+        내보내기
+      </Button>
+
+      {/* 선택된 항목 일괄 삭제 버튼 */}
+      {selectedTemplates.length > 0 && (
+        <>
+          <Button
+            variant="outline"
+            size="sm"
+            onClick={() => setShowDeleteDialog(true)}
+            className="text-destructive hover:text-destructive"
+          >
+            <Trash className="mr-2 size-4" aria-hidden="true" />
+            삭제 ({selectedTemplates.length})
+          </Button>
+
+          {/* 일괄 삭제 Dialog */}
+          <DeleteTemplateDialog
+            open={showDeleteDialog}
+            onOpenChange={setShowDeleteDialog}
+            templates={selectedTemplates}
+            showTrigger={false}
+            onSuccess={() => {
+              table.toggleAllRowsSelected(false)
+              setShowDeleteDialog(false)
+            }}
+          />
+        </>
+      )}
+    </div>
+  )
+}
\ No newline at end of file
-- 
cgit v1.2.3

