import clsx from "clsx"; //import { PaginationDto } from "~/application/dtos/data/PaginationDto"; //import { RowHeaderDisplayDto } from "~/application/dtos/data/RowHeaderDisplayDto"; //import RowDisplayValueHelper from "~/utils/helpers/RowDisplayValueHelper"; import {ButtonTertiary} from "../buttons/ButtonTertiary"; import TablePagination from "./TablePagination"; import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from "react"; //import { RowHeaderActionDto } from "~/application/dtos/data/RowHeaderActionDto"; import DownArrow from "../icons/DownArrow"; import UpArrow from "../icons/UpArrow"; import { useApp } from "../../../hooks"; import { useRouter, useSearchParams } from "next/navigation"; import RowDisplayValueHelper from "../../../utils/helpers/RowDisplayValueHelper"; interface Props { //@ts-ignore headers: RowHeaderDisplayDto[]; items: T[]; //@ts-ignore actions?: RowHeaderActionDto[]; //@ts-ignore pagination?: PaginationDto; onClickRoute?: (idx: number, item: T) => string | undefined; selectedRows?: T[]; onSelected?: (item: T[]) => void; className?: (idx: number, item: T) => string; padding?: string; noRecords?: ReactNode; emptyState?: { title: string; description: string; icon?: ReactNode }; } export default function TableSimple(props: Props) { const [showChild, setShowChild] = useState(false); // Wait until after client-side hydration to show useEffect(() => { setShowChild(true); }, []); if (!showChild) { // You can show some kind of placeholder UI here return null; } return ; } function Table({ headers, items, actions = [], pagination, onClickRoute, selectedRows, onSelected, className, padding = "px-2 py-2", noRecords, emptyState, }: Props) { const { t } = useApp(); const navigate = useRouter(); const [searchParams, setSearchParams] = useSearchParams(); const [sortBy, setSortBy] = useState<{ by: string; order: "asc" | "desc" }[]>(); useEffect(() => { let sort: string = searchParams["sort"] as any; const sortArray = sort?.split(",") ?? []; const sortObject = sortArray.map((s) => { let order: "asc" | "desc" = "asc"; if (s.startsWith("-")) { order = "desc"; } return { by: s.replace("-", ""), order }; }); setSortBy(sortObject); }, [searchParams]); // const [selectedRows, setSelectedRows] = useState([]); // useEffect(() => { // if (onSelected) { // onSelected(selectedRows); // } // }, [selectedRows]); function toggleSelected(_: number, item: T) { if (!selectedRows || !onSelected) { return; } if (selectedRows.includes(item)) { onSelected(selectedRows.filter((i) => i !== item)); } else { onSelected([...selectedRows, item]); } } const checkbox = useRef(null); const [checked, setChecked] = useState(false); const [indeterminate, setIndeterminate] = useState(false); useLayoutEffect(() => { if (!selectedRows || !onSelected) { return; } const isIndeterminate = selectedRows.length > 0 && selectedRows.length < items.length; setChecked(selectedRows.length === items.length && items.length > 0); setIndeterminate(isIndeterminate); // @ts-ignore checkbox.current.indeterminate = isIndeterminate; // eslint-disable-next-line react-hooks/exhaustive-deps }, [onSelected, selectedRows]); function toggleAll() { if (!selectedRows || !onSelected) { return; } onSelected(checked || indeterminate ? [] : items); setChecked(!checked && !indeterminate); setIndeterminate(false); } //@ts-ignore function onHeaderClick(header: RowHeaderDisplayDto) { if (!header.sortBy) { return; } let currentSort = sortBy?.find((s) => s.by === header.sortBy); let newSort = header.sortBy; if (currentSort?.order === "asc") { newSort = `-${header.sortBy}`; } /* searchParams.set("sort", newSort); setSearchParams(searchParams); */ } //@ts-ignore function getSortDirection(header: RowHeaderDisplayDto) { if (!header.sortBy) { return; } let currentSort = sortBy?.find((s) => s.by === header.sortBy); if (!currentSort) { return; } return currentSort.order; } return (
{actions.filter((f) => f.firstColumn).length > 0 && } {onSelected && ( )} {headers.map((header, idxHeader) => { return ( ); })} {actions.filter((f) => !f.firstColumn).length > 0 && } {items.length === 0 ? ( ) : ( items.map((item, idxRow) => { const href = onClickRoute?.(idxRow, item); return ( { if (e.ctrlKey || e.metaKey) { window.open(href, "_blank"); } else { navigate.push(href); } } : undefined } className={clsx("group text-gray-700", href && "cursor-pointer hover:bg-gray-100")} > f.firstColumn)} className={className} item={item} idxRow={idxRow} /> {onSelected && ( )} {headers.map((header, idxHeader) => { return ( ); })} !f.firstColumn)} className={className} item={item} idxRow={idxRow} /> ); }) )} {/* {[...Array(pageSize - items.length)].map((_, i) => ( ))} */}
e.stopPropagation()} /> onHeaderClick(header)} className={clsx( idxHeader === 0 && actions.filter((f) => f.firstColumn).length === 0 && "pl-3", "whitespace-nowrap px-2 py-2 tracking-wider", header.breakpoint === "sm" && "hidden sm:table-cell", header.breakpoint === "md" && "mg:table-cell hidden", header.breakpoint === "lg" && "hidden lg:table-cell", header.breakpoint === "xl" && "hidden xl:table-cell", header.breakpoint === "2xl" && "hidden 2xl:table-cell", header.sortBy && "cursor-pointer" )} >
{t(header.title)}
{header.sortBy && (
{getSortDirection(header) === "desc" ? ( ) : ( getSortDirection(header) === "asc" && )}
)}
{noRecords ?? (
{!emptyState ? ( {t("shared.noRecords")} ) : (
{emptyState.title}
{emptyState.description}
)}
)}
{selectedRows?.includes(item) &&
}
{ toggleSelected(idxRow, item); }} onClick={(e) => e.stopPropagation()} />
f.firstColumn).length === 0 && "pl-4", "whitespace-nowrap text-sm text-gray-700", header.className, padding ?? "px-2 py-2", header.breakpoint === "sm" && "hidden sm:table-cell", header.breakpoint === "md" && "mg:table-cell hidden", header.breakpoint === "lg" && "hidden lg:table-cell", header.breakpoint === "xl" && "hidden xl:table-cell", header.breakpoint === "2xl" && "hidden 2xl:table-cell", className && className(idxRow, item) )} > {RowDisplayValueHelper.displayRowValue(t, header, item, idxRow)}
No row
{pagination && ( )} ); } function ActionsCells({ item, actions, idxRow, className, }: { item: T; //@ts-ignore actions: RowHeaderActionDto[]; idxRow: number; className?: (idx: number, item: T) => string; }) { return ( <> {actions && actions.length > 0 && (
{actions .filter((f) => !f.hidden || !f.hidden(item)) .map((action, idx) => { return ( { e.stopPropagation(); e.preventDefault(); if (action.onClick) { action.onClick(idxRow, item); } }} to={action.onClickRoute && action.onClickRoute(idxRow, item)} target={action.onClickRouteTarget} > {action.renderTitle ? action.renderTitle(item) : action.title} ); })}
)} ); }