DataTable.utils.ts88 lines · main
1import { FilterFn } from '@tanstack/react-table'
2import { isAfter, isBefore, isSameDay } from 'date-fns'
3
4import { LEVELS } from './DataTable.constants'
5
6export function formatCompactNumber(value: number) {
7 if (value >= 100 && value < 1000) {
8 return value.toString() // Keep the number as is if it's in the hundreds
9 } else if (value >= 1000 && value < 1000000) {
10 return (value / 1000).toFixed(1) + 'k' // Convert to 'k' for thousands
11 } else if (value >= 1000000) {
12 return (value / 1000000).toFixed(1) + 'M' // Convert to 'M' for millions
13 } else {
14 return value.toString() // Optionally handle numbers less than 100 if needed
15 }
16}
17
18export function isArrayOfNumbers(arr: any): arr is number[] {
19 if (!Array.isArray(arr)) return false
20 return arr.every((item) => typeof item === 'number')
21}
22
23export function isArrayOfDates(arr: any): arr is Date[] {
24 if (!Array.isArray(arr)) return false
25 return arr.every((item) => item instanceof Date)
26}
27
28export function isArrayOfStrings(arr: any): arr is string[] {
29 if (!Array.isArray(arr)) return false
30 return arr.every((item) => typeof item === 'string')
31}
32
33export function isArrayOfBooleans(arr: any): arr is boolean[] {
34 if (!Array.isArray(arr)) return false
35 return arr.every((item) => typeof item === 'boolean')
36}
37
38export const inDateRange: FilterFn<any> = (row, columnId, value) => {
39 const date = new Date(row.getValue(columnId))
40 const [start, end] = value as Date[]
41
42 if (isNaN(date.getTime())) return false
43
44 // if no end date, check if it's the same day
45 if (!end) return isSameDay(date, start)
46
47 return isAfter(date, start) && isBefore(date, end)
48}
49
50inDateRange.autoRemove = (val: any) => !Array.isArray(val) || !val.length || !isArrayOfDates(val)
51
52export const arrSome: FilterFn<any> = (row, columnId, filterValue) => {
53 if (!Array.isArray(filterValue)) return false
54 return filterValue.some((val) => row.getValue<unknown[]>(columnId) === val)
55}
56
57arrSome.autoRemove = (val: any) => !Array.isArray(val) || !val?.length
58
59export function getLevelColor(
60 value: (typeof LEVELS)[number]
61): Record<'text' | 'bg' | 'border', string> {
62 switch (value) {
63 case 'success':
64 return {
65 text: 'text-muted',
66 bg: 'bg-muted group-data-[state=selected]/row:bg-foreground-lighter',
67 border: 'border-muted group-data-[state=selected]/row:border-foreground-lighter',
68 }
69 case 'warning':
70 return {
71 text: 'text-warning',
72 bg: 'bg-warning',
73 border: 'border-warning',
74 }
75 case 'error':
76 return {
77 text: 'text-destructive',
78 bg: 'bg-destructive',
79 border: 'border-destructive',
80 }
81 default:
82 return {
83 text: 'text-info',
84 bg: 'bg-info',
85 border: 'border-info',
86 }
87 }
88}