diff --git a/ui/src/pages/occurrences/occurrence-stats.tsx b/ui/src/pages/occurrences/occurrence-stats.tsx new file mode 100644 index 000000000..7b12cbb8e --- /dev/null +++ b/ui/src/pages/occurrences/occurrence-stats.tsx @@ -0,0 +1,73 @@ +import { useModelAgreement } from 'data-services/hooks/occurrences/stats/useModelAgreement' +import { Box } from 'nova-ui-kit' + +interface OccurrenceStatsProps { + projectId?: string + filters: { field: string; value?: string; error?: string }[] +} + +const StatBar = ({ label, value }: { label: string; value: number }) => { + const pct = Math.round(Math.min(Math.max(value, 0), 1) * 100) + + return ( +
+ + {label} + +
+
+
+
+ {pct}% +
+
+ ) +} + +// Live verified / agreement stats for the occurrence list. Threads the same +// filter array the list view sends so the numbers always match the result set. +export const OccurrenceStats = ({ + projectId, + filters, +}: OccurrenceStatsProps) => { + const activeFilters = filters.reduce>( + (acc, { field, value, error }) => { + if (value?.length && !error) { + acc[field] = value + } + return acc + }, + {} + ) + + const { data, isLoading, error } = useModelAgreement(projectId, activeFilters) + + if (error || (!isLoading && !data)) { + return null + } + + return ( + + Stats +
+ {isLoading || !data ? ( + <> +
+
+ + ) : ( + <> + + + + )} +
+ + ) +} diff --git a/ui/src/pages/occurrences/occurrences.tsx b/ui/src/pages/occurrences/occurrences.tsx index 9a1071a3c..77da98ea6 100644 --- a/ui/src/pages/occurrences/occurrences.tsx +++ b/ui/src/pages/occurrences/occurrences.tsx @@ -35,6 +35,7 @@ import { useSelectedView } from 'utils/useSelectedView' import { useSort } from 'utils/useSort' import { columns } from './occurrence-columns' import { OccurrenceGallery } from './occurrence-gallery' +import { OccurrenceStats } from './occurrence-stats' import { OccurrenceNavigation } from './occurrence-navigation' import { OccurrencesActions } from './occurrences-actions' @@ -94,6 +95,7 @@ export const Occurrences = () => { <>
+