diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-02 00:45:49 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-02 00:45:49 +0000 |
| commit | 2acf5f8966a40c1c9a97680c8dc263ee3f1ad3d1 (patch) | |
| tree | f406b5c86f563347c7fd088a85fd1a82284dc5ff /lib/qna/table/qna-table-toolbar-actions.tsx | |
| parent | 6a9ca20deddcdcbe8495cf5a73ec7ea5f53f9b55 (diff) | |
(대표님/최겸) 20250702 변경사항 업데이트
Diffstat (limited to 'lib/qna/table/qna-table-toolbar-actions.tsx')
| -rw-r--r-- | lib/qna/table/qna-table-toolbar-actions.tsx | 176 |
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 |
