Fix therapeutic range input

This commit is contained in:
2025-11-24 18:48:20 +00:00
parent c4ddf1f32b
commit 84c88ea6d3
4 changed files with 70 additions and 61 deletions

View File

@@ -139,7 +139,7 @@ const MedPlanAssistant = () => {
therapeuticRange={therapeuticRange}
uiSettings={uiSettings}
onUpdatePkParams={(key, value) => updateNestedState('pkParams', key, value)}
onUpdateTherapeuticRange={(key, value) => updateNestedState('therapeuticRange', key, { [key]: value })}
onUpdateTherapeuticRange={(key, value) => updateNestedState('therapeuticRange', key, value)}
onUpdateUiSetting={updateUiSetting}
onReset={handleReset}
t={t}

View File

@@ -10,11 +10,14 @@ const NumericInput = ({
unit,
align = 'right', // 'left', 'center', 'right'
allowEmpty = false, // Allow empty value (e.g., for "Auto" mode)
clearButton = false, // Show clear button (with allowEmpty=true)
errorMessage = 'This field is required' // Error message for mandatory empty fields
}) => {
const [hasError, setHasError] = React.useState(false);
const [showErrorTooltip, setShowErrorTooltip] = React.useState(false);
const containerRef = React.useRef(null);
const showClearButton = clearButton && allowEmpty;
// Determine decimal places based on increment
const getDecimalPlaces = () => {
const inc = String(increment || '1');
@@ -158,14 +161,14 @@ const NumericInput = ({
return (
<div
ref={containerRef}
className="relative"
className="relative inline-block"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<div className="relative inline-flex items-center">
<button
onClick={() => updateValue(-1)}
className="px-2 py-1 border rounded-l-md bg-gray-100 hover:bg-gray-200 text-lg font-bold"
className="px-2 py-1 border rounded-l-md bg-gray-100 bg-gray-100 hover:bg-gray-200 text-gray-600 hover:text-gray-800 text-lg font-bold"
tabIndex={-1}
>
-
@@ -183,15 +186,15 @@ const NumericInput = ({
/>
<button
onClick={() => updateValue(1)}
className={`px-2 py-1 border bg-gray-100 hover:bg-gray-200 text-lg font-bold ${!allowEmpty ? 'rounded-r-md' : ''}`}
className={`px-2 py-1 border-t border-b ${showClearButton ? 'border-l' : 'border-l border-r rounded-r-md'} bg-gray-100 bg-gray-100 hover:bg-gray-200 text-gray-600 hover:text-gray-800 text-lg font-bold`}
tabIndex={-1}
>
+
</button>
{allowEmpty && (
{showClearButton && (
<button
onClick={handleClear}
className="px-2 py-1 border rounded-r-md bg-gray-100 hover:bg-gray-200 text-gray-600 hover:text-gray-800"
className="px-2 py-1 border rounded-r-md bg-gray-100 bg-gray-100 hover:bg-gray-200 text-gray-600 hover:text-gray-800 text-gray-600 hover:text-gray-800"
tabIndex={-1}
title="Clear (set to Auto)"
>
@@ -203,8 +206,8 @@ const NumericInput = ({
{hasError && (
<div className="absolute inset-0 border-2 border-red-500 rounded-md pointer-events-none" style={{ zIndex: 10 }} />
)}
</div>
{unit && <span className="ml-2 text-gray-500 text-sm whitespace-nowrap">{unit}</span>}
</div>
{hasError && showErrorTooltip && (
<div
className={`absolute z-50 bg-white border-2 border-red-500 rounded-md shadow-lg p-2 flex items-start gap-2 ${

View File

@@ -30,8 +30,8 @@ const Settings = ({
</label>
</div>
<div>
<label className="block font-medium text-gray-600 pt-2">{t.simulationDuration}</label>
<div className="w-40">
<NumericInput
value={simulationDays}
onChange={val => onUpdateUiSetting('simulationDays', val)}
@@ -43,8 +43,8 @@ const Settings = ({
/>
</div>
<div>
<label className="block font-medium text-gray-600">{t.displayedDays}</label>
<div className="w-40">
<NumericInput
value={displayedDays}
onChange={val => onUpdateUiSetting('displayedDays', val)}
@@ -56,6 +56,7 @@ const Settings = ({
/>
</div>
<div>
<label className="block font-medium text-gray-600 pt-2">{t.yAxisRange}</label>
<div className="flex items-center mt-1">
<div className="w-30">
@@ -66,6 +67,7 @@ const Settings = ({
min={0}
placeholder={t.auto}
allowEmpty={true}
clearButton={true}
/>
</div>
<span className="text-gray-500 px-2">-</span>
@@ -78,10 +80,13 @@ const Settings = ({
placeholder={t.auto}
unit="ng/ml"
allowEmpty={true}
clearButton={true}
/>
</div>
</div>
</div>
<div>
<label className="block font-medium text-gray-600">{t.therapeuticRange}</label>
<div className="flex items-center mt-1">
<div className="w-30">
@@ -107,9 +112,10 @@ const Settings = ({
/>
</div>
</div>
</div>
<h3 className="text-lg font-semibold mt-4 pt-4 border-t">{t.dAmphetamineParameters}</h3>
<div className="w-40">
<div>
<label className="block font-medium text-gray-600">{t.halfLife}</label>
<NumericInput
value={pkParams.damph.halfLife}
@@ -122,7 +128,7 @@ const Settings = ({
</div>
<h3 className="text-lg font-semibold mt-4 pt-4 border-t">{t.lisdexamfetamineParameters}</h3>
<div className="w-40">
<div>
<label className="block font-medium text-gray-600">{t.conversionHalfLife}</label>
<NumericInput
value={pkParams.ldx.halfLife}
@@ -133,7 +139,7 @@ const Settings = ({
errorMessage={t.fieldRequired}
/>
</div>
<div className="w-40">
<div>
<label className="block font-medium text-gray-600">{t.absorptionRate}</label>
<NumericInput
value={pkParams.ldx.absorptionRate}

View File

@@ -16,7 +16,7 @@ export const getDefaultState = () => ({
{ time: '01:00', dose: '0', label: 'night' },
],
steadyStateConfig: { daysOnMedication: '7' },
therapeuticRange: { min: '11.5', max: '14' },
therapeuticRange: { min: '10.5', max: '11.5' },
doseIncrement: '2.5',
uiSettings: {
showDayTimeXAxis: true,