"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 { getUserCustomSettings, saveUserCustomSetting, deleteUserCustomSetting, } from "@/actions/user-custom-data"; import { toast } from "sonner"; interface ClientTableSaveViewProps { table: Table; tableKey: string; } export function ClientTableSaveView({ table, tableKey, }: ClientTableSaveViewProps) { const { data: session } = useSession(); const [savedViews, setSavedViews] = React.useState<{ id: string; customSettingName: string; customSetting: Record }[]>([]); const [isSaveDialogOpen, setIsSaveDialogOpen] = React.useState(false); const [newViewName, setNewViewName] = 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 getUserCustomSettings(tableKey, userId); if (res.success && res.data) { // @ts-ignore - data from DB might need casting setSavedViews(res.data); } }, [session, tableKey]); React.useEffect(() => { if (session) { fetchSettings(); } }, [fetchSettings, session]); const handleSaveView = async () => { const userIdVal = session?.user?.id; if (!newViewName.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 saveUserCustomSetting(userId, tableKey, newViewName, settingToSave); setIsLoading(false); if (res.success) { toast.success("View saved successfully"); setIsSaveDialogOpen(false); setNewViewName(""); fetchSettings(); } else { toast.error("Failed to save view"); } }; const handleLoadView = (setting: { customSetting: Record | unknown; customSettingName: string }) => { const s = setting.customSetting 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(`View "${setting.customSettingName}" loaded`); }; const handleDeleteView = async (e: React.MouseEvent, id: string) => { e.stopPropagation(); if (!confirm("Are you sure you want to delete this view?")) return; const res = await deleteUserCustomSetting(id); if (res.success) { toast.success("View deleted"); fetchSettings(); } else { toast.error("Failed to delete view"); } }; if (!session) return null; return ( <> Saved Views {savedViews.length === 0 ? (
No saved views
) : ( savedViews.map((view) => ( handleLoadView(view)} className="flex justify-between cursor-pointer"> {view.customSettingName} )) )} setIsSaveDialogOpen(true)} className="cursor-pointer"> Save Current View
Save View Save the current table configuration as a preset.
setNewViewName(e.target.value)} />
); }