diff options
Diffstat (limited to 'lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx')
| -rw-r--r-- | lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx b/lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx new file mode 100644 index 00000000..3628f87e --- /dev/null +++ b/lib/tech-vendor-possible-items/table/possible-items-table-toolbar-actions.tsx @@ -0,0 +1,201 @@ +"use client";
+
+import * as React from "react";
+import { type Table } from "@tanstack/react-table";
+import { Download, Upload, FileSpreadsheet, Trash2 } from "lucide-react";
+
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { useToast } from "@/hooks/use-toast";
+import { deleteTechVendorPossibleItems } from "@/lib/tech-vendor-possible-items/service";
+// Excel 함수들을 동적 import로만 사용하기 위해 타입만 import
+type TechVendorPossibleItemsData = {
+ id: number;
+ vendorId: number;
+ vendorCode: string | null;
+ vendorName: string;
+ techVendorType: string;
+ itemCode: string;
+ createdAt: Date;
+ updatedAt: Date;
+};
+
+interface PossibleItemsTableToolbarActionsProps {
+ table: Table<TechVendorPossibleItemsData>;
+}
+
+export function PossibleItemsTableToolbarActions({
+ table,
+}: PossibleItemsTableToolbarActionsProps) {
+ const { toast } = useToast();
+ const [isPending, startTransition] = React.useTransition();
+
+ const selectedRows = table.getFilteredSelectedRowModel().rows;
+ const hasSelection = selectedRows.length > 0;
+
+ const handleDelete = () => {
+ if (!hasSelection) return;
+
+ startTransition(async () => {
+ const selectedIds = selectedRows.map((row) => row.original.id);
+
+ try {
+ const result = await deleteTechVendorPossibleItems(selectedIds);
+
+ if (result.success) {
+ toast({
+ title: "성공",
+ description: `${selectedIds.length}개의 아이템이 삭제되었습니다.`,
+ });
+ table.toggleAllRowsSelected(false);
+ // 페이지 새로고침이나 데이터 다시 로드 필요
+ window.location.reload();
+ } else {
+ toast({
+ title: "오류",
+ description: result.error || "삭제 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ }
+ } catch (error) {
+ console.error("Delete error:", error);
+ toast({
+ title: "오류",
+ description: "삭제 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ }
+ });
+ };
+
+ const handleExport = async () => {
+ try {
+ const { exportTechVendorPossibleItemsToExcel } = await import("./excel-export");
+ const result = await exportTechVendorPossibleItemsToExcel(table.getFilteredRowModel().rows.map(row => row.original));
+
+ if (result.success) {
+ toast({
+ title: "성공",
+ description: "Excel 파일이 다운로드되었습니다.",
+ });
+ } else {
+ toast({
+ title: "오류",
+ description: result.error || "내보내기 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ }
+ } catch (error) {
+ console.error("Export error:", error);
+ toast({
+ title: "오류",
+ description: "내보내기 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ }
+ };
+
+ const handleImport = async (event: React.ChangeEvent<HTMLInputElement>) => {
+ const file = event.target.files?.[0];
+ if (!file) return;
+
+ try {
+ const { importTechVendorPossibleItemsFromExcel } = await import("./excel-import");
+ const result = await importTechVendorPossibleItemsFromExcel(file);
+
+ if (result.success) {
+ toast({
+ title: "성공",
+ description: `${result.successCount}개의 아이템이 가져와졌습니다.`,
+ });
+ // 페이지 새로고침이나 데이터 다시 로드 필요
+ window.location.reload();
+ } else {
+ toast({
+ title: "가져오기 완료",
+ description: `${result.successCount}개 성공, ${result.failedRows.length}개 실패`,
+ variant: result.successCount > 0 ? "default" : "destructive",
+ });
+ }
+ } catch (error) {
+ console.error("Import error:", error);
+ toast({
+ title: "오류",
+ description: "가져오기 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ }
+
+ // Reset input
+ event.target.value = "";
+ };
+
+ const handleDownloadTemplate = async () => {
+ try {
+ const { exportTechVendorPossibleItemsTemplate } = await import("./excel-template");
+ const result = await exportTechVendorPossibleItemsTemplate();
+ if (result.success) {
+ toast({
+ title: "성공",
+ description: "템플릿 파일이 다운로드되었습니다.",
+ });
+ } else {
+ toast({
+ title: "오류",
+ description: result.error || "템플릿 다운로드 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ }
+ } catch (error) {
+ console.error("Template download error:", error);
+ toast({
+ title: "오류",
+ description: "템플릿 다운로드 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ }
+ };
+
+ return (
+ <div className="flex items-center gap-2">
+ {hasSelection && (
+ <Button
+ variant="destructive"
+ size="sm"
+ onClick={handleDelete}
+ disabled={isPending}
+ >
+ <Trash2 className="mr-2 h-4 w-4" />
+ 삭제 ({selectedRows.length})
+ </Button>
+ )}
+
+ <Button variant="outline" size="sm" onClick={handleExport}>
+ <Download className="mr-2 h-4 w-4" />
+ Export
+ </Button>
+
+ <Input
+ id="import-file"
+ type="file"
+ accept=".xlsx,.xls"
+ onChange={handleImport}
+ className="hidden"
+ />
+
+ <Button
+ variant="outline"
+ size="sm"
+ onClick={() => document.getElementById("import-file")?.click()}
+ >
+ <Upload className="mr-2 h-4 w-4" />
+ Import
+ </Button>
+
+ <Button variant="outline" size="sm" onClick={handleDownloadTemplate}>
+ <FileSpreadsheet className="mr-2 h-4 w-4" />
+ Download Template
+ </Button>
+ </div>
+ );
+}
\ No newline at end of file |
