Update NumericInput size and decimal digits

This commit is contained in:
2025-11-11 09:45:58 +01:00
parent cfc6088d22
commit e774c74fe9
3 changed files with 66 additions and 12 deletions

View File

@@ -15,7 +15,7 @@ const DeviationList = ({
<div className="bg-amber-50 p-5 rounded-lg shadow-sm border border-amber-200"> <div className="bg-amber-50 p-5 rounded-lg shadow-sm border border-amber-200">
<h2 className="text-xl font-semibold mb-4 text-gray-700">{t.deviationsFromPlan}</h2> <h2 className="text-xl font-semibold mb-4 text-gray-700">{t.deviationsFromPlan}</h2>
{deviations.map((dev, index) => ( {deviations.map((dev, index) => (
<div key={index} className="flex items-center space-x-2 mb-2 p-2 bg-white rounded flex-wrap"> <div key={index} className="flex items-center gap-3 mb-2 p-2 bg-white rounded flex-wrap">
<select <select
value={dev.dayOffset || 0} value={dev.dayOffset || 0}
onChange={e => onDeviationChange(index, 'dayOffset', parseInt(e.target.value, 10))} onChange={e => onDeviationChange(index, 'dayOffset', parseInt(e.target.value, 10))}
@@ -40,11 +40,11 @@ const DeviationList = ({
</div> </div>
<button <button
onClick={() => onRemoveDeviation(index)} onClick={() => onRemoveDeviation(index)}
className="text-red-500 hover:text-red-700 font-bold text-lg" className="text-red-500 hover:text-red-700 font-bold text-lg px-1"
> >
&times; &times;
</button> </button>
<div className="flex items-center mt-1" title={t.additionalTooltip}> <div className="flex items-center" title={t.additionalTooltip}>
<input <input
type="checkbox" type="checkbox"
id={`add_dose_${index}`} id={`add_dose_${index}`}
@@ -52,7 +52,7 @@ const DeviationList = ({
onChange={e => onDeviationChange(index, 'isAdditional', e.target.checked)} onChange={e => onDeviationChange(index, 'isAdditional', e.target.checked)}
className="h-4 w-4 rounded border-gray-300 text-sky-600 focus:ring-sky-500" className="h-4 w-4 rounded border-gray-300 text-sky-600 focus:ring-sky-500"
/> />
<label htmlFor={`add_dose_${index}`} className="ml-2 text-xs text-gray-600"> <label htmlFor={`add_dose_${index}`} className="ml-2 text-xs text-gray-600 whitespace-nowrap">
{t.additional} {t.additional}
</label> </label>
</div> </div>

View File

@@ -1,13 +1,42 @@
import React from 'react'; import React from 'react';
const NumericInput = ({ value, onChange, increment, min = -Infinity, max = Infinity, placeholder, unit }) => { const NumericInput = ({
value,
onChange,
increment,
min = -Infinity,
max = Infinity,
placeholder,
unit,
align = 'right' // 'left', 'center', 'right'
}) => {
// Determine decimal places based on increment
const getDecimalPlaces = () => {
const inc = String(increment || '1');
const decimalIndex = inc.indexOf('.');
if (decimalIndex === -1) return 0;
return inc.length - decimalIndex - 1;
};
const decimalPlaces = getDecimalPlaces();
// Format value for display
const formatValue = (val) => {
const num = Number(val);
if (isNaN(num)) return val;
return num.toFixed(decimalPlaces);
};
const updateValue = (direction) => { const updateValue = (direction) => {
const numIncrement = parseFloat(increment) || 1; const numIncrement = parseFloat(increment) || 1;
let numValue = parseFloat(value) || 0; let numValue = Number(value);
if (isNaN(numValue)) {
numValue = min !== -Infinity ? min : 0;
}
numValue += direction * numIncrement; numValue += direction * numIncrement;
numValue = Math.max(min, numValue); numValue = Math.max(min, numValue);
numValue = Math.min(max, numValue); numValue = Math.min(max, numValue);
const finalValue = String(Math.round(numValue * 100) / 100); const finalValue = formatValue(numValue);
onChange(finalValue); onChange(finalValue);
}; };
@@ -20,16 +49,38 @@ const NumericInput = ({ value, onChange, increment, min = -Infinity, max = Infin
const handleChange = (e) => { const handleChange = (e) => {
const val = e.target.value; const val = e.target.value;
// Only allow valid numbers or empty string
if (val === '' || /^-?\d*\.?\d*$/.test(val)) { if (val === '' || /^-?\d*\.?\d*$/.test(val)) {
// Prevent object values
if (typeof val === 'object') return;
onChange(val); onChange(val);
} }
}; };
const handleBlur = (e) => {
const val = e.target.value;
if (val !== '' && !isNaN(Number(val))) {
// Format the value when user finishes editing
onChange(formatValue(val));
}
};
// Get alignment class
const getAlignmentClass = () => {
switch (align) {
case 'left': return 'text-left';
case 'center': return 'text-center';
case 'right': return 'text-right';
default: return 'text-right';
}
};
return ( return (
<div className="flex items-center w-full"> <div className="flex items-center w-full">
<button <button
onClick={() => updateValue(-1)} 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 hover:bg-gray-200 text-lg font-bold"
tabIndex={-1}
> >
- -
</button> </button>
@@ -38,12 +89,15 @@ const NumericInput = ({ value, onChange, increment, min = -Infinity, max = Infin
value={value} value={value}
onChange={handleChange} onChange={handleChange}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
onBlur={handleBlur}
placeholder={placeholder} placeholder={placeholder}
className="p-2 border-t border-b w-full text-sm text-center" style={{ width: '4em', minWidth: '4em', maxWidth: '8em' }}
className={`p-2 border-t border-b text-sm ${getAlignmentClass()}`}
/> />
<button <button
onClick={() => updateValue(1)} onClick={() => updateValue(1)}
className="px-2 py-1 border rounded-r-md bg-gray-100 hover:bg-gray-200 text-lg font-bold" className="px-2 py-1 border rounded-r-md bg-gray-100 hover:bg-gray-200 text-lg font-bold"
tabIndex={-1}
> >
+ +
</button> </button>

View File

@@ -55,7 +55,7 @@ const Settings = ({
</div> </div>
<label className="block font-medium text-gray-600 pt-2">{t.yAxisRange}</label> <label className="block font-medium text-gray-600 pt-2">{t.yAxisRange}</label>
<div className="flex items-center space-x-2 mt-1"> <div className="flex items-center space-x-3 mt-1">
<div className="w-32"> <div className="w-32">
<NumericInput <NumericInput
value={yAxisMin} value={yAxisMin}
@@ -66,7 +66,7 @@ const Settings = ({
unit="ng/ml" unit="ng/ml"
/> />
</div> </div>
<span className="text-gray-500">-</span> <span className="text-gray-500 px-2">-</span>
<div className="w-32"> <div className="w-32">
<NumericInput <NumericInput
value={yAxisMax} value={yAxisMax}
@@ -80,7 +80,7 @@ const Settings = ({
</div> </div>
<label className="block font-medium text-gray-600">{t.therapeuticRange}</label> <label className="block font-medium text-gray-600">{t.therapeuticRange}</label>
<div className="flex items-center space-x-2 mt-1"> <div className="flex items-center space-x-3 mt-1">
<div className="w-32"> <div className="w-32">
<NumericInput <NumericInput
value={therapeuticRange.min} value={therapeuticRange.min}
@@ -91,7 +91,7 @@ const Settings = ({
unit="ng/ml" unit="ng/ml"
/> />
</div> </div>
<span className="text-gray-500">-</span> <span className="text-gray-500 px-2">-</span>
<div className="w-32"> <div className="w-32">
<NumericInput <NumericInput
value={therapeuticRange.max} value={therapeuticRange.max}