import { useLocal } from "@/utils/use-local"; import { FC, useEffect, useRef } from "react"; import DataGrid, { ColumnOrColumnGroup, DataGridHandle, Row, SortColumn, } from "react-data-grid"; import "react-data-grid/lib/styles.css"; import { Skeleton } from "../ui/skeleton"; type OnRowClick = { row: any; rows: any[]; idx: any; event: React.MouseEvent; }; type RowSelected = { row: any; rows: any[]; idx: any; }; export const Table: FC<{ columns: () => Promise[]>; on_load: (opt: { reload: () => Promise }) => Promise; child: any; PassProp: any; row_click: (arg: OnRowClick) => void; selected: (arg: RowSelected) => boolean; }> = ({ columns, on_load, child, PassProp, row_click, selected }) => { const local = useLocal({ loading: false, data: undefined as unknown as any[], columns: [] as ColumnOrColumnGroup[], }); useEffect(() => { local.loading = true; columns().then((col) => { local.columns = col.map((e) => ({ ...e, resizable: true, renderCell(props) { return ( {child} ); }, })); if (!!local.data) { local.loading = false; } local.render(); }); }, [columns]); useEffect(() => { local.loading = true; const arg = { reload: async () => { local.loading = true; local.render(); const data = await on_load(arg); local.data = data; local.loading = false; local.render(); }, }; on_load(arg).then((data) => { local.data = data; local.loading = false; local.render(); }); }, [on_load]); return ( ); }; const TableInternal: FC<{ columns: ColumnOrColumnGroup[]; data?: any[]; render: () => void; row_click: (arg: OnRowClick) => void; selected: (arg: RowSelected) => boolean; }> = ({ columns, data, render, row_click, selected }) => { const local = useLocal({ width: 0, height: 0, rob: new ResizeObserver(([e]) => { local.height = e.contentRect.height; local.width = e.contentRect.width; local.render(); }), el: null as any, sort: [] as SortColumn[], scrolled: false, }); const rdg = useRef(null); useEffect(() => { return () => { local.rob.disconnect(); }; }, []); const sort = local.sort; // let sorted = data; // if (sort.length > 0 && data) { // sorted = data.sort((a, b) => { // const va = a[sort[0].columnKey]; // const vb = b[sort[0].columnKey]; // if (typeof va === "string" && typeof vb === "string") { // if (sort[0].direction === "ASC") { // return va.localeCompare(vb); // } else { // return vb.localeCompare(va); // } // } // return 0; // }); // } let selected_idx = -1; if (data) { for (let i = 0; i < data.length; i++) { const row = data[i]; if ( typeof selected === "function" ? selected({ idx: i, row: row, rows: data, }) : false ) { selected_idx = i; break; } } } useEffect(() => { rdg.current!.scrollToCell({ rowIdx: selected_idx, idx: 0 }); }, [selected_idx]); return (
{ if (!local.el && el) { local.el = el; local.rob.observe(el); } }} > { local.sort = []; if (col) { if (sort.length > 0) { const first = sort[0]; if (first && first.columnKey === col.columnKey) { local.sort.push({ columnKey: col.columnKey, direction: first.direction === "ASC" ? "DESC" : "ASC", }); render(); return; } } local.sort.push(col); } render(); }} className="fill-grid rdg-light" renderers={ typeof data === "undefined" ? undefined : { renderRow(key, props) { const is_selected = selected_idx === props.rowIdx; return ( { if (typeof row_click === "function") { row_click({ event: ev, idx: props.rowIdx, row: props.row, rows: data, }); } }} isRowSelected={is_selected} className={cx( props.className, is_selected && "row-selected" )} /> ); }, noRowsFallback: (
No Data
), } } style={{ height: typeof data === "undefined" ? 50 : local.height, width: local.width, }} rows={data || []} /> {typeof data === "undefined" && (
)}
); };