mirror of
https://github.com/kjanat/livedash-node.git
synced 2026-01-16 18:32:10 +01:00
Major code quality overhaul addressing 58% of all linting issues: • Type Safety Improvements: - Replace all any types with proper TypeScript interfaces - Fix Map component shadowing (renamed to CountryMap) - Add comprehensive custom error classes system - Enhance API route type safety • Accessibility Enhancements: - Add explicit button types to all interactive elements - Implement useId() hooks for form element accessibility - Add SVG title attributes for screen readers - Fix static element interactions with keyboard handlers • React Best Practices: - Resolve exhaustive dependencies warnings with useCallback - Extract nested component definitions to top level - Fix array index keys with proper unique identifiers - Improve component organization and prop typing • Code Organization: - Automatic import organization and type import optimization - Fix unused function parameters and variables - Enhanced error handling with structured error responses - Improve component reusability and maintainability Results: 248 → 104 total issues (58% reduction) - Fixed all critical type safety and security issues - Enhanced accessibility compliance significantly - Improved code maintainability and performance
135 lines
3.5 KiB
TypeScript
135 lines
3.5 KiB
TypeScript
"use client";
|
|
|
|
import { useId } from "react";
|
|
import {
|
|
Area,
|
|
AreaChart,
|
|
CartesianGrid,
|
|
Line,
|
|
LineChart,
|
|
ResponsiveContainer,
|
|
Tooltip,
|
|
XAxis,
|
|
YAxis,
|
|
} from "recharts";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
|
|
interface LineChartData {
|
|
date: string;
|
|
value: number;
|
|
[key: string]: string | number;
|
|
}
|
|
|
|
interface LineChartProps {
|
|
data: LineChartData[];
|
|
title?: string;
|
|
dataKey?: string;
|
|
color?: string;
|
|
gradient?: boolean;
|
|
height?: number;
|
|
className?: string;
|
|
}
|
|
|
|
interface TooltipProps {
|
|
active?: boolean;
|
|
payload?: Array<{ value: number; name?: string }>;
|
|
label?: string;
|
|
}
|
|
|
|
const CustomTooltip = ({ active, payload, label }: TooltipProps) => {
|
|
if (active && payload && payload.length) {
|
|
return (
|
|
<div className="rounded-lg border bg-background p-3 shadow-md">
|
|
<p className="text-sm font-medium">{label}</p>
|
|
<p className="text-sm text-muted-foreground">
|
|
<span className="font-medium text-foreground">
|
|
{payload[0].value}
|
|
</span>{" "}
|
|
sessions
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
export default function ModernLineChart({
|
|
data,
|
|
title,
|
|
dataKey = "value",
|
|
color = "hsl(var(--primary))",
|
|
gradient = true,
|
|
height = 300,
|
|
className,
|
|
}: LineChartProps) {
|
|
const gradientId = useId();
|
|
const ChartComponent = gradient ? AreaChart : LineChart;
|
|
|
|
return (
|
|
<Card className={className}>
|
|
{title && (
|
|
<CardHeader>
|
|
<CardTitle className="text-lg font-semibold">{title}</CardTitle>
|
|
</CardHeader>
|
|
)}
|
|
<CardContent>
|
|
<ResponsiveContainer width="100%" height={height}>
|
|
<ChartComponent
|
|
data={data}
|
|
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
|
|
>
|
|
<defs>
|
|
{gradient && (
|
|
<linearGradient id={gradientId} x1="0" y1="0" x2="0" y2="1">
|
|
<stop offset="5%" stopColor={color} stopOpacity={0.3} />
|
|
<stop offset="95%" stopColor={color} stopOpacity={0.05} />
|
|
</linearGradient>
|
|
)}
|
|
</defs>
|
|
<CartesianGrid
|
|
strokeDasharray="3 3"
|
|
stroke="hsl(var(--border))"
|
|
strokeOpacity={0.3}
|
|
/>
|
|
<XAxis
|
|
dataKey="date"
|
|
stroke="hsl(var(--muted-foreground))"
|
|
fontSize={12}
|
|
tickLine={false}
|
|
axisLine={false}
|
|
/>
|
|
<YAxis
|
|
stroke="hsl(var(--muted-foreground))"
|
|
fontSize={12}
|
|
tickLine={false}
|
|
axisLine={false}
|
|
/>
|
|
<Tooltip content={<CustomTooltip />} />
|
|
|
|
{gradient ? (
|
|
<Area
|
|
type="monotone"
|
|
dataKey={dataKey}
|
|
stroke={color}
|
|
strokeWidth={2}
|
|
fill={`url(#${gradientId})`}
|
|
dot={{ fill: color, strokeWidth: 2, r: 4 }}
|
|
activeDot={{ r: 6, stroke: color, strokeWidth: 2 }}
|
|
/>
|
|
) : (
|
|
<Line
|
|
type="monotone"
|
|
dataKey={dataKey}
|
|
stroke={color}
|
|
strokeWidth={2}
|
|
dot={{ fill: color, strokeWidth: 2, r: 4 }}
|
|
activeDot={{ r: 6, stroke: color, strokeWidth: 2 }}
|
|
/>
|
|
)}
|
|
</ChartComponent>
|
|
</ResponsiveContainer>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|