summaryrefslogtreecommitdiff
path: root/lib/qna/table/qna-table-toolbar-actions.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-07-02 00:45:49 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-07-02 00:45:49 +0000
commit2acf5f8966a40c1c9a97680c8dc263ee3f1ad3d1 (patch)
treef406b5c86f563347c7fd088a85fd1a82284dc5ff /lib/qna/table/qna-table-toolbar-actions.tsx
parent6a9ca20deddcdcbe8495cf5a73ec7ea5f53f9b55 (diff)
(대표님/최겸) 20250702 변경사항 업데이트
Diffstat (limited to 'lib/qna/table/qna-table-toolbar-actions.tsx')
-rw-r--r--lib/qna/table/qna-table-toolbar-actions.tsx176
1 files changed, 176 insertions, 0 deletions
diff --git a/lib/qna/table/qna-table-toolbar-actions.tsx b/lib/qna/table/qna-table-toolbar-actions.tsx
new file mode 100644
index 00000000..d3e8623e
--- /dev/null
+++ b/lib/qna/table/qna-table-toolbar-actions.tsx
@@ -0,0 +1,176 @@
+"use client"
+
+import * as React from "react"
+import { type Table } from "@tanstack/react-table"
+import { Download, Plus, RefreshCw, FileSpreadsheet, FileText, Users } from "lucide-react"
+import { toast } from "sonner"
+
+import { Button } from "@/components/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
+
+import { QnaViewSelect } from "@/db/schema"
+import { exportQnaData } from "./qna-export-actions"
+
+interface QnaTableToolbarActionsProps {
+ table: Table<QnaViewSelect>
+ domain: string
+ onCreateClick: () => void
+}
+
+export function QnaTableToolbarActions({
+ table,
+ domain,
+ onCreateClick
+}: QnaTableToolbarActionsProps) {
+ const [isExporting, setIsExporting] = React.useState(false)
+ const [isRefreshing, setIsRefreshing] = React.useState(false)
+
+ // 선택된 행들
+ const selectedRows = table.getFilteredSelectedRowModel().rows
+ const selectedCount = selectedRows.length
+
+ // 새로고침
+ const handleRefresh = async () => {
+ setIsRefreshing(true)
+ try {
+ // 페이지 새로고침 또는 데이터 재요청
+ window.location.reload()
+ } catch (error) {
+ toast.error("새로고침 중 오류가 발생했습니다.")
+ } finally {
+ setIsRefreshing(false)
+ }
+ }
+
+ // 데이터 내보내기
+ const handleExport = async (format: "csv" | "excel") => {
+ setIsExporting(true)
+ try {
+ const selectedData = selectedCount > 0
+ ? selectedRows.map(row => row.original)
+ : table.getFilteredRowModel().rows.map(row => row.original)
+
+ const result = await exportQnaData({
+ format,
+ data: selectedData,
+ fields: [
+ "title",
+ "authorName",
+ "companyName",
+ "totalAnswers",
+ "totalComments",
+ "createdAt",
+ "lastActivityAt"
+ ]
+ })
+
+ if (result.success) {
+ toast.success(`${format.toUpperCase()} 파일이 다운로드되었습니다.`)
+ } else {
+ toast.error(result.error || "내보내기에 실패했습니다.")
+ }
+ } catch (error) {
+ toast.error("내보내기 중 오류가 발생했습니다.")
+ console.error("Export error:", error)
+ } finally {
+ setIsExporting(false)
+ }
+ }
+
+ return (
+ <div className="flex items-center gap-2">
+ {/* 선택된 항목 수 표시 */}
+ {selectedCount > 0 && (
+ <div className="flex items-center gap-2 text-sm text-muted-foreground">
+ <Users className="h-4 w-4" />
+ <span>{selectedCount}개 선택됨</span>
+ </div>
+ )}
+
+ {/* 새 질문 작성 버튼 */}
+ {domain === "partners" &&
+ <Tooltip>
+ <TooltipTrigger asChild>
+ <Button
+ onClick={onCreateClick}
+ size="sm"
+ className="h-8 gap-2"
+ >
+ <Plus className="h-4 w-4" />
+ 새 질문
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent>새로운 질문을 작성합니다</TooltipContent>
+ </Tooltip>
+}
+
+ {/* 내보내기 드롭다운 */}
+ <DropdownMenu>
+ <DropdownMenuTrigger asChild>
+ <Button
+ variant="outline"
+ size="sm"
+ className="h-8 gap-2"
+ disabled={isExporting}
+ >
+ <Download className="h-4 w-4" />
+ {isExporting ? "내보내는 중..." : "내보내기"}
+ </Button>
+ </DropdownMenuTrigger>
+ <DropdownMenuContent align="end" className="w-[180px]">
+ <DropdownMenuItem
+ onClick={() => handleExport("csv")}
+ disabled={isExporting}
+ >
+ <FileText className="mr-2 h-4 w-4" />
+ CSV 파일로 내보내기
+ </DropdownMenuItem>
+ <DropdownMenuItem
+ onClick={() => handleExport("excel")}
+ disabled={isExporting}
+ >
+ <FileSpreadsheet className="mr-2 h-4 w-4" />
+ Excel 파일로 내보내기
+ </DropdownMenuItem>
+ <DropdownMenuSeparator />
+ <DropdownMenuItem
+ onClick={() => {
+ const rowCount = selectedCount > 0 ? selectedCount : table.getFilteredRowModel().rows.length
+ toast.info(`${rowCount}개의 질문이 내보내집니다.`)
+ }}
+ disabled={isExporting}
+ className="text-xs text-muted-foreground"
+ >
+ {selectedCount > 0
+ ? `선택된 ${selectedCount}개 항목`
+ : `전체 ${table.getFilteredRowModel().rows.length}개 항목`
+ }
+ </DropdownMenuItem>
+ </DropdownMenuContent>
+ </DropdownMenu>
+
+ {/* 새로고침 버튼 */}
+ <Tooltip>
+ <TooltipTrigger asChild>
+ <Button
+ variant="outline"
+ size="sm"
+ onClick={handleRefresh}
+ disabled={isRefreshing}
+ className="h-8 w-8 p-0"
+ >
+ <RefreshCw className={`h-4 w-4 ${isRefreshing ? "animate-spin" : ""}`} />
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent>목록 새로고침</TooltipContent>
+ </Tooltip>
+ </div>
+ )
+} \ No newline at end of file