fix: bar chart uses analysis_summary from each day's status records

X-axis: animals with valid field data on that day.
Bars: Success / Failure / Total from status.analysis_summary for that day.
Each day shows its own session metrics. Animals without analysis_summary
or with total=0 are excluded from the chart.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Experiments DB Dev
2026-04-23 12:29:15 -04:00
parent b888c1b76d
commit 5f3ad1d408
2 changed files with 19 additions and 34 deletions
+13 -15
View File
@@ -53,25 +53,22 @@ function DayPanel({ date, animals, allStatuses, template, experimentId, selected
const fieldLabel = fieldOptions.find((f) => f.value === selectedField)?.label;
// Bar chart: this day's field value per animal (numeric only, filtered to animals present that day)
// Bar chart: animals with analysis_summary on this day → Success/Failure/Total from that summary
const barData = useMemo(() => {
if (!selectedField) return [];
const isBuiltin = BUILTIN_KEYS_SET.has(selectedField);
return animalsWithData
.map((animal) => {
const status = statusByAnimal[animal.id];
if (!status) return null;
const raw = isBuiltin ? status[selectedField] : status.custom_fields?.[selectedField];
if (raw === null || raw === undefined || String(raw).trim() === '') return null;
const num = parseFloat(raw);
if (isNaN(num)) return null;
const summary = status?.analysis_summary;
if (!summary || summary.total === 0) return null;
return {
name: animal.animal_name || animal.animal_id_string || animal.id.slice(0, 8),
value: num,
total: summary.total,
success: summary.counts?.Success ?? 0,
failure: summary.counts?.Failure ?? 0,
};
})
.filter(Boolean);
}, [animalsWithData, statusByAnimal, selectedField]);
}, [animalsWithData, statusByAnimal]);
return (
<div className="space-y-3 max-h-[80vh] overflow-y-auto pr-1">
@@ -120,16 +117,17 @@ function DayPanel({ date, animals, allStatuses, template, experimentId, selected
{/* Bar chart: overall per-subject completeness */}
{barData.length > 0 && (
<div className="mt-4 pt-4 border-t border-gray-100">
<h4 className="text-sm font-semibold text-gray-700 mb-3">
{fieldLabel ?? 'Field'} this session
</h4>
<h4 className="text-sm font-semibold text-gray-700 mb-3">Session metrics</h4>
<ResponsiveContainer width="100%" height={200}>
<BarChart data={barData} margin={{ top: 4, right: 16, left: 0, bottom: 4 }}>
<CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" />
<XAxis dataKey="name" tick={{ fontSize: 11 }} />
<YAxis tick={{ fontSize: 11 }} />
<Tooltip formatter={(v) => [v, fieldLabel ?? 'Value']} />
<Bar dataKey="value" name={fieldLabel ?? 'Value'} fill="#6366f1" radius={[3, 3, 0, 0]} />
<Tooltip />
<Legend wrapperStyle={{ fontSize: 11 }} />
<Bar dataKey="total" name="Total" fill="#94a3b8" radius={[3, 3, 0, 0]} />
<Bar dataKey="success" name="Success" fill="#22c55e" radius={[3, 3, 0, 0]} />
<Bar dataKey="failure" name="Failure" fill="#f87171" radius={[3, 3, 0, 0]} minPointSize={2} />
</BarChart>
</ResponsiveContainer>
</div>