- Implemented TemplateCheckpointEditDialog for creating and editing inspection checkpoints. - Added VendorActions component for managing vendor actions including edit, activate/deactivate, and delete. - Created VendorContext for managing vendor state across components. - Developed VendorGeneralInfo component to display detailed vendor information. - Introduced AedSymbol and Money components for consistent currency representation. - Added PromptDialog for user input prompts throughout the application. - Implemented RelationLink component for unified related-data display in CRUD tables. - Created InspectionTemplatesClient for API interactions related to inspection templates.
120 lines
3.8 KiB
TypeScript
120 lines
3.8 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { useQueryStates } from "nuqs"
|
|
import { useQuery, useQueryClient, type UseQueryOptions } from "@tanstack/react-query"
|
|
import type { DataViewChangeEvent, DataViewPaginationState, DataViewSorting } from "./types"
|
|
import { dataTableSearchParams } from "./search-params"
|
|
import { DEFAULT_PER_PAGE, type CrudListResponse } from "@garage/api"
|
|
|
|
type DataTableClient = {
|
|
list(query?: any): Promise<any>
|
|
}
|
|
|
|
type DataTableParams = {
|
|
page: number
|
|
per_page: number
|
|
sort_by: string | null
|
|
sort_order: "asc" | "desc" | null
|
|
}
|
|
|
|
type UseDataTableQueryOptions<C extends DataTableClient> = {
|
|
queryKey: string[]
|
|
client: C
|
|
queryOptions?: Omit<UseQueryOptions<CrudListResponse<C>>, "queryKey" | "queryFn">
|
|
extraParams?: Record<string, unknown>
|
|
/** When true, pagination/sorting state lives in component state instead of URL params. Used for tables inside dialogs so they don't share state with the parent page. */
|
|
localState?: boolean
|
|
}
|
|
|
|
export function useDataTableQuery<C extends DataTableClient>({
|
|
queryKey,
|
|
client,
|
|
queryOptions,
|
|
extraParams,
|
|
localState = false,
|
|
}: UseDataTableQueryOptions<C>) {
|
|
const [urlParams, setUrlParams] = useQueryStates(dataTableSearchParams)
|
|
const [localParams, setLocalParams] = useState<DataTableParams>({
|
|
page: 1,
|
|
per_page: DEFAULT_PER_PAGE,
|
|
sort_by: null,
|
|
sort_order: null,
|
|
})
|
|
|
|
const params: DataTableParams = localState ? localParams : urlParams
|
|
const setParams = (next: Partial<DataTableParams>) => {
|
|
if (localState) {
|
|
setLocalParams((prev) => ({ ...prev, ...next }))
|
|
} else {
|
|
setUrlParams(next)
|
|
}
|
|
}
|
|
|
|
const _queryKey = [...queryKey, params, ...(extraParams ? [extraParams] : [])]
|
|
const query = useQuery<CrudListResponse<C>>({
|
|
queryKey: _queryKey,
|
|
queryFn: () => {
|
|
const apiParams: Record<string, unknown> = {
|
|
page: params.page,
|
|
per_page: params.per_page,
|
|
...extraParams,
|
|
}
|
|
if (params.sort_by) apiParams.sort_by = params.sort_by
|
|
if (params.sort_order) apiParams.sort_order = params.sort_order
|
|
|
|
return client.list(apiParams) as Promise<CrudListResponse<C>>
|
|
},
|
|
...queryOptions,
|
|
})
|
|
|
|
const pagination: DataViewPaginationState = {
|
|
page: params.page,
|
|
pageSize: params.per_page,
|
|
pageCount: (query.data as any)?.meta?.last_page ?? 1,
|
|
total: (query.data as any)?.meta?.total ?? 0,
|
|
}
|
|
|
|
const sorting: DataViewSorting = params.sort_by
|
|
? [{ id: params.sort_by, desc: params.sort_order === "desc" }]
|
|
: []
|
|
|
|
const handleChange = (event: DataViewChangeEvent) => {
|
|
switch (event.type) {
|
|
case "pagination":
|
|
setParams({
|
|
page: event.pagination.page,
|
|
per_page: event.pagination.pageSize,
|
|
})
|
|
break
|
|
case "sorting": {
|
|
const sort = event.sorting[0]
|
|
setParams({
|
|
sort_by: sort?.id ?? null,
|
|
sort_order: sort ? (sort.desc ? "desc" : "asc") : null,
|
|
page: 1,
|
|
})
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
const queryClient = useQueryClient();
|
|
const invalidateQuery = () => {
|
|
// Prefix-match on the base route key so all paginated/sorted variants of
|
|
// the list refetch — exact-matching the params object is flaky because
|
|
// nuqs returns a fresh reference per render.
|
|
queryClient.invalidateQueries({ queryKey, refetchType: "active" })
|
|
}
|
|
|
|
return {
|
|
...query,
|
|
pagination,
|
|
sorting,
|
|
params,
|
|
setParams,
|
|
handleChange,
|
|
invalidateQuery,
|
|
}
|
|
}
|