Files
property-match/.claude/worktrees/agent-a82a3716/src/components/data-quality/DataQualityBar.tsx
T
Benjamin Sutter d15a13e485 feat: remove Administration workspace — keep only Verwaltung + Suche
- Delete all ops page components (ReviewQueue, AIMonitoring, Governance,
  SourceMonitoring, ActivityTimeline, SignalPipeline)
- Remove OPERATIONS workspace from AppShell config, nav order, path detection
- Remove all /ops/* routes from App.tsx
- Remove WorkspaceType.OPERATIONS from allowedWorkspaces in authService,
  sessionStore, permissions
- Keep MarketIntelligence page (already moved to /supply/market-intelligence)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 20:32:41 +02:00

102 lines
3.8 KiB
TypeScript

import { Box, LinearProgress, Tooltip, Typography, Chip } from '@mui/material'
import { AlertTriangle } from 'lucide-react'
import { dataQualityColor, dataQualityHex, formatPercent } from '../../lib/utils'
import { FRESHNESS_LABELS } from '../../lib/constants'
import type { DataQuality } from '../../domain/property'
interface DataQualityBarProps {
quality: DataQuality
compact?: boolean
showWarnings?: boolean
}
export function DataQualityBar({ quality, compact = false, showWarnings = true }: DataQualityBarProps) {
const color = dataQualityColor(quality.score)
const hex = dataQualityHex(quality.score)
const pct = Math.round(quality.score * 100)
const tooltipContent = (
<Box sx={{ p: 0.5 }}>
<Typography variant="caption" sx={{ fontWeight: 600, display: 'block', mb: 0.5 }}>
Datenqualität {formatPercent(quality.score)}
</Typography>
{quality.missingCriticalFields.length > 0 && (
<Box sx={{ mb: 0.5 }}>
<Typography variant="caption" sx={{ color: '#fca5a5', display: 'block' }}>Fehlende Pflichtfelder:</Typography>
{quality.missingCriticalFields.map(f => (
<Typography key={f} variant="caption" sx={{ display: 'block', pl: 1 }}> {f}</Typography>
))}
</Box>
)}
{quality.warnings.length > 0 && (
<Box>
<Typography variant="caption" sx={{ color: '#fcd34d', display: 'block' }}>Warnungen:</Typography>
{quality.warnings.map((w, i) => (
<Typography key={i} variant="caption" sx={{ display: 'block', pl: 1 }}> {w}</Typography>
))}
</Box>
)}
<Typography variant="caption" sx={{ color: '#94a3b8', display: 'block', mt: 0.5 }}>
Aktualität: {FRESHNESS_LABELS[quality.freshness]}
{quality.lastVerifiedAt ? ` · Geprüft: ${quality.lastVerifiedAt}` : ''}
</Typography>
</Box>
)
if (compact) {
return (
<Tooltip title={tooltipContent} arrow placement="top">
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.75, cursor: 'default' }}>
<Box sx={{ width: 56 }}>
<LinearProgress
variant="determinate"
value={pct}
color={color}
sx={{ height: 5, borderRadius: 3 }}
/>
</Box>
<Typography variant="caption" sx={{ color: hex, fontWeight: 600, fontSize: '0.7rem', whiteSpace: 'nowrap' }}>
{pct}%
</Typography>
{quality.missingCriticalFields.length > 0 && showWarnings && (
<AlertTriangle size={11} color="#d97706" />
)}
</Box>
</Tooltip>
)
}
return (
<Box>
<Tooltip title={tooltipContent} arrow placement="top">
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, cursor: 'default' }}>
<Box sx={{ flex: 1, minWidth: 80 }}>
<LinearProgress
variant="determinate"
value={pct}
color={color}
sx={{ height: 6, borderRadius: 3 }}
/>
</Box>
<Typography variant="caption" sx={{ color: hex, fontWeight: 600, whiteSpace: 'nowrap' }}>
{pct}%
</Typography>
</Box>
</Tooltip>
{showWarnings && quality.missingCriticalFields.length > 0 && (
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.25, mt: 0.5 }}>
{quality.missingCriticalFields.slice(0, 2).map(f => (
<Chip key={f} label={f} size="small" color="error" variant="outlined"
sx={{ height: 16, fontSize: '0.625rem' }} />
))}
{quality.missingCriticalFields.length > 2 && (
<Typography variant="caption" sx={{ color: 'error.main' }}>
+{quality.missingCriticalFields.length - 2}
</Typography>
)}
</Box>
)}
</Box>
)
}