"use client" import React from "react" import { DataTable, type ActionsColumnOptions, type DataViewProps } from "@/shared/data-view/table-view" import { useResourcePage, type UseResourcePageOptions, type ResourceItem, type ResourcePageClient } from "./use-resource-page" import type { ColumnDef } from "@tanstack/react-table" type LooseColumnDef = ColumnDef | (Omit, "accessorKey"> & { accessorKey: string }) export type CrudResourceColumnHelpers = { actionsColumn: (options?: Partial>>) => ColumnDef, unknown> openEdit: (row: ResourceItem) => void deleteItem: (id: string) => Promise } export type CrudResourceContext = { selectedItem: ResourceItem | null isDialogOpen: boolean dialogResourceId: string | null isLoading: boolean data: ResourceItem[] openCreate: () => void openEdit: (row: ResourceItem) => void closeDialog: () => void deleteItem: (id: string) => Promise invalidateQuery: () => void } type ReactNodeOrRender = | React.ReactNode | ((context: CrudResourceContext) => React.ReactNode) type ManagedTableProps = "columns" | "data" | "pagination" | "sorting" | "onChange" | "isLoading" export type CrudResourceProps = UseResourcePageOptions & { columns: LooseColumnDef>[] | ((helpers: CrudResourceColumnHelpers) => LooseColumnDef>[]) onRowClick?: (row: ResourceItem) => void tableHeader?: ReactNodeOrRender tableProps?: Omit>>, ManagedTableProps> render?: (table: React.ReactElement, context: CrudResourceContext) => React.ReactElement } export function CrudResource({ columns: columnsProp, routeKey, getClient, queryOptions, paramKey, extraParams, onRowClick, tableHeader, tableProps, render, }: CrudResourceProps) { type TItem = ResourceItem const page = useResourcePage({ routeKey, getClient, queryOptions, paramKey, extraParams }) const columns = typeof columnsProp === "function" ? columnsProp({ actionsColumn: page.actionsColumn, openEdit: page.openEdit, deleteItem: page.deleteItem, }) : columnsProp type ListResponse = { data?: TItem[] } const responseData = page.data as ListResponse | undefined const items = (responseData?.data ?? []) as TItem[] const context: CrudResourceContext = { selectedItem: page.selectedItem, isDialogOpen: page.isDialogOpen, dialogResourceId: page.dialogResourceId, isLoading: page.isLoading, data: items, openCreate: page.openCreate, openEdit: page.openEdit, closeDialog: page.closeDialog, deleteItem: page.deleteItem, invalidateQuery: () => page.invalidateQuery(), } const table = ( <> {tableHeader && (typeof tableHeader === "function" ? tableHeader(context) : tableHeader)} []} data={items} pagination={page.pagination} sorting={page.sorting} onChange={page.handleChange} isLoading={page.isLoading} onRowClick={onRowClick ?? tableProps?.onRowClick} /> ) if (render) return render(table, context) return table }