Skip to content

Commit 6e2c00d

Browse files
committed
i hate this game
1 parent 511de6b commit 6e2c00d

File tree

7 files changed

+778
-325
lines changed

7 files changed

+778
-325
lines changed

apps/dashboard/components/analytics/components/table-content.tsx

Lines changed: 122 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,117 @@ import {
1717
TableRow,
1818
} from '@/components/ui/table';
1919
import { cn } from '@/lib/utils';
20-
import { useTableRowPercentage } from '../hooks/use-table-row-percentage';
20+
21+
// Row percentage thresholds for gradient colors
22+
const PERCENTAGE_THRESHOLDS = {
23+
HIGH: 50,
24+
MEDIUM: 25,
25+
LOW: 10,
26+
} as const;
27+
28+
interface PercentageRow {
29+
percentage?: string | number;
30+
}
31+
32+
function getRowPercentage(row: PercentageRow): number {
33+
const value = row.percentage;
34+
return value !== undefined ? Number.parseFloat(String(value)) || 0 : 0;
35+
}
36+
37+
// Color schemes for different percentage ranges
38+
const GRADIENT_COLORS = {
39+
high: {
40+
rgb: '34, 197, 94',
41+
opacity: {
42+
background: 0.08,
43+
hover: 0.12,
44+
border: 0.3,
45+
accent: 0.8,
46+
glow: 0.2,
47+
},
48+
},
49+
medium: {
50+
rgb: '59, 130, 246',
51+
opacity: {
52+
background: 0.08,
53+
hover: 0.12,
54+
border: 0.3,
55+
accent: 0.8,
56+
glow: 0.2,
57+
},
58+
},
59+
low: {
60+
rgb: '245, 158, 11',
61+
opacity: {
62+
background: 0.08,
63+
hover: 0.12,
64+
border: 0.3,
65+
accent: 0.8,
66+
glow: 0.2,
67+
},
68+
},
69+
default: {
70+
rgb: '107, 114, 128',
71+
opacity: {
72+
background: 0.06,
73+
hover: 0.1,
74+
border: 0.2,
75+
accent: 0.7,
76+
glow: 0.15,
77+
},
78+
},
79+
} as const;
80+
81+
function createGradient(
82+
rgb: string,
83+
opacity: typeof GRADIENT_COLORS.high.opacity,
84+
percentage: number
85+
) {
86+
const {
87+
background: bgOpacity,
88+
hover: hoverOpacity,
89+
border: borderOpacity,
90+
accent: accentOpacity,
91+
glow: glowOpacity,
92+
} = opacity;
93+
94+
return {
95+
background: `linear-gradient(90deg, rgba(${rgb}, ${bgOpacity}) 0%, rgba(${rgb}, ${bgOpacity + 0.07}) ${percentage * 0.8}%, rgba(${rgb}, ${bgOpacity + 0.04}) ${percentage}%, rgba(${rgb}, ${bgOpacity - 0.06}) ${percentage + 5}%, transparent 100%)`,
96+
hoverBackground: `linear-gradient(90deg, rgba(${rgb}, ${hoverOpacity}) 0%, rgba(${rgb}, ${hoverOpacity + 0.1}) ${percentage * 0.8}%, rgba(${rgb}, ${hoverOpacity + 0.06}) ${percentage}%, rgba(${rgb}, ${hoverOpacity - 0.08}) ${percentage + 5}%, transparent 100%)`,
97+
borderColor: `rgba(${rgb}, ${borderOpacity})`,
98+
accentColor: `rgba(${rgb}, ${accentOpacity})`,
99+
glowColor: `rgba(${rgb}, ${glowOpacity})`,
100+
};
101+
}
102+
103+
function getPercentageGradient(percentage: number) {
104+
if (percentage >= PERCENTAGE_THRESHOLDS.HIGH) {
105+
return createGradient(
106+
GRADIENT_COLORS.high.rgb,
107+
GRADIENT_COLORS.high.opacity,
108+
percentage
109+
);
110+
}
111+
if (percentage >= PERCENTAGE_THRESHOLDS.MEDIUM) {
112+
return createGradient(
113+
GRADIENT_COLORS.medium.rgb,
114+
GRADIENT_COLORS.medium.opacity,
115+
percentage
116+
);
117+
}
118+
if (percentage >= PERCENTAGE_THRESHOLDS.LOW) {
119+
return createGradient(
120+
GRADIENT_COLORS.low.rgb,
121+
GRADIENT_COLORS.low.opacity,
122+
percentage
123+
);
124+
}
125+
return createGradient(
126+
GRADIENT_COLORS.default.rgb,
127+
GRADIENT_COLORS.default.opacity,
128+
percentage
129+
);
130+
}
21131

22132
interface TableContentProps<TData extends { name: string | number }> {
23133
table: Table<TData>;
@@ -59,16 +169,19 @@ export function TableContent<TData extends { name: string | number }>({
59169
className,
60170
}: TableContentProps<TData>) {
61171
const [expandedRow, setExpandedRow] = useState<string | null>(null);
62-
const { getRowPercentage, getRowGradient, hasPercentageColumn } =
63-
useTableRowPercentage();
64172

65173
const toggleRowExpansion = useCallback((rowId: string) => {
66174
setExpandedRow((prev) => (prev === rowId ? null : rowId));
67175
}, []);
68176

69177
const displayData = table.getRowModel().rows;
70178
const tableData = displayData.map((row) => row.original);
71-
const hasPercentageData = hasPercentageColumn(tableData);
179+
180+
// Check if any row has percentage data
181+
const hasPercentageData = tableData.some((row) => {
182+
const percentage = getRowPercentage(row as PercentageRow);
183+
return percentage > 0;
184+
});
72185

73186
if (!displayData.length) {
74187
return (
@@ -200,11 +313,12 @@ export function TableContent<TData extends { name: string | number }>({
200313
const hasSubRows = subRows && subRows.length > 0;
201314
const isExpanded = expandedRow === row.id;
202315
const percentage = hasPercentageData
203-
? getRowPercentage(row.original)
316+
? getRowPercentage(row.original as PercentageRow)
204317
: 0;
205-
const gradient = hasPercentageData
206-
? getRowGradient(row.original)
207-
: null;
318+
const gradient =
319+
hasPercentageData && percentage > 0
320+
? getPercentageGradient(percentage)
321+
: null;
208322

209323
return (
210324
<Fragment key={row.id}>

apps/dashboard/components/analytics/data-table.tsx

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1-
import type { ColumnDef } from '@tanstack/react-table';
1+
import {
2+
type ColumnDef,
3+
getCoreRowModel,
4+
getFilteredRowModel,
5+
getSortedRowModel,
6+
type SortingState,
7+
useReactTable,
8+
} from '@tanstack/react-table';
29
import type React from 'react';
3-
import { useMemo } from 'react';
10+
import { useMemo, useState } from 'react';
411
import ReactDOM from 'react-dom';
512
import { Skeleton } from '@/components/ui/skeleton';
613
import { cn } from '@/lib/utils';
714
import { FullScreenModal } from './components/fullscreen-modal';
815
import { TableContent } from './components/table-content';
916
import { TableTabs } from './components/table-tabs';
1017
import { TableToolbar } from './components/table-toolbar';
11-
import { useDataTableTabs } from './hooks/use-data-table-tabs';
1218
import { useFullScreen } from './hooks/use-fullscreen';
13-
import { useTableState } from './hooks/use-table-state';
1419

1520
const DEFAULT_MIN_HEIGHT = 200;
1621
const FULLSCREEN_HEIGHT = 'h-[92vh]';
@@ -101,14 +106,14 @@ export function DataTable<TData extends { name: string | number }, TValue>({
101106
onAddFilter,
102107
onRowAction,
103108
}: DataTableProps<TData, TValue>) {
109+
const [sorting, setSorting] = useState<SortingState>([]);
110+
const [globalFilter, setGlobalFilter] = useState('');
111+
const [activeTab, setActiveTab] = useState(tabs?.[0]?.id || '');
112+
const [isTransitioning, setIsTransitioning] = useState(false);
113+
104114
const { fullScreen, setFullScreen, hasMounted, modalRef } = useFullScreen();
105-
const { activeTab, isTransitioning, handleTabChange, currentTabData } =
106-
useDataTableTabs({
107-
tabs,
108-
onGlobalFilterChange: () => {},
109-
onExpandedRowChange: () => {},
110-
});
111115

116+
const currentTabData = tabs?.find((tab) => tab.id === activeTab);
112117
const tableData = useMemo(
113118
() => currentTabData?.data || data || [],
114119
[currentTabData?.data, data]
@@ -119,13 +124,40 @@ export function DataTable<TData extends { name: string | number }, TValue>({
119124
[currentTabData?.columns, columns]
120125
);
121126

122-
const { table, globalFilter, setGlobalFilter } = useTableState({
127+
const table = useReactTable({
123128
data: tableData,
124-
columns: tableColumns as ColumnDef<TData, unknown>[],
125-
showSearch,
126-
activeTab,
129+
columns: tableColumns,
130+
getRowId: (row, index) => {
131+
if ((row as any)._uniqueKey) {
132+
return (row as any)._uniqueKey;
133+
}
134+
return activeTab ? `${activeTab}-${index}` : `row-${index}`;
135+
},
136+
state: {
137+
sorting,
138+
globalFilter: showSearch ? globalFilter : '',
139+
},
140+
onSortingChange: setSorting,
141+
onGlobalFilterChange: setGlobalFilter,
142+
getCoreRowModel: getCoreRowModel(),
143+
getFilteredRowModel: getFilteredRowModel(),
144+
getSortedRowModel: getSortedRowModel(),
127145
});
128146

147+
const handleTabChange = (tabId: string) => {
148+
if (tabId === activeTab) {
149+
return;
150+
}
151+
152+
setIsTransitioning(true);
153+
setTimeout(() => {
154+
setActiveTab(tabId);
155+
setGlobalFilter('');
156+
setSorting([]);
157+
setIsTransitioning(false);
158+
}, 150);
159+
};
160+
129161
if (isLoading) {
130162
return (
131163
<div

apps/dashboard/components/analytics/hooks/use-data-table-tabs.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)