import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"; import { Table, flexRender } from "@tanstack/react-table"; import clsx from "clsx"; import { FC } from "react"; import { useDrag, useDrop } from "react-dnd"; import { includesDateNames } from "../../utils/utils"; export const magnitudeRegex = new RegExp("^([0-9]+)(\\s)([kKmMbBtT])$"); export const isoYearRegex = new RegExp("^\\d{4}$"); export const isoDateRegex = new RegExp( "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}|\\d{4}-\\d{2}-\\d{2}$", ); function Filter({ column, table, numberOfColumns, }: { column: any; table: Table; numberOfColumns: number; }) { function getTime(value: string | number | Date) { if (!value) return null; const datetime = new Date(value); const date = datetime.toISOString().split("T")[0]; const time = datetime.toTimeString().split(" ")[0]; return `${date} ${time}`; } const values = table.getPreFilteredRowModel().flatRows.map( (row: { getValue: (arg0: any) => any }) => // @ts-ignore row.original[column.id], ); const areAllValuesString = values.every( (value: null) => typeof value === "string" || value === null, ); const areAllValuesNumber = values.every( (value: null | number | string) => typeof value === "number" || magnitudeRegex.test(value as string) || value === null || value === "", ); const valuesContainStringWithSpaces = values.some( (value: string | string[]) => typeof value === "string" && value.includes(" "), ); const columnFilterValue = column.getFilterValue(); let dateType = "date"; const isProbablyDate = values.every((value: string) => { const only_numbers = value?.toString().replace(/[^0-9]/g, "").trim(); if (isoDateRegex.test(value?.toString())) { dateType = "datetime-local"; } if (isoYearRegex.test(value?.toString())) { dateType = "number"; } return ( only_numbers?.length >= 4 && (includesDateNames(column.id) || (column.id.toLowerCase() === "index" && !valuesContainStringWithSpaces)) ); }); if (isProbablyDate && dateType === "number") { return (
{ column.setFilterValue((old: [string, string]) => [ `${e.target.value}`, `${old?.[1]}`, ]); }} min={values.reduce( (acc: number, value: string) => Math.min(acc, parseInt(value, 10)), Infinity, )} max={values.reduce( (acc: number, value: string) => Math.max(acc, parseInt(value, 10)), -Infinity, )} placeholder={"Start year"} className="_input" title="Start year" /> { column.setFilterValue((old: [string, string]) => [ `${old?.[0]}`, `${e.target.value}`, ]); }} min={values.reduce( (acc: number, value: string) => Math.min(acc, parseInt(value, 10)), Infinity, )} max={values.reduce( (acc: number, value: string) => Math.max(acc, parseInt(value, 10)), -Infinity, )} placeholder={"End year"} className="_input" title="End year" />
); } if (isProbablyDate && dateType !== "number") { return (
{ const value = new Date(e.target.value).getTime(); column.setFilterValue((old: [string, string]) => [value, old?.[1]]); }} placeholder={"Start date"} className="_input" title="Start date" /> { const value = new Date(e.target.value).getTime(); column.setFilterValue((old: [string, string]) => [old?.[0], value]); }} placeholder={"End date"} className="_input" title="End date" />
); } if (areAllValuesNumber) { return (
column.setFilterValue((old: [number, number]) => [ e.target.value, old?.[1], ]) } placeholder={"Min"} className="_input p-0.5" title="Min" /> column.setFilterValue((old: [number, number]) => [ old?.[0], e.target.value, ]) } placeholder={"Max"} className="_input p-0.5" title="Max" />
); } if (areAllValuesString) { return (
column.setFilterValue(e.target.value)} placeholder={"Search..."} className="_input" title="Search" />
); } return
; } const reorderColumn = ( draggedColumnId: string, targetColumnId: string, columnOrder: string[], ) => { columnOrder.splice( columnOrder.indexOf(targetColumnId), 0, columnOrder.splice(columnOrder.indexOf(draggedColumnId), 1)[0] as string, ); return [...columnOrder]; }; const DraggableColumnHeader: FC<{ header: any; table: any; advanced: boolean; idx: number; lockFirstColumn: boolean; setLockFirstColumn: (value: boolean) => void; }> = ({ header, table, advanced, idx, lockFirstColumn, setLockFirstColumn, }) => { const { getState, setColumnOrder } = table; const { columnOrder } = getState(); const { column } = header; const [, dropRef] = useDrop({ accept: "column", drop: (draggedColumn: any) => { const newColumnOrder = reorderColumn( draggedColumn.id, column.id, columnOrder, ); setColumnOrder(newColumnOrder); }, }); const [{ isDragging }, dragRef, previewRef] = useDrag({ collect: (monitor) => ({ isDragging: monitor.isDragging(), }), item: () => column, type: "column", }); const renderField = () => (
{header.isPlaceholder ? null : ( <>
{flexRender(column.columnDef.header, header.getContext())} {column.getCanSort() && (
)}
{advanced && column.id !== "select" && ( )}
{advanced && column.getCanFilter() ? (
) : null} )}
); return ( {idx === 0 ? ( {renderField()}
) : ( renderField() )}