Update new unified dose management, style/other improvements

This commit is contained in:
2025-12-02 21:39:17 +00:00
parent 3fa5bf8360
commit bbdfc5f894
15 changed files with 830 additions and 495 deletions

View File

@@ -10,7 +10,7 @@
*/
import React from 'react';
import { LOCAL_STORAGE_KEY, getDefaultState, type AppState } from '../constants/defaults';
import { LOCAL_STORAGE_KEY, getDefaultState, type AppState, type DayGroup, type DayDose } from '../constants/defaults';
export const useAppState = () => {
const [appState, setAppState] = React.useState<AppState>(getDefaultState);
@@ -26,6 +26,7 @@ export const useAppState = () => {
...defaults,
...parsedState,
pkParams: {...defaults.pkParams, ...parsedState.pkParams},
days: parsedState.days || defaults.days,
uiSettings: {...defaults.uiSettings, ...parsedState.uiSettings},
});
}
@@ -40,7 +41,7 @@ export const useAppState = () => {
try {
const stateToSave = {
pkParams: appState.pkParams,
doses: appState.doses,
days: appState.days,
steadyStateConfig: appState.steadyStateConfig,
therapeuticRange: appState.therapeuticRange,
doseIncrement: appState.doseIncrement,
@@ -72,15 +73,119 @@ export const useAppState = () => {
key: K,
value: AppState['uiSettings'][K]
) => {
const newUiSettings = { ...appState.uiSettings, [key]: value };
if (key === 'simulationDays') {
const simDaysNum = parseInt(value as string, 10) || 1;
const dispDaysNum = parseInt(newUiSettings.displayedDays, 10) || 1;
if (dispDaysNum > simDaysNum) {
newUiSettings.displayedDays = String(simDaysNum);
setAppState(prev => {
const newUiSettings = { ...prev.uiSettings, [key]: value };
// Auto-adjust displayedDays if simulationDays is reduced
if (key === 'simulationDays') {
const simDays = parseInt(value as string, 10) || 3;
const dispDays = parseInt(prev.uiSettings.displayedDays, 10) || 2;
if (dispDays > simDays) {
newUiSettings.displayedDays = String(simDays);
}
}
}
setAppState(prev => ({ ...prev, uiSettings: newUiSettings }));
return { ...prev, uiSettings: newUiSettings };
});
};
// Day management functions
const addDay = (cloneFromDayId?: string) => {
const maxDays = 3; // Template + 2 deviation days
if (appState.days.length >= maxDays) return;
const sourceDay = cloneFromDayId
? appState.days.find(d => d.id === cloneFromDayId)
: undefined;
const newDay: DayGroup = sourceDay
? {
id: `day-${Date.now()}`,
isTemplate: false,
doses: sourceDay.doses.map(d => ({
id: `dose-${Date.now()}-${Math.random()}`,
time: d.time,
ldx: d.ldx
}))
}
: {
id: `day-${Date.now()}`,
isTemplate: false,
doses: [{ id: `dose-${Date.now()}`, time: '12:00', ldx: '30' }]
};
setAppState(prev => ({ ...prev, days: [...prev.days, newDay] }));
};
const removeDay = (dayId: string) => {
setAppState(prev => {
const dayToRemove = prev.days.find(d => d.id === dayId);
// Never delete template day
if (dayToRemove?.isTemplate) {
console.warn('Cannot delete template day');
return prev;
}
// Never delete if it would leave us with no days
if (prev.days.length <= 1) {
console.warn('Cannot delete last day');
return prev;
}
return { ...prev, days: prev.days.filter(d => d.id !== dayId) };
});
};
const updateDay = (dayId: string, updatedDay: DayGroup) => {
setAppState(prev => ({
...prev,
days: prev.days.map(day => day.id === dayId ? updatedDay : day)
}));
};
const addDoseToDay = (dayId: string, newDose?: Partial<DayDose>) => {
setAppState(prev => ({
...prev,
days: prev.days.map(day => {
if (day.id !== dayId) return day;
if (day.doses.length >= 5) return day; // Max 5 doses per day
const dose: DayDose = {
id: `dose-${Date.now()}-${Math.random()}`,
time: newDose?.time || '12:00',
ldx: newDose?.ldx || '0',
damph: newDose?.damph || '0',
};
return { ...day, doses: [...day.doses, dose] };
})
}));
};
const removeDoseFromDay = (dayId: string, doseId: string) => {
setAppState(prev => ({
...prev,
days: prev.days.map(day => {
if (day.id !== dayId) return day;
// Don't allow removing last dose from template day
if (day.isTemplate && day.doses.length <= 1) return day;
return { ...day, doses: day.doses.filter(dose => dose.id !== doseId) };
})
}));
};
const updateDoseInDay = (dayId: string, doseId: string, field: keyof DayDose, value: string) => {
setAppState(prev => ({
...prev,
days: prev.days.map(day => {
if (day.id !== dayId) return day;
return {
...day,
doses: day.doses.map(dose =>
dose.id === doseId ? { ...dose, [field]: value } : dose
)
};
})
}));
};
const handleReset = () => {
@@ -96,6 +201,12 @@ export const useAppState = () => {
updateState,
updateNestedState,
updateUiSetting,
addDay,
removeDay,
updateDay,
addDoseToDay,
removeDoseFromDay,
updateDoseInDay,
handleReset
};
};