import type { ExtendedSortingState, Filter } from "@/types/table" import { type Row } from "@tanstack/react-table" import { createParser } from "nuqs/server" import { z } from "zod" import { dataTableConfig } from "@/config/data-table" export const sortingItemSchema = z.object({ id: z.string(), desc: z.boolean(), }) /** * Creates a parser for TanStack Table sorting state. * @param originalRow The original row data to validate sorting keys against. * @returns A parser for TanStack Table sorting state. */ export const getSortingStateParser = ( originalRow?: Row["original"] ) => { const validKeys = originalRow ? new Set(Object.keys(originalRow)) : null return createParser>({ parse: (value) => { try { const parsed = JSON.parse(value) const result = z.array(sortingItemSchema).safeParse(parsed) if (!result.success) return null if (validKeys && result.data.some((item) => !validKeys.has(item.id))) { return null } return result.data as ExtendedSortingState } catch { return null } }, serialize: (value) => JSON.stringify(value), eq: (a, b) => a.length === b.length && a.every( (item, index) => item.id === b[index]?.id && item.desc === b[index]?.desc ), }) } export const filterSchema = z.object({ id: z.string(), value: z.union([z.string(), z.array(z.string())]), type: z.enum(dataTableConfig.columnTypes), operator: z.enum(dataTableConfig.globalOperators), rowId: z.string(), }) /** * Create a parser for data table filters. * @param originalRow The original row data to create the parser for. * @returns A parser for data table filters state. */ export const getFiltersStateParser = (originalRow?: Row["original"]) => { const validKeys = originalRow ? new Set(Object.keys(originalRow)) : null return createParser[]>({ parse: (value) => { try { const parsed = JSON.parse(value) const result = z.array(filterSchema).safeParse(parsed) if (!result.success) return null if (validKeys && result.data.some((item) => !validKeys.has(item.id))) { return null } return result.data as Filter[] } catch { return null } }, serialize: (value) => JSON.stringify(value), eq: (a, b) => a.length === b.length && a.every( (filter, index) => filter.id === b[index]?.id && filter.value === b[index]?.value && filter.type === b[index]?.type && filter.operator === b[index]?.operator ), }) }