From ffb8e2e99e1d0c105b1c545ff7ab4d3149ec6c48 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Mon, 1 Dec 2025 15:22:38 +0900 Subject: (김준회) 서버측 where, order by 절 지원을 위한 v2 임시작업 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/client-table-v2/client-table-preset.tsx | 185 +++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 components/client-table-v2/client-table-preset.tsx (limited to 'components/client-table-v2/client-table-preset.tsx') diff --git a/components/client-table-v2/client-table-preset.tsx b/components/client-table-v2/client-table-preset.tsx new file mode 100644 index 00000000..64930e7a --- /dev/null +++ b/components/client-table-v2/client-table-preset.tsx @@ -0,0 +1,185 @@ +"use client"; + +import * as React from "react"; +import { Table } from "@tanstack/react-table"; +import { useSession } from "next-auth/react"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Bookmark, Save, Trash2 } from "lucide-react"; +import { + getPresets, + savePreset, + deletePreset, +} from "./preset-actions"; +import { Preset } from "./preset-types"; +import { toast } from "sonner"; + +interface ClientTablePresetProps { + table: Table; + tableKey: string; +} + +export function ClientTablePreset({ + table, + tableKey, +}: ClientTablePresetProps) { + const { data: session } = useSession(); + const [savedPresets, setSavedPresets] = React.useState([]); + const [isPresetDialogOpen, setIsPresetDialogOpen] = React.useState(false); + const [newPresetName, setNewPresetName] = React.useState(""); + const [isLoading, setIsLoading] = React.useState(false); + + const fetchSettings = React.useCallback(async () => { + const userIdVal = session?.user?.id; + if (!userIdVal) return; + + const userId = Number(userIdVal); + if (isNaN(userId)) return; + + const res = await getPresets(tableKey, userId); + if (res.success && res.data) { + setSavedPresets(res.data); + } + }, [session, tableKey]); + + React.useEffect(() => { + if (session) { + fetchSettings(); + } + }, [fetchSettings, session]); + + const handleSavePreset = async () => { + const userIdVal = session?.user?.id; + if (!newPresetName.trim() || !userIdVal) return; + const userId = Number(userIdVal); + if (isNaN(userId)) return; + + setIsLoading(true); + const state = table.getState(); + const settingToSave = { + sorting: state.sorting, + columnFilters: state.columnFilters, + globalFilter: state.globalFilter, + columnVisibility: state.columnVisibility, + columnPinning: state.columnPinning, + columnOrder: state.columnOrder, + grouping: state.grouping, + pagination: { pageSize: state.pagination.pageSize }, + }; + + const res = await savePreset(userId, tableKey, newPresetName, settingToSave); + setIsLoading(false); + + if (res.success) { + toast.success("Preset saved successfully"); + setIsPresetDialogOpen(false); + setNewPresetName(""); + fetchSettings(); + } else { + toast.error("Failed to save preset"); + } + }; + + const handleLoadPreset = (preset: Preset) => { + const s = preset.setting as Record; + if (!s) return; + + if (s.sorting) table.setSorting(s.sorting); + if (s.columnFilters) table.setColumnFilters(s.columnFilters); + if (s.globalFilter !== undefined) table.setGlobalFilter(s.globalFilter); + if (s.columnVisibility) table.setColumnVisibility(s.columnVisibility); + if (s.columnPinning) table.setColumnPinning(s.columnPinning); + if (s.columnOrder) table.setColumnOrder(s.columnOrder); + if (s.grouping) table.setGrouping(s.grouping); + if (s.pagination?.pageSize) table.setPageSize(s.pagination.pageSize); + + toast.success(`Preset "${preset.name}" loaded`); + }; + + const handleDeletePreset = async (e: React.MouseEvent, id: string) => { + e.stopPropagation(); + if (!confirm("Are you sure you want to delete this preset?")) return; + + const res = await deletePreset(id); + if (res.success) { + toast.success("Preset deleted"); + fetchSettings(); + } else { + toast.error("Failed to delete preset"); + } + }; + + if (!session) return null; + + return ( + <> + + + + + + Saved Presets + + {savedPresets.length === 0 ? ( +
No saved presets
+ ) : ( + savedPresets.map((preset) => ( + handleLoadPreset(preset)} className="flex justify-between cursor-pointer"> + {preset.name} + + + )) + )} + + setIsPresetDialogOpen(true)} className="cursor-pointer"> + + Save Current Preset + +
+
+ + + + + Save Preset + + Save the current table configuration as a preset. + + +
+ setNewPresetName(e.target.value)} + /> +
+ + + + +
+
+ + ); +} -- cgit v1.2.3