Add intake auto sorting, chart intake markers, upped max daily intakes to 6, various style changes
This commit is contained in:
@@ -56,6 +56,7 @@ const SimulationChart = ({
|
||||
chartView,
|
||||
showDayTimeOnXAxis,
|
||||
showDayReferenceLines,
|
||||
showIntakeTimeLines,
|
||||
showTherapeuticRange,
|
||||
therapeuticRange,
|
||||
simulationDays,
|
||||
@@ -347,6 +348,44 @@ const SimulationChart = ({
|
||||
}
|
||||
}, [days, daysWithDeviations, t]);
|
||||
|
||||
// Extract all intake times from all days for intake time reference lines
|
||||
const intakeTimes = React.useMemo(() => {
|
||||
if (!days || !Array.isArray(days)) return [];
|
||||
|
||||
const times: Array<{ hour: number; dayIndex: number; doseIndex: number }> = [];
|
||||
const simDaysCount = parseInt(simulationDays, 10) || 3;
|
||||
|
||||
// Iterate through each simulated day
|
||||
for (let dayNum = 1; dayNum <= simDaysCount; dayNum++) {
|
||||
// Determine which schedule to use for this day
|
||||
let daySchedule;
|
||||
if (dayNum === 1 || days.length === 1) {
|
||||
// First day or only one schedule exists: use template/first schedule
|
||||
daySchedule = days.find(d => d.isTemplate) || days[0];
|
||||
} else {
|
||||
// For subsequent days, use the corresponding schedule if it exists, otherwise use template
|
||||
const scheduleIndex = dayNum - 1;
|
||||
daySchedule = days[scheduleIndex] || days.find(d => d.isTemplate) || days[0];
|
||||
}
|
||||
|
||||
if (daySchedule && daySchedule.doses) {
|
||||
daySchedule.doses.forEach((dose: any, doseIdx: number) => {
|
||||
if (dose.time) {
|
||||
const [hours, minutes] = dose.time.split(':').map(Number);
|
||||
const hoursSinceStart = (dayNum - 1) * 24 + hours + minutes / 60;
|
||||
times.push({
|
||||
hour: hoursSinceStart,
|
||||
dayIndex: dayNum,
|
||||
doseIndex: doseIdx + 1 // 1-based index
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return times;
|
||||
}, [days, simulationDays]);
|
||||
|
||||
// Merge all profiles into a single dataset for proper tooltip synchronization
|
||||
const mergedData = React.useMemo(() => {
|
||||
const dataMap = new Map();
|
||||
@@ -617,6 +656,43 @@ const SimulationChart = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
{showIntakeTimeLines && intakeTimes.map((intake, idx) => {
|
||||
// Determine label position offset if day lines are also shown
|
||||
const labelOffsetY = showDayReferenceLines !== false ? 20 : 5; // More spacing when day lines are shown
|
||||
|
||||
return (
|
||||
<ReferenceLine
|
||||
key={`intake-${idx}`}
|
||||
x={intake.hour}
|
||||
label={(props: any) => {
|
||||
const { viewBox } = props;
|
||||
// Position at top-right of the reference line with proper offsets
|
||||
// x: subtract 5px from right edge to create gap between line and text
|
||||
// y: add offset + ~12px (font size) since y is the text baseline, not top
|
||||
const x = viewBox.x + viewBox.width - 5;
|
||||
const y = viewBox.y + labelOffsetY + 12; // 12px ≈ 0.75rem font size
|
||||
|
||||
return (
|
||||
<text
|
||||
x={x}
|
||||
y={y}
|
||||
textAnchor="end"
|
||||
fontSize="0.75rem"
|
||||
fontStyle="italic"
|
||||
fill="#a0a0a0"
|
||||
>
|
||||
{intake.doseIndex}
|
||||
</text>
|
||||
);
|
||||
}}
|
||||
stroke="#c0c0c0"
|
||||
strokeDasharray="3 3"
|
||||
xAxisId="hours"
|
||||
yAxisId="concentration"
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
{[...Array(parseInt(simulationDays, 10) || 3).keys()].map(day => (
|
||||
day > 0 && (
|
||||
<ReferenceLine
|
||||
|
||||
Reference in New Issue
Block a user