Skip to content

Commit fad7b32

Browse files
committed
cleanup metrics chart
1 parent 75a2358 commit fad7b32

File tree

2 files changed

+36
-136
lines changed

2 files changed

+36
-136
lines changed

apps/dashboard/components/charts/metrics-chart.tsx

Lines changed: 35 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { ChartLineIcon } from '@phosphor-icons/react';
2-
import { useCallback, useMemo } from 'react';
32
import {
43
Area,
54
AreaChart,
@@ -20,27 +19,13 @@ import {
2019
import { cn } from '@/lib/utils';
2120
import {
2221
type ChartDataRow,
23-
METRIC_COLORS,
2422
METRICS,
2523
type MetricConfig,
2624
} from './metrics-constants';
2725
import { SkeletonChart } from './skeleton-chart';
2826

29-
const CustomTooltip = ({
30-
active,
31-
payload,
32-
label,
33-
}: {
34-
active?: boolean;
35-
payload?: Array<{
36-
name: string;
37-
value: number;
38-
color: string;
39-
payload: ChartDataRow;
40-
}>;
41-
label?: string;
42-
}) => {
43-
if (!(active && payload && payload.length)) {
27+
const CustomTooltip = ({ active, payload, label }: any) => {
28+
if (!(active && payload?.length)) {
4429
return null;
4530
}
4631

@@ -51,38 +36,31 @@ const CustomTooltip = ({
5136
<p className="font-semibold text-foreground text-sm">{label}</p>
5237
</div>
5338
<div className="space-y-2.5">
54-
{payload.map((entry) => {
55-
const dataPoint = entry.payload;
56-
const metric = METRICS.find(
57-
(m) => m.label === entry.name || m.key === entry.name
58-
);
39+
{payload.map((entry: any) => {
40+
const metric = METRICS.find((m) => m.key === entry.dataKey);
5941
if (!metric) {
6042
return null;
6143
}
6244

63-
const Icon = metric.icon;
6445
const displayValue = metric.formatValue
65-
? metric.formatValue(entry.value, dataPoint)
46+
? metric.formatValue(entry.value, entry.payload)
6647
: entry.value.toLocaleString();
6748

6849
return (
6950
<div
70-
className="group flex items-center justify-between gap-3"
71-
key={`item-${metric.key}`}
51+
className="flex items-center justify-between gap-3"
52+
key={metric.key}
7253
>
7354
<div className="flex items-center gap-2.5">
7455
<div
75-
className="h-3 w-3 rounded-full shadow-sm ring-2 ring-background"
56+
className="h-3 w-3 rounded-full"
7657
style={{ backgroundColor: entry.color }}
7758
/>
78-
<div className="flex items-center gap-1.5">
79-
<Icon className="h-3 w-3" />
80-
<span className="font-medium text-muted-foreground text-xs">
81-
{metric.label}
82-
</span>
83-
</div>
59+
<span className="text-muted-foreground text-xs">
60+
{metric.label}
61+
</span>
8462
</div>
85-
<span className="font-bold text-foreground text-sm group-hover:text-primary">
63+
<span className="font-bold text-foreground text-sm">
8664
{displayValue}
8765
</span>
8866
</div>
@@ -118,17 +96,17 @@ export function MetricsChart({
11896
metricsFilter,
11997
showLegend = true,
12098
}: MetricsChartProps) {
121-
const chartData = useMemo(() => data || [], [data]);
99+
const chartData = data || [];
122100

123-
const valueFormatter = useCallback((value: number): string => {
101+
const valueFormatter = (value: number): string => {
124102
if (value >= 1_000_000) {
125103
return `${(value / 1_000_000).toFixed(1)}M`;
126104
}
127105
if (value >= 1000) {
128106
return `${(value / 1000).toFixed(1)}k`;
129107
}
130108
return value.toString();
131-
}, []);
109+
};
132110

133111
const yAxisConfig = {
134112
yAxisId: 'left',
@@ -185,15 +163,15 @@ export function MetricsChart({
185163

186164
const displayMetrics = metricsFilter
187165
? METRICS.filter(metricsFilter)
188-
: METRICS.filter((metric) =>
189-
[
166+
: METRICS.filter((metric) => {
167+
return [
190168
'pageviews',
191169
'visitors',
192170
'sessions',
193171
'bounce_rate',
194172
'avg_session_duration',
195-
].includes(metric.key)
196-
);
173+
].includes(metric.key);
174+
});
197175

198176
return (
199177
<Card className={cn('w-full overflow-hidden rounded-none p-0', className)}>
@@ -202,8 +180,6 @@ export function MetricsChart({
202180
className="relative"
203181
style={{ width: '100%', height: height + 20 }}
204182
>
205-
<div className="pointer-events-none absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-muted/5" />
206-
207183
<ResponsiveContainer height="100%" width="100%">
208184
<AreaChart
209185
data={chartData}
@@ -215,41 +191,27 @@ export function MetricsChart({
215191
}}
216192
>
217193
<defs>
218-
{Object.entries(METRIC_COLORS).map(([key, colors]) => (
194+
{displayMetrics.map((metric) => (
219195
<linearGradient
220-
id={`gradient-${key}`}
221-
key={key}
196+
id={`gradient-${metric.gradient}`}
197+
key={metric.key}
222198
x1="0"
223199
x2="0"
224200
y1="0"
225201
y2="1"
226202
>
227203
<stop
228204
offset="0%"
229-
stopColor={colors.primary}
205+
stopColor={metric.color}
230206
stopOpacity={0.3}
231207
/>
232-
<stop
233-
offset="50%"
234-
stopColor={colors.primary}
235-
stopOpacity={0.1}
236-
/>
237208
<stop
238209
offset="100%"
239-
stopColor={colors.primary}
210+
stopColor={metric.color}
240211
stopOpacity={0.02}
241212
/>
242213
</linearGradient>
243214
))}
244-
{Object.entries(METRIC_COLORS).map(([key]) => (
245-
<filter id={`glow-${key}`} key={`glow-${key}`}>
246-
<feGaussianBlur result="coloredBlur" stdDeviation="3" />
247-
<feMerge>
248-
<feMergeNode in="coloredBlur" />
249-
<feMergeNode in="SourceGraphic" />
250-
</feMerge>
251-
</filter>
252-
))}
253215
</defs>
254216
<CartesianGrid
255217
stroke="var(--border)"
@@ -284,104 +246,42 @@ export function MetricsChart({
284246
align="center"
285247
formatter={(value) => {
286248
const metric = displayMetrics.find(
287-
(m) => m.label === value || m.key === value
249+
(m) => m.label === value
288250
);
289-
if (!metric) {
290-
// Fallback for unknown metrics
291-
return (
292-
<span className="inline-flex cursor-pointer select-none items-center font-medium text-muted-foreground text-xs capitalize leading-none opacity-100 transition-all duration-200 hover:text-foreground">
293-
{String(value).replace(/_/g, ' ')}
294-
</span>
295-
);
296-
}
297-
298-
const hasData = chartData.some(
299-
(item) =>
300-
metric.key in item &&
301-
item[metric.key] !== undefined &&
302-
item[metric.key] !== null
303-
);
304-
const isHidden = hiddenMetrics[metric.key];
305-
251+
const isHidden = metric && hiddenMetrics[metric.key];
306252
return (
307253
<span
308-
className={`inline-flex cursor-pointer select-none items-center font-medium text-xs capitalize leading-none transition-all duration-200 ${
254+
className={`cursor-pointer text-xs ${
309255
isHidden
310-
? 'text-slate-600 line-through decoration-1 opacity-40'
311-
: hasData
312-
? 'text-muted-foreground opacity-100 hover:text-foreground'
313-
: 'text-muted-foreground/60 opacity-60 hover:text-foreground'
256+
? 'text-muted-foreground/50 line-through'
257+
: 'text-muted-foreground hover:text-foreground'
314258
}`}
315259
>
316-
{metric.label}
260+
{value}
317261
</span>
318262
);
319263
}}
320-
iconSize={10}
321-
iconType="circle"
322-
layout="horizontal"
323-
onClick={(payload) => {
324-
const anyPayload = payload as unknown as {
325-
dataKey?: string | number;
326-
value?: string | number;
327-
id?: string | number;
328-
};
329-
const raw =
330-
anyPayload?.dataKey ??
331-
anyPayload?.value ??
332-
anyPayload?.id;
333-
if (raw == null || !onToggleMetric) {
334-
return;
335-
}
336-
const key = String(raw);
264+
onClick={(payload: any) => {
337265
const metric = displayMetrics.find(
338-
(m) => m.label === key || m.key === key
266+
(m) => m.label === payload.value
339267
);
340-
if (metric) {
268+
if (metric && onToggleMetric) {
341269
onToggleMetric(metric.key);
342270
}
343271
}}
344-
payload={displayMetrics.map((metric) => ({
345-
value: metric.label,
346-
type: 'circle',
347-
color: metric.color,
348-
id: metric.key,
349-
dataKey: metric.key,
350-
}))}
351272
verticalAlign="bottom"
352-
wrapperStyle={{
353-
display: 'flex',
354-
justifyContent: 'center',
355-
gap: 12,
356-
fontSize: '12px',
357-
paddingTop: '20px',
358-
bottom: chartData.length > 5 ? 35 : 5,
359-
fontWeight: 500,
360-
cursor: 'pointer',
361-
}}
362273
/>
363274
)}
364275
{displayMetrics.map((metric) => {
365276
const hasData = chartData.some(
366-
(item) =>
367-
metric.key in item &&
368-
item[metric.key] !== undefined &&
369-
item[metric.key] !== null
277+
(item) => item[metric.key] != null
370278
);
371279
const isHidden = hiddenMetrics[metric.key];
372280
return (
373281
<Area
374-
activeDot={{
375-
r: 6,
376-
strokeWidth: 3,
377-
stroke: metric.color,
378-
fill: 'var(--background)',
379-
filter: `url(#glow-${metric.gradient})`,
380-
}}
282+
activeDot={{ r: 4, stroke: metric.color, strokeWidth: 2 }}
381283
dataKey={metric.key}
382-
dot={{ r: 0 }}
383284
fill={`url(#gradient-${metric.gradient})`}
384-
fillOpacity={1}
385285
hide={!hasData || isHidden}
386286
key={metric.key}
387287
name={metric.label}

apps/dashboard/components/charts/metrics-constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export interface ChartDataRow {
175175
bounce_rate?: number;
176176
avg_session_duration?: number;
177177
avg_session_duration_formatted?: string;
178-
// Load time metrics
178+
// Load time metrics\
179179
avg_load_time?: number;
180180
p50_load_time?: number;
181181
p75_load_time?: number;

0 commit comments

Comments
 (0)