Files
teOS/apps/web/src/components/charts/line-chart.tsx
Flexomatic81 fe305f6fc8 feat: complete tOS project with HR, LEAN, Dashboard and Integrations modules
Full enterprise web operating system including:
- Next.js 14 frontend with App Router, i18n (DE/EN), shadcn/ui
- NestJS 10 backend with Prisma, JWT auth, Swagger docs
- Keycloak 24 SSO with role-based access control
- HR module (employees, time tracking, absences, org chart)
- LEAN module (3S planning, morning meeting SQCDM, skill matrix)
- Integrations module (PlentyONE, Zulip, Todoist, FreeScout, Nextcloud, ecoDMS, GembaDocs)
- Dashboard with customizable drag & drop widget grid
- Docker Compose infrastructure (PostgreSQL 16, Redis 7, Keycloak 24)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 19:37:55 +01:00

128 lines
3.1 KiB
TypeScript

'use client';
import {
LineChart as RechartsLineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
Legend,
} from 'recharts';
import { ChartContainer, ChartEmptyState } from './chart-container';
interface LineChartDataPoint {
name: string;
[key: string]: string | number;
}
interface LineChartSeries {
dataKey: string;
name: string;
color: string;
strokeWidth?: number;
dot?: boolean;
dashed?: boolean;
}
interface LineChartProps {
/** Chart title */
title: string;
/** Optional description */
description?: string;
/** Data points to display */
data: LineChartDataPoint[];
/** Series configuration */
series: LineChartSeries[];
/** Whether data is loading */
isLoading?: boolean;
/** Chart height */
height?: number;
/** Whether to show grid lines */
showGrid?: boolean;
/** Whether to show legend */
showLegend?: boolean;
/** Whether to use curved lines */
curved?: boolean;
/** Additional CSS classes */
className?: string;
}
/**
* Line Chart component using Recharts
* Supports single or multiple series with various styling options
*/
export function LineChart({
title,
description,
data,
series,
isLoading = false,
height = 300,
showGrid = true,
showLegend = true,
curved = true,
className,
}: LineChartProps) {
if (!isLoading && data.length === 0) {
return (
<ChartContainer title={title} description={description} height={height} className={className}>
<ChartEmptyState />
</ChartContainer>
);
}
return (
<ChartContainer
title={title}
description={description}
isLoading={isLoading}
height={height}
className={className}
>
<ResponsiveContainer width="100%" height="100%">
<RechartsLineChart data={data} margin={{ top: 10, right: 30, left: 0, bottom: 0 }}>
{showGrid && (
<CartesianGrid strokeDasharray="3 3" className="stroke-muted" opacity={0.5} />
)}
<XAxis
dataKey="name"
className="text-xs"
tick={{ fill: 'hsl(var(--muted-foreground))' }}
/>
<YAxis className="text-xs" tick={{ fill: 'hsl(var(--muted-foreground))' }} />
<Tooltip
contentStyle={{
backgroundColor: 'hsl(var(--popover))',
border: '1px solid hsl(var(--border))',
borderRadius: '0.5rem',
color: 'hsl(var(--popover-foreground))',
}}
/>
{showLegend && <Legend wrapperStyle={{ paddingTop: '20px' }} />}
{series.map((s) => (
<Line
key={s.dataKey}
type={curved ? 'monotone' : 'linear'}
dataKey={s.dataKey}
name={s.name}
stroke={s.color}
strokeWidth={s.strokeWidth || 2}
strokeDasharray={s.dashed ? '5 5' : undefined}
dot={s.dot !== false}
activeDot={{ r: 6, strokeWidth: 2 }}
/>
))}
</RechartsLineChart>
</ResponsiveContainer>
</ChartContainer>
);
}