import React, { useState, useEffect, useMemo } from 'react'; import { format, startOfMonth, endOfMonth, eachDayOfInterval, getDay, addMonths, subMonths, } from 'date-fns'; import { useNavigate } from 'react-router-dom'; import { experimentsApi } from '../api/client'; export default function ExperimentCalendar({ experimentId, template }) { const navigate = useNavigate(); const [currentMonth, setCurrentMonth] = useState(() => new Date()); const [selectedField, setSelectedField] = useState(null); const [calendarDays, setCalendarDays] = useState({}); const fieldOptions = useMemo( () => template.filter((f) => f.active).map((f) => ({ value: f.builtin ? f.key : f.fieldId, label: f.label })), [template], ); useEffect(() => { if (fieldOptions.length === 0 || selectedField) return; const weightField = fieldOptions.find((f) => f.label.toLowerCase().includes('weight')); setSelectedField(weightField ? weightField.value : fieldOptions[0]?.value ?? null); }, [fieldOptions]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { if (!selectedField) return; let cancelled = false; experimentsApi.getCalendar(experimentId, selectedField) .then(({ days }) => { if (!cancelled) setCalendarDays(days); }) .catch(() => {}); return () => { cancelled = true; }; }, [experimentId, selectedField]); const monthStart = startOfMonth(currentMonth); const monthEnd = endOfMonth(currentMonth); const days = eachDayOfInterval({ start: monthStart, end: monthEnd }); const leadingPad = getDay(monthStart); return (

Daily Record Calendar

Count by field:
{format(currentMonth, 'MMMM yyyy')}
{['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map((d) => (
{d}
))}
{Array.from({ length: leadingPad }).map((_, i) =>
)} {days.map((day) => { const dateStr = format(day, 'yyyy-MM-dd'); const count = calendarDays[dateStr] ?? 0; const hasData = count > 0; return ( ); })}
); }