diff options
Diffstat (limited to 'lib/parsers.ts')
| -rw-r--r-- | lib/parsers.ts | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/parsers.ts b/lib/parsers.ts new file mode 100644 index 00000000..20f3107b --- /dev/null +++ b/lib/parsers.ts @@ -0,0 +1,94 @@ +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 = <TData>( + originalRow?: Row<TData>["original"] +) => { + const validKeys = originalRow ? new Set(Object.keys(originalRow)) : null + + return createParser<ExtendedSortingState<TData>>({ + 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<TData> + } 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 = <T>(originalRow?: Row<T>["original"]) => { + const validKeys = originalRow ? new Set(Object.keys(originalRow)) : null + + return createParser<Filter<T>[]>({ + 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<T>[] + } 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 + ), + }) +} |
