'use client' /** * ComplianceTrendChart Component * * Displays compliance score trend over time using Recharts. * Shows 12-month history with interactive tooltip. */ import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Area, AreaChart, } from 'recharts' import { Language, getTerm } from '@/lib/compliance-i18n' interface TrendDataPoint { date: string score: number label?: string } interface ComplianceTrendChartProps { data: TrendDataPoint[] lang?: Language height?: number showArea?: boolean } export default function ComplianceTrendChart({ data, lang = 'de', height = 200, showArea = true, }: ComplianceTrendChartProps) { if (!data || data.length === 0) { return (
{lang === 'de' ? 'Keine Trenddaten verfuegbar' : 'No trend data available'}
) } const getScoreColor = (score: number) => { if (score >= 80) return '#22c55e' // green-500 if (score >= 60) return '#eab308' // yellow-500 return '#ef4444' // red-500 } const latestScore = data[data.length - 1]?.score || 0 const strokeColor = getScoreColor(latestScore) const CustomTooltip = ({ active, payload, label }: any) => { if (active && payload && payload.length) { const score = payload[0].value return (

{label}

{score.toFixed(1)}%

) } return null } if (showArea) { return ( `${value}%`} /> } /> ) } return ( `${value}%`} /> } /> ) } /** * TrafficLightIndicator Component * * Large circular indicator showing overall compliance status. */ interface TrafficLightIndicatorProps { status: 'green' | 'yellow' | 'red' score: number lang?: Language size?: 'sm' | 'md' | 'lg' } export function TrafficLightIndicator({ status, score, lang = 'de', size = 'lg' }: TrafficLightIndicatorProps) { const colors = { green: { bg: 'bg-green-500', ring: 'ring-green-200', text: 'text-green-700' }, yellow: { bg: 'bg-yellow-500', ring: 'ring-yellow-200', text: 'text-yellow-700' }, red: { bg: 'bg-red-500', ring: 'ring-red-200', text: 'text-red-700' }, } const sizes = { sm: { container: 'w-16 h-16', text: 'text-lg', label: 'text-xs' }, md: { container: 'w-24 h-24', text: 'text-2xl', label: 'text-sm' }, lg: { container: 'w-32 h-32', text: 'text-4xl', label: 'text-base' }, } const labels = { green: { de: 'Gut', en: 'Good' }, yellow: { de: 'Achtung', en: 'Attention' }, red: { de: 'Kritisch', en: 'Critical' }, } const { bg, ring, text } = colors[status] const { container, text: textSize, label: labelSize } = sizes[size] return (
{score.toFixed(0)}%
{labels[status][lang]}
) } /** * MiniSparkline Component * * Tiny inline chart for trend indication. */ interface MiniSparklineProps { data: number[] width?: number height?: number } export function MiniSparkline({ data, width = 60, height = 20 }: MiniSparklineProps) { if (!data || data.length < 2) { return -- } const chartData = data.map((value, index) => ({ value, index })) const trend = data[data.length - 1] - data[0] const color = trend >= 0 ? '#22c55e' : '#ef4444' return ( ) }