'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 (
)
}