fix: hide subjects with no data in day modal; fix failure bar rendering

- Day modal now only shows animals that have a status record for that day
- Removed '+ Add' button and 'No data' placeholder for absent subjects
- Fixed failure bars disappearing in recharts: removed radius from all bars,
  added minPointSize=2 on failure bar so zero-value bars remain visible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Experiments DB Dev
2026-04-23 12:13:05 -04:00
parent d764bc66fb
commit 8b40856205
2 changed files with 17 additions and 15 deletions
+14 -13
View File
@@ -72,10 +72,16 @@ function DayPanel({ date, animals, allStatuses, template, experimentId, selected
const fieldLabel = fieldOptions.find((f) => f.value === selectedField)?.label; const fieldLabel = fieldOptions.find((f) => f.value === selectedField)?.label;
// Only show animals that have a status record for this day
const animalsWithData = animals.filter((a) => statusByAnimal[a.id]);
return ( return (
<div className="space-y-3 max-h-[80vh] overflow-y-auto pr-1"> <div className="space-y-3 max-h-[80vh] overflow-y-auto pr-1">
{animalsWithData.length === 0 && (
<p className="text-gray-400 text-sm py-2">No data recorded for this day.</p>
)}
{/* Per-animal data for this day */} {/* Per-animal data for this day */}
{animals.map((animal) => { {animalsWithData.map((animal) => {
const existing = statusByAnimal[animal.id]; const existing = statusByAnimal[animal.id];
const isEditing = editingAnimalId === animal.id; const isEditing = editingAnimalId === animal.id;
return ( return (
@@ -93,7 +99,7 @@ function DayPanel({ date, animals, allStatuses, template, experimentId, selected
onClick={() => setEditingAnimalId(animal.id)} onClick={() => setEditingAnimalId(animal.id)}
className="text-xs text-blue-600 hover:text-blue-800 border border-blue-200 rounded px-2 py-0.5 hover:bg-blue-50 transition-colors" className="text-xs text-blue-600 hover:text-blue-800 border border-blue-200 rounded px-2 py-0.5 hover:bg-blue-50 transition-colors"
> >
{existing ? 'Edit' : '+ Add'} Edit
</button> </button>
)} )}
</div> </div>
@@ -102,17 +108,12 @@ function DayPanel({ date, animals, allStatuses, template, experimentId, selected
animalId={animal.id} animalId={animal.id}
experimentId={experimentId} experimentId={experimentId}
template={template} template={template}
existing={existing ? { ...existing, date: dateStr } : undefined} existing={{ ...existing, date: dateStr }}
onSuccess={(saved) => { onSuccess={(saved) => { onStatusChange(saved); setEditingAnimalId(null); }}
if (existing) { onStatusChange(saved); } else { onStatusCreate(saved); }
setEditingAnimalId(null);
}}
onCancel={() => setEditingAnimalId(null)} onCancel={() => setEditingAnimalId(null)}
/> />
) : existing ? (
<SubjectReadOnly status={existing} template={template} />
) : ( ) : (
<p className="text-xs text-gray-400">No data recorded for this day.</p> <SubjectReadOnly status={existing} template={template} />
)} )}
</div> </div>
); );
@@ -132,9 +133,9 @@ function DayPanel({ date, animals, allStatuses, template, experimentId, selected
<YAxis tick={{ fontSize: 11 }} allowDecimals={false} /> <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />
<Tooltip /> <Tooltip />
<Legend wrapperStyle={{ fontSize: 11 }} /> <Legend wrapperStyle={{ fontSize: 11 }} />
<Bar dataKey="total" name="Total" fill="#94a3b8" radius={[3, 3, 0, 0]} /> <Bar dataKey="total" name="Total" fill="#94a3b8" />
<Bar dataKey="success" name="Success" fill="#22c55e" radius={[3, 3, 0, 0]} /> <Bar dataKey="success" name="Success" fill="#22c55e" />
<Bar dataKey="failure" name="Failure" fill="#f87171" radius={[3, 3, 0, 0]} /> <Bar dataKey="failure" name="Failure" fill="#f87171" minPointSize={2} />
</BarChart> </BarChart>
</ResponsiveContainer> </ResponsiveContainer>
<div className="mt-2 flex flex-wrap gap-4"> <div className="mt-2 flex flex-wrap gap-4">
+3 -2
View File
@@ -227,8 +227,9 @@ describe('day click modal', () => {
expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
}); });
it('shows all animals in the modal (with and without data)', async () => { it('shows only animals with data — excludes subjects with no record that day', async () => {
const dateStr = todayStr(); const dateStr = todayStr();
// Only Rat A has a record; Rat B does not
const statuses = [ const statuses = [
makeStatus('a1000000-0000-0000-0000-000000000001', dateStr, { 'ww000000-0000-0000-0000-000000000099': '320' }), makeStatus('a1000000-0000-0000-0000-000000000001', dateStr, { 'ww000000-0000-0000-0000-000000000099': '320' }),
]; ];
@@ -239,7 +240,7 @@ describe('day click modal', () => {
await waitFor(() => { await waitFor(() => {
const dialog = screen.getByRole('dialog'); const dialog = screen.getByRole('dialog');
expect(within(dialog).getAllByText('Rat A').length).toBeGreaterThan(0); expect(within(dialog).getAllByText('Rat A').length).toBeGreaterThan(0);
expect(within(dialog).getAllByText('Rat B').length).toBeGreaterThan(0); expect(within(dialog).queryAllByText('Rat B')).toHaveLength(0);
}); });
}); });
}); });