From 3ebd7ea251b7b9088ca36dbc40c75b51d6af6296 Mon Sep 17 00:00:00 2001 From: Andreas Weyer Date: Thu, 8 Jan 2026 13:15:49 +0000 Subject: [PATCH] Update separated pharmacokinetic from diagram settings, made both collapsible --- src/components/settings.tsx | 428 +++++++++++++++++++----------------- src/constants/defaults.ts | 2 +- src/locales/de.ts | 6 +- src/locales/en.ts | 6 +- 4 files changed, 234 insertions(+), 208 deletions(-) diff --git a/src/components/settings.tsx b/src/components/settings.tsx index c37e6b7..7da1a1e 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -18,6 +18,7 @@ import { Label } from './ui/label'; import { Separator } from './ui/separator'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './ui/tooltip'; +import { ChevronDown, ChevronUp } from 'lucide-react'; const Settings = ({ pkParams, @@ -32,217 +33,238 @@ const Settings = ({ const { showDayTimeOnXAxis, yAxisMin, yAxisMax, showTemplateDay, simulationDays, displayedDays } = uiSettings; const showDayReferenceLines = (uiSettings as any).showDayReferenceLines ?? true; + const [isDiagramExpanded, setIsDiagramExpanded] = React.useState(true); + const [isPharmacokineticExpanded, setIsPharmacokineticExpanded] = React.useState(true); + return ( - - - {t('diagramSettings')} - - -
- - - - -
- -
- onUpdateUiSetting('showDayReferenceLines', checked)} - /> - -
- -
- onUpdateUiSetting('showTemplateDay', checked)} - /> - -
- -
- - onUpdateUiSetting('simulationDays', val)} - increment={1} - min={3} - max={7} - unit={t('unitDays')} - required={true} - errorMessage={t('errorNumberRequired')} - /> -
- -
- - onUpdateUiSetting('displayedDays', val)} - increment={1} - min={1} - max={parseInt(simulationDays, 10) || 3} - unit={t('unitDays')} - required={true} - errorMessage={t('errorNumberRequired')} - /> -
- -
- -
- onUpdateUiSetting('yAxisMin', val)} - increment={1} - min={0} - placeholder={t('auto')} - allowEmpty={true} - clearButton={true} - /> - - - onUpdateUiSetting('yAxisMax', val)} - increment={5} - min={0} - placeholder={t('auto')} - unit="ng/ml" - allowEmpty={true} - clearButton={true} - /> +
+ {/* Diagram Settings Card */} + + setIsDiagramExpanded(!isDiagramExpanded)}> +
+ {t('diagramSettings')} + {isDiagramExpanded ? : }
-
+ + {isDiagramExpanded && ( + +
+ + + + +
-
- -
- onUpdateTherapeuticRange('min', val)} - increment={0.5} - min={0} - placeholder={t('min')} - required={true} - errorMessage={t('therapeuticRangeMinRequired') || 'Minimum therapeutic range is required'} - /> - - - onUpdateTherapeuticRange('max', val)} - increment={0.5} - min={0} - placeholder={t('max')} - unit="ng/ml" - required={true} - errorMessage={t('therapeuticRangeMaxRequired') || 'Maximum therapeutic range is required'} - /> +
+ onUpdateUiSetting('showDayReferenceLines', checked)} + /> + +
+ +
+ onUpdateUiSetting('showTemplateDay', checked)} + /> + +
+ +
+ + onUpdateUiSetting('simulationDays', val)} + increment={1} + min={3} + max={7} + unit={t('unitDays')} + required={true} + errorMessage={t('errorNumberRequired')} + /> +
+ +
+ + onUpdateUiSetting('displayedDays', val)} + increment={1} + min={1} + max={parseInt(simulationDays, 10) || 3} + unit={t('unitDays')} + required={true} + errorMessage={t('errorNumberRequired')} + /> +
+ +
+ +
+ onUpdateUiSetting('yAxisMin', val)} + increment={1} + min={0} + placeholder={t('auto')} + allowEmpty={true} + clearButton={true} + /> + - + onUpdateUiSetting('yAxisMax', val)} + increment={1} + min={0} + placeholder={t('auto')} + unit="ng/ml" + allowEmpty={true} + clearButton={true} + /> +
+
+ +
+ +
+ onUpdateTherapeuticRange('min', val)} + increment={0.5} + min={0} + placeholder={t('min')} + required={true} + errorMessage={t('therapeuticRangeMinRequired') || 'Minimum therapeutic range is required'} + /> + - + onUpdateTherapeuticRange('max', val)} + increment={0.5} + min={0} + placeholder={t('max')} + unit="ng/ml" + required={true} + errorMessage={t('therapeuticRangeMaxRequired') || 'Maximum therapeutic range is required'} + /> +
+
+ + )} + + + {/* Pharmacokinetic Settings Card */} + + setIsPharmacokineticExpanded(!isPharmacokineticExpanded)}> +
+ {t('pharmacokineticsSettings')} + {isPharmacokineticExpanded ? : }
-
+ + {isPharmacokineticExpanded && ( + +

{t('dAmphetamineParameters')}

+
+ + onUpdatePkParams('damph', { ...pkParams.damph, halfLife: val })} + increment={0.5} + min={0.1} + unit="h" + required={true} + errorMessage={t('halfLifeRequired') || 'Half-life is required'} + /> +
- + -

{t('dAmphetamineParameters')}

-
- - onUpdatePkParams('damph', { ...pkParams.damph, halfLife: val })} - increment={0.5} - min={0.1} - unit="h" - required={true} - errorMessage={t('halfLifeRequired') || 'Half-life is required'} - /> -
+

{t('lisdexamfetamineParameters')}

+
+ + onUpdatePkParams('ldx', { ...pkParams.ldx, halfLife: val })} + increment={0.1} + min={0.1} + unit="h" + required={true} + errorMessage={t('conversionHalfLifeRequired') || 'Conversion half-life is required'} + /> +
- +
+ + onUpdatePkParams('ldx', { ...pkParams.ldx, absorptionRate: val })} + increment={0.1} + min={0.1} + unit={t('faster')} + required={true} + errorMessage={t('absorptionRateRequired') || 'Absorption rate is required'} + /> +
+
+ )} + -

{t('lisdexamfetamineParameters')}

-
- - onUpdatePkParams('ldx', { ...pkParams.ldx, halfLife: val })} - increment={0.1} - min={0.1} - unit="h" - required={true} - errorMessage={t('conversionHalfLifeRequired') || 'Conversion half-life is required'} - /> -
- -
- - onUpdatePkParams('ldx', { ...pkParams.ldx, absorptionRate: val })} - increment={0.1} - min={0.1} - unit={t('faster')} - required={true} - errorMessage={t('absorptionRateRequired') || 'Absorption rate is required'} - /> -
- - - - - - + {/* Reset Button - Always Visible */} + +
); }; diff --git a/src/constants/defaults.ts b/src/constants/defaults.ts index c16ed63..2ba3f1c 100644 --- a/src/constants/defaults.ts +++ b/src/constants/defaults.ts @@ -105,6 +105,6 @@ export const getDefaultState = (): AppState => ({ yAxisMin: '8', yAxisMax: '13', simulationDays: '5', - displayedDays: '5', + displayedDays: '2', } }); diff --git a/src/locales/de.ts b/src/locales/de.ts index f01499d..efd992b 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -55,6 +55,7 @@ export const de = { // Settings diagramSettings: "Diagramm-Einstellungen", + pharmacokineticsSettings: "Pharmakokinetik-Einstellungen", xAxisTimeFormat: "Zeitformat", xAxisFormatContinuous: "Fortlaufend", xAxisFormatContinuousDesc: "Endlose Sequenz (0h, 6h, 12h...)", @@ -77,8 +78,9 @@ export const de = { conversionHalfLife: "Umwandlungs-Halbwertszeit", absorptionRate: "Absorptionsrate", faster: "(schneller >)", - resetAllSettings: "Alle Einstellungen zurücksetzen", - + resetAllSettings: "Alle Einstellungen zurücksetzen", resetDiagramSettings: "Diagramm-Einstellungen zurücksetzen", + resetPharmacokineticSetting: "Pharmakokinetik-Einstellungen zurücksetzen", + resetPlan: "Plan zurücksetzen", // Units unitMg: "mg", unitNgml: "ng/ml", diff --git a/src/locales/en.ts b/src/locales/en.ts index 235ac3e..776dad9 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -54,6 +54,7 @@ export const en = { // Settings diagramSettings: "Diagram Settings", + pharmacokineticsSettings: "Pharmacokinetics Settings", xAxisTimeFormat: "Time Format", xAxisFormatContinuous: "Continuous", xAxisFormatContinuousDesc: "Endless sequence (0h, 6h, 12h...)", @@ -76,8 +77,9 @@ export const en = { conversionHalfLife: "Conversion Half-life", absorptionRate: "Absorption Rate", faster: "(faster >)", - resetAllSettings: "Reset All Settings", - + resetAllSettings: "Reset All Settings", resetDiagramSettings: "Reset Diagram Settings", + resetPharmacokineticSettings: "Reset Pharmacokinetic Settings", + resetPlan: "Reset Plan", // Units unitMg: "mg", unitNgml: "ng/ml",