import { memo, useMemo } from 'react'
import { Box, Typography } from '@mui/material'
import type { AgentMetric, TeamAgent } from '../../domain/teamAgent'
import { EmptyState } from '../ui'
import { useMatchRuns } from '../../hooks/useMatchRuns'
import { useFutureSignals } from '../../hooks/useFutureSignals'
import { isRisiko } from '../../lib/leadSignal'
import { DS_BG, DS_BORDER, DS_TEXT } from '../../lib/ds'
/**
* Reiter «Kennzahlen».
*
* Zeigt die Kennzahlen, die das Personalblatt führt. Es wird nichts
* hochgerechnet und nichts ergänzt — was der Katalog nicht führt, steht hier
* auch nicht.
*
* Ausnahme seit Runde 10 (§3.11): Noras beide Kennzahlen kommen aus dem
* laufenden Stand der Anwendung und nicht aus dem Katalog. Ein fester Wert
* wäre dort eine Behauptung — die eine Zahl zählt tatsächlich ausgeführte
* Matching-Läufe, die andere tatsächlich zugeordnete Objekte.
*/
/** Kennungen, deren Wert zur Laufzeit entsteht. */
const MATCH_RUNS_METRIC = 'nora-metric-match-runs'
const AFFECTED_OBJECTS_METRIC = 'nora-metric-affected-objects'
const MetricTile = memo(function MetricTile({ metric }: { metric: AgentMetric }) {
return (
{metric.value}
{metric.label}
{metric.hint && (
{metric.hint}
)}
)
})
export function AgentMetricsTab({ agent }: { agent: TeamAgent }) {
const { data: matchRuns = [] } = useMatchRuns()
const { data: signals = [] } = useFutureSignals()
/**
* Die beiden Laufzeit-Kennzahlen einsetzen.
*
* «Betroffene Objekte» zählt Risikosignale mit eindeutig zugeordnetem
* Objekt — und zwar die Objekte, nicht die Signale: Zwei Meldungen über
* dasselbe Objekt sind ein betroffenes Objekt, nicht zwei.
*/
const metrics = useMemo((): AgentMetric[] => {
const laeufe = matchRuns.length
const betroffene = new Set(
signals.filter(sig => isRisiko(sig) && sig.propertyId).map(sig => sig.propertyId!),
).size
return agent.metrics.map((m) => {
if (m.id === MATCH_RUNS_METRIC) {
return {
...m,
value: String(laeufe),
hint: laeufe === 0
? 'Noch kein Matching ausgeführt. Die Zahl steigt nur durch einen tatsächlichen Lauf.'
: `Zuletzt am ${new Date(matchRuns[0].timestamp).toLocaleString('de-CH', { dateStyle: 'short', timeStyle: 'short' })} für «${matchRuns[0].leadTitle}».`,
}
}
if (m.id === AFFECTED_OBJECTS_METRIC) {
return {
...m,
value: String(betroffene),
hint: betroffene === 0
? 'Derzeit ist keinem Risikosignal ein Objekt aus dem Bestand eindeutig zugeordnet.'
: m.hint,
}
}
return m
})
}, [agent.metrics, matchRuns, signals])
if (metrics.length === 0) {
return (
)
}
return (
{metrics.map((metric) => (
))}
)
}