61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
import type { HTMLAttributes } from "react";
|
|
|
|
import type { UseQueryResult } from "@tanstack/react-query";
|
|
import { type TableOptions, useReactTable } from "@tanstack/react-table";
|
|
|
|
import type { PageResponse } from "@/shared/model";
|
|
import { NoData } from "@/shared/ui/no-data";
|
|
import { DataTable, Skeleton } from "@common/components";
|
|
|
|
import { matchQueryStatus } from "./match-query-status";
|
|
|
|
interface DataTableOptions<T> {
|
|
variant?: "default" | "secondary" | "line";
|
|
className?: HTMLAttributes<HTMLTableElement>["className"];
|
|
caption?: string;
|
|
viewPagination?: boolean;
|
|
onRowClick?: (row: T) => void;
|
|
}
|
|
|
|
interface UseDataTableOptions<T> {
|
|
/** 페이징 응답(PageResponse) 또는 페이징 없는 목록(T[]) */
|
|
query: UseQueryResult<PageResponse<T> | T[]>;
|
|
tableOptions: Omit<TableOptions<T>, "data" | "rowCount">;
|
|
dataTableOptions?: DataTableOptions<T>;
|
|
}
|
|
|
|
const EMPTY_ROWS: never[] = [];
|
|
|
|
export function useDataTable<T>({ query, tableOptions, dataTableOptions }: UseDataTableOptions<T>) {
|
|
const { data } = query;
|
|
const rows = Array.isArray(data) ? data : (data?.content ?? EMPTY_ROWS);
|
|
const rowCount = Array.isArray(data) ? data.length : (data?.totalElements ?? 0);
|
|
|
|
const table = useReactTable({
|
|
...tableOptions,
|
|
data: rows,
|
|
rowCount,
|
|
});
|
|
|
|
return {
|
|
tableComponent: matchQueryStatus(query, {
|
|
Pending: (
|
|
<div className="flex flex-col gap-2">
|
|
<Skeleton className="h-[4rem]" />
|
|
<Skeleton className="h-[16rem]" />
|
|
</div>
|
|
),
|
|
Empty: <NoData />,
|
|
Error: (
|
|
<p className="py-6 text-center text-lg text-muted-foreground">
|
|
데이터를 불러오는 중 오류가 발생했습니다.
|
|
</p>
|
|
),
|
|
Success: () => <DataTable table={table} {...dataTableOptions} />,
|
|
}),
|
|
tableInstance: table,
|
|
};
|
|
}
|