From efa45ab28882897b7224fe8d5e4dfdc61a38f1e2 Mon Sep 17 00:00:00 2001 From: Andreas Weyer Date: Wed, 4 Feb 2026 12:24:03 +0000 Subject: [PATCH] Update data deletion now in data manager with customization, minor UI improvements, increased chart y-axis tick count (regression) --- src/App.tsx | 28 ++- src/components/data-management-modal.tsx | 234 ++++++++++++++++++++++- src/components/settings.tsx | 27 +-- src/components/simulation-chart.tsx | 4 +- src/components/ui/form-numeric-input.tsx | 18 +- src/constants/defaults.ts | 9 +- src/hooks/useAppState.ts | 10 +- src/locales/de.ts | 14 ++ src/locales/en.ts | 14 ++ src/utils/exportImport.ts | 159 +++++++++++++++ 10 files changed, 469 insertions(+), 48 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 1cc4aa3..c75f6ab 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -24,6 +24,8 @@ import { Button } from './components/ui/button'; import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from './components/ui/tooltip'; import { IconButtonWithTooltip } from './components/ui/icon-button-with-tooltip'; import { PROJECT_REPOSITORY_URL, APP_VERSION } from './constants/defaults'; +import { deleteSelectedData } from './utils/exportImport'; +import type { ExportOptions } from './utils/exportImport'; // Custom Hooks import { useAppState } from './hooks/useAppState'; @@ -74,7 +76,6 @@ const MedPlanAssistant = () => { updateState, updateNestedState, updateUiSetting, - handleReset, addDay, removeDay, addDoseToDay, @@ -135,6 +136,29 @@ const MedPlanAssistant = () => { templateProfile } = useSimulation(appState); + // Handle data deletion + const handleDeleteData = (options: ExportOptions) => { + const newState = deleteSelectedData(appState, options); + + // Apply all state updates + Object.entries(newState).forEach(([key, value]) => { + if (key === 'days') { + updateState('days', value as any); + } else if (key === 'pkParams') { + updateState('pkParams', value as any); + } else if (key === 'therapeuticRange') { + updateState('therapeuticRange', value as any); + } else if (key === 'doseIncrement') { + updateState('doseIncrement', value as any); + } else if (key === 'uiSettings') { + // Update UI settings individually + Object.entries(value as any).forEach(([uiKey, uiValue]) => { + updateUiSetting(uiKey as any, uiValue); + }); + } + }); + }; + return (
@@ -163,6 +187,7 @@ const MedPlanAssistant = () => { onUpdateTherapeuticRange={(key: any, value: any) => updateNestedState('therapeuticRange', key, value)} onUpdateUiSetting={(key: any, value: any) => updateUiSetting(key as any, value)} onImportDays={(importedDays: any) => updateState('days', importedDays)} + onDeleteData={handleDeleteData} />
{ onUpdatePkParams={(key: any, value: any) => updateNestedState('pkParams', key, value)} onUpdateTherapeuticRange={(key: any, value: any) => updateNestedState('therapeuticRange', key, value)} onUpdateUiSetting={updateUiSetting} - onReset={handleReset} onImportDays={(importedDays: any) => updateState('days', importedDays)} onOpenDataManagement={() => setShowDataManagement(true)} t={t} diff --git a/src/components/data-management-modal.tsx b/src/components/data-management-modal.tsx index f0f34fc..a0586b5 100644 --- a/src/components/data-management-modal.tsx +++ b/src/components/data-management-modal.tsx @@ -21,6 +21,7 @@ import { Switch } from './ui/switch'; import { Separator } from './ui/separator'; import { Textarea } from './ui/textarea'; import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip'; +import { Trash2 } from 'lucide-react'; import { Popover, PopoverContent, @@ -52,6 +53,7 @@ interface ExportImportOptions { includeSimulationSettings: boolean; includePharmacoSettings: boolean; includeAdvancedSettings: boolean; + includeOtherData: boolean; } interface DataManagementModalProps { @@ -69,6 +71,7 @@ interface DataManagementModalProps { onUpdateTherapeuticRange: (key: string, value: any) => void; onUpdateUiSetting: (key: string, value: any) => void; onImportDays?: (days: any) => void; + onDeleteData?: (options: ExportImportOptions) => void; } const DataManagementModal: React.FC = ({ @@ -84,6 +87,7 @@ const DataManagementModal: React.FC = ({ onUpdateTherapeuticRange, onUpdateUiSetting, onImportDays, + onDeleteData, }) => { // Export/Import options const [exportOptions, setExportOptions] = useState({ @@ -92,6 +96,7 @@ const DataManagementModal: React.FC = ({ includeSimulationSettings: true, includePharmacoSettings: true, includeAdvancedSettings: true, + includeOtherData: false, }); const [importOptions, setImportOptions] = useState({ @@ -100,6 +105,17 @@ const DataManagementModal: React.FC = ({ includeSimulationSettings: true, includePharmacoSettings: true, includeAdvancedSettings: true, + includeOtherData: false, + }); + + // Deletion options - defaults: all except otherData + const [deletionOptions, setDeletionOptions] = useState({ + includeSchedules: true, + includeDiagramSettings: true, + includeSimulationSettings: true, + includePharmacoSettings: true, + includeAdvancedSettings: true, + includeOtherData: true, }); // File upload state @@ -445,6 +461,40 @@ const DataManagementModal: React.FC = ({ } }; + // Handle delete selected data + const handleDeleteData = () => { + const hasAnySelected = Object.values(deletionOptions).some(v => v); + if (!hasAnySelected) { + alert(t('deleteNoOptionsSelected')); + return; + } + + // Build confirmation message listing what will be deleted + const categoriesToDelete = []; + if (deletionOptions.includeSchedules) categoriesToDelete.push(t('exportOptionSchedules')); + if (deletionOptions.includeDiagramSettings) categoriesToDelete.push(t('exportOptionDiagram')); + if (deletionOptions.includeSimulationSettings) categoriesToDelete.push(t('exportOptionSimulation')); + if (deletionOptions.includePharmacoSettings) categoriesToDelete.push(t('exportOptionPharmaco')); + if (deletionOptions.includeAdvancedSettings) categoriesToDelete.push(t('exportOptionAdvanced')); + if (deletionOptions.includeOtherData) categoriesToDelete.push(t('exportOptionOtherData')); + + const confirmMessage = + t('deleteDataConfirmTitle') + '\n\n' + + categoriesToDelete.map(cat => `• ${cat}`).join('\n') + '\n\n' + + t('deleteDataConfirmWarning'); + + if (!window.confirm(confirmMessage)) { + return; + } + + // Call deletion handler + if (onDeleteData) { + onDeleteData(deletionOptions); + alert(t('deleteDataSuccess')); + onClose(); + } + }; + return (
@@ -542,6 +592,31 @@ const DataManagementModal: React.FC = ({ {t('exportOptionAdvanced')}
+
+ + setExportOptions({ ...exportOptions, includeOtherData: checked }) + } + /> + + + + + + +

{t('exportOptionOtherDataTooltip')}

+
+
+
@@ -647,6 +722,31 @@ const DataManagementModal: React.FC = ({ {t('exportOptionAdvanced')}
+
+ + setImportOptions({ ...importOptions, includeOtherData: checked }) + } + /> + + + + + + +

{t('exportOptionOtherDataTooltip')}

+
+
+
@@ -791,22 +891,138 @@ const DataManagementModal: React.FC = ({ )} + {/* Apply Import Button - directly below JSON editor without separator */} + + - {/* Action Buttons */} -
+ {/* Delete Specific Data Section */} +
+
+
+ +
+

{t('deleteSpecificData')}

+ + + + + +

{t('deleteSpecificDataTooltip')}

+
+
+
+ + {/* Warning Message */} +
+

{t('deleteDataWarning')}

+
+ +
+ +
+
+ + setDeletionOptions({ ...deletionOptions, includeSchedules: checked }) + } + /> + +
+
+ + setDeletionOptions({ ...deletionOptions, includeDiagramSettings: checked }) + } + /> + +
+
+ + setDeletionOptions({ ...deletionOptions, includeSimulationSettings: checked }) + } + /> + +
+
+ + setDeletionOptions({ ...deletionOptions, includePharmacoSettings: checked }) + } + /> + +
+
+ + setDeletionOptions({ ...deletionOptions, includeAdvancedSettings: checked }) + } + /> + +
+
+ + setDeletionOptions({ ...deletionOptions, includeOtherData: checked }) + } + /> + +
+
+
+ + {/* Delete Button */} -
+ + {/* Close Button */} +
diff --git a/src/components/settings.tsx b/src/components/settings.tsx index 7ec42ed..15099dd 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -116,7 +116,6 @@ const Settings = ({ onUpdatePkParams, onUpdateTherapeuticRange, onUpdateUiSetting, - onReset, onImportDays, onOpenDataManagement, t @@ -458,6 +457,8 @@ const Settings = ({ unit={t('unitDays')} required={true} errorMessage={t('errorNumberRequired')} + showResetButton={true} + defaultValue="2" /> @@ -490,7 +491,8 @@ const Settings = ({ max={500} placeholder={t('auto')} allowEmpty={true} - clearButton={true} + showResetButton={true} + defaultValue="" warning={!!yAxisRangeError} warningMessage={yAxisRangeError} /> @@ -504,7 +506,8 @@ const Settings = ({ placeholder={t('auto')} unit="ng/ml" allowEmpty={true} - clearButton={true} + showResetButton={true} + defaultValue="" warning={!!yAxisRangeError} warningMessage={yAxisRangeError} /> @@ -598,6 +601,8 @@ const Settings = ({ unit={t('unitDays')} required={true} errorMessage={t('errorNumberRequired')} + showResetButton={true} + defaultValue="5" /> @@ -649,6 +654,8 @@ const Settings = ({ max={7} unit={t('unitDays')} required={true} + showResetButton={true} + defaultValue="7" /> )} @@ -699,6 +706,8 @@ const Settings = ({ error={eliminationExtreme} warningMessage={t('warningEliminationOutOfRange')} errorMessage={t('errorEliminationHalfLifeRequired')} + showResetButton={true} + defaultValue="11" /> @@ -736,6 +745,8 @@ const Settings = ({ warning={conversionWarning} warningMessage={t('warningConversionOutOfRange')} errorMessage={t('errorConversionHalfLifeRequired')} + showResetButton={true} + defaultValue="0.8" /> @@ -1144,16 +1155,6 @@ const Settings = ({ > {t('openDataManagement')} - - {/* Reset Button - Always Visible */} - ); }; diff --git a/src/components/simulation-chart.tsx b/src/components/simulation-chart.tsx index ba52880..15e8f83 100644 --- a/src/components/simulation-chart.tsx +++ b/src/components/simulation-chart.tsx @@ -467,8 +467,8 @@ const SimulationChart = ({ // FIXME //label={{ value: t('axisLabelConcentration'), angle: -90, position: 'insideLeft', style: { fontStyle: 'italic', color: '#666' } }} domain={yAxisDomain as any} - tickCount={20} - interval={1} + tickCount={16} + interval={0} allowDecimals={false} allowDataOverflow={false} /> diff --git a/src/components/ui/form-numeric-input.tsx b/src/components/ui/form-numeric-input.tsx index 7fafbab..9e19316 100644 --- a/src/components/ui/form-numeric-input.tsx +++ b/src/components/ui/form-numeric-input.tsx @@ -9,7 +9,7 @@ */ import * as React from "react" -import { Minus, Plus, X } from "lucide-react" +import { Minus, Plus, RotateCcw } from "lucide-react" import { Button } from "./button" import { IconButtonWithTooltip } from "./icon-button-with-tooltip" import { Input } from "./input" @@ -25,7 +25,8 @@ interface NumericInputProps extends Omit( unit, align = 'right', allowEmpty = false, - clearButton = false, + showResetButton = false, + defaultValue, error = false, warning = false, required = false, @@ -217,7 +219,7 @@ const FormNumericInput = React.forwardRef( size="icon" className={cn( "h-9 w-9", - clearButton && allowEmpty ? "rounded-l-none rounded-r-none border-x-0" : "rounded-l-none border-l-0", + showResetButton ? "rounded-l-none rounded-r-none border-x-0" : "rounded-l-none border-l-0", hasError && "border-destructive", hasWarning && !hasError && "border-yellow-500" )} @@ -226,11 +228,11 @@ const FormNumericInput = React.forwardRef( > - {clearButton && allowEmpty && ( + {showResetButton && ( } - tooltip={t('buttonClear')} + icon={} + tooltip={t('buttonResetToDefault')} variant="outline" size="icon" className={cn( @@ -238,7 +240,7 @@ const FormNumericInput = React.forwardRef( hasError && "border-destructive", hasWarning && !hasError && "border-yellow-500" )} - onClick={() => onChange('')} + onClick={() => onChange(String(defaultValue ?? ''))} tabIndex={-1} /> )} diff --git a/src/constants/defaults.ts b/src/constants/defaults.ts index 38fb74c..8d42746 100644 --- a/src/constants/defaults.ts +++ b/src/constants/defaults.ts @@ -151,15 +151,14 @@ export const getDefaultState = (): AppState => ({ id: 'day-template', isTemplate: true, doses: [ - { id: 'dose-1', time: '06:30', ldx: '20' }, - { id: 'dose-2', time: '12:30', ldx: '10' }, - { id: 'dose-3', time: '17:30', ldx: '10' }, - { id: 'dose-4', time: '22:00', ldx: '7.5' }, + { id: 'dose-1', time: '06:30', ldx: '25' }, + { id: 'dose-2', time: '14:30', ldx: '15' }, + { id: 'dose-4', time: '22:15', ldx: '15' }, ] } ], steadyStateConfig: { daysOnMedication: '7' }, // kept for backwards compatibility, now sourced from pkParams.advanced - therapeuticRange: { min: '10', max: '120' }, // min for adults and max for children for maximum range (users should personalize based on their response) + therapeuticRange: { min: '', max: '' }, // users should personalize based on their response doseIncrement: '2.5', uiSettings: { showDayTimeOnXAxis: '24h', diff --git a/src/hooks/useAppState.ts b/src/hooks/useAppState.ts index f569f9e..538f8eb 100644 --- a/src/hooks/useAppState.ts +++ b/src/hooks/useAppState.ts @@ -311,13 +311,6 @@ export const useAppState = () => { })); }; - const handleReset = () => { - if (window.confirm("Bist du sicher, dass du alle Einstellungen auf die Standardwerte zurücksetzen möchtest? Dies kann nicht rückgängig gemacht werden.")) { - window.localStorage.removeItem(LOCAL_STORAGE_KEY); - window.location.reload(); - } - }; - return { appState, isLoaded, @@ -331,7 +324,6 @@ export const useAppState = () => { removeDoseFromDay, updateDoseInDay, updateDoseFieldInDay, - sortDosesInDay, - handleReset + sortDosesInDay }; }; diff --git a/src/locales/de.ts b/src/locales/de.ts index dbd2538..6e7d1ea 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -210,6 +210,8 @@ export const de = { exportOptionSimulation: "Simulations-Einstellungen (Dauer, Bereich, Diagrammansicht)", exportOptionPharmaco: "Pharmakokinetik-Einstellungen (Halbwertszeiten, therapeutischer Bereich)", exportOptionAdvanced: "Erweiterte Einstellungen (Gewicht, Nahrung, pH, Bioverfügbarkeit)", + exportOptionOtherData: "Andere Daten (Design, eingeklappte Karten, Sprache, Haftungsausschluss)", + exportOptionOtherDataTooltip: "UI-Präferenzen wie Design, eingeklappte Kartenstatus, Spracheinstellung und Haftungsausschluss-Bestätigung. Normalerweise nicht nötig beim Teilen von Plänen mit anderen.", exportButton: "Backup-Datei herunterladen", importButton: "Datei zum Importieren wählen", importApplyButton: "Import anwenden", @@ -254,12 +256,24 @@ export const de = { closeDataManagement: "Schließen", pasteContentTooLarge: "Inhalt zu groß (max. 5000 Zeichen)", + // Delete Data + deleteSpecificData: "Spezifische Daten löschen", + deleteSpecificDataTooltip: "Ausgewählte Datenkategorien dauerhaft von Ihrem Gerät löschen. Dieser Vorgang kann nicht rückgängig gemacht werden.", + deleteSelectWhat: "Was möchtest du löschen:", + deleteDataWarning: "⚠️ Warnung: Das Löschen ist dauerhaft und kann nicht rückgängig gemacht werden. Gelöschte Daten werden auf Standardwerte zurückgesetzt.", + deleteDataButton: "Ausgewählte Daten löschen", + deleteNoOptionsSelected: "Bitte wähle mindestens eine Kategorie zum Löschen aus.", + deleteDataConfirmTitle: "Bist du sicher, dass du die folgenden Daten dauerhaft löschen möchtest?", + deleteDataConfirmWarning: "Diese Aktion kann nicht rückgängig gemacht werden. Gelöschte Daten werden auf Werkseinstellungen zurückgesetzt.", + deleteDataSuccess: "Ausgewählte Daten wurden erfolgreich gelöscht.", + // Footer disclaimer importantNote: "Wichtiger Hinweis", disclaimer: "Dieses Tool dient ausschließlich zu Illustrations- und Informationszwecken. Es ist kein medizinisches Gerät und ersetzt nicht die Beratung durch einen Arzt oder Apotheker. Alle Berechnungen sind Simulationen, die auf allgemeinen pharmakokinetischen Modellen basieren und von individuellen Faktoren erheblich abweichen können. Bitte konsultiere deinen behandelnden Arzt, bevor du Anpassungen an deiner Medikation vornimmst.", // Number input field buttonClear: "Feld löschen", + buttonResetToDefault: "Auf Standard zurücksetzen", // Field validation - Errors errorNumberRequired: "⛔ Bitte gib eine gültige Zahl ein.", diff --git a/src/locales/en.ts b/src/locales/en.ts index 87eacb7..ae91308 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -208,6 +208,8 @@ export const en = { exportOptionSimulation: "Simulation Settings (Duration, range, chart view)", exportOptionPharmaco: "Pharmacokinetic Settings (Half-lives, therapeutic range)", exportOptionAdvanced: "Advanced Settings (Weight, food, pH, bioavailability)", + exportOptionOtherData: "Other Data (Theme, collapsed cards, language, disclaimer)", + exportOptionOtherDataTooltip: "UI preferences like theme, collapsed card states, language preference, and disclaimer acceptance. Typically not needed when sharing plans with others.", exportButton: "Download Backup File", importButton: "Choose File to Import", importApplyButton: "Apply Import", @@ -252,12 +254,24 @@ export const en = { closeDataManagement: "Close", pasteContentTooLarge: "Content too large (max. 5000 characters)", + // Delete Data + deleteSpecificData: "Delete Specific Data", + deleteSpecificDataTooltip: "Permanently delete selected data categories from your device. This operation cannot be undone.", + deleteSelectWhat: "Select what to delete:", + deleteDataWarning: "⚠️ Warning: Deletion is permanent and cannot be undone. Deleted data will be reset to default values.", + deleteDataButton: "Delete Selected Data", + deleteNoOptionsSelected: "Please select at least one category to delete.", + deleteDataConfirmTitle: "Are you sure you want to permanently delete the following data?", + deleteDataConfirmWarning: "This action cannot be undone. Deleted data will be reset to factory defaults.", + deleteDataSuccess: "Selected data has been deleted successfully.", + // Footer disclaimer importantNote: "Important Notice", disclaimer: "This tool is for illustration and information purposes only. It is not a medical device and does not replace consultation with a doctor or pharmacist. All calculations are simulations based on general pharmacokinetic models and may differ significantly from individual factors. Please consult your treating physician before making adjustments to your medication.", // Number input field buttonClear: "Clear field", + buttonResetToDefault: "Reset to default", // Field validation - Errors errorNumberRequired: "⛔ Please enter a valid number.", diff --git a/src/utils/exportImport.ts b/src/utils/exportImport.ts index 608c3b4..921d227 100644 --- a/src/utils/exportImport.ts +++ b/src/utils/exportImport.ts @@ -37,6 +37,13 @@ export interface ExportData { doseIncrement: AppState['doseIncrement']; }; advancedSettings?: AppState['pkParams']['advanced']; + otherData?: { + theme?: AppState['uiSettings']['theme']; + settingsCardStates?: any; + dayScheduleCollapsedStates?: any; + language?: string; + disclaimerAccepted?: boolean; + }; }; } @@ -46,6 +53,7 @@ export interface ExportOptions { includeSimulationSettings: boolean; includePharmacoSettings: boolean; includeAdvancedSettings: boolean; + includeOtherData: boolean; } export interface ImportValidationResult { @@ -111,6 +119,21 @@ export const exportSettings = ( exportData.data.advancedSettings = appState.pkParams.advanced; } + if (options.includeOtherData) { + const settingsCardStates = localStorage.getItem('settingsCardStates_v1'); + const dayScheduleCollapsedStates = localStorage.getItem('dayScheduleCollapsedDays_v1'); + const language = localStorage.getItem('medPlanAssistant_language'); + const disclaimerAccepted = localStorage.getItem('medPlanDisclaimerAccepted_v1'); + + exportData.data.otherData = { + theme: appState.uiSettings.theme, + settingsCardStates: settingsCardStates ? JSON.parse(settingsCardStates) : undefined, + dayScheduleCollapsedStates: dayScheduleCollapsedStates ? JSON.parse(dayScheduleCollapsedStates) : undefined, + language: language || undefined, + disclaimerAccepted: disclaimerAccepted === 'true', + }; + } + return exportData; }; @@ -228,6 +251,17 @@ export const validateImportData = (data: any): ImportValidationResult => { } } + // Validate other data + if (importData.otherData !== undefined) { + const validFields = ['theme', 'settingsCardStates', 'dayScheduleCollapsedStates', 'language', 'disclaimerAccepted']; + const importedFields = Object.keys(importData.otherData); + const unknownFields = importedFields.filter(f => !validFields.includes(f)); + if (unknownFields.length > 0) { + result.warnings.push(`Other data: Unknown fields found (${unknownFields.join(', ')})`); + result.hasUnknownFields = true; + } + } + return result; }; @@ -295,6 +329,131 @@ export const importSettings = ( }; } + if (options.includeOtherData && importData.otherData) { + // Update theme in uiSettings + if (importData.otherData.theme !== undefined) { + if (!newState.uiSettings) { + newState.uiSettings = { ...currentState.uiSettings }; + } + newState.uiSettings.theme = importData.otherData.theme; + } + + // Update localStorage-only settings + if (importData.otherData.settingsCardStates !== undefined) { + localStorage.setItem('settingsCardStates_v1', JSON.stringify(importData.otherData.settingsCardStates)); + } + if (importData.otherData.dayScheduleCollapsedStates !== undefined) { + localStorage.setItem('dayScheduleCollapsedDays_v1', JSON.stringify(importData.otherData.dayScheduleCollapsedStates)); + } + if (importData.otherData.language !== undefined) { + localStorage.setItem('medPlanAssistant_language', importData.otherData.language); + } + if (importData.otherData.disclaimerAccepted !== undefined) { + localStorage.setItem('medPlanDisclaimerAccepted_v1', importData.otherData.disclaimerAccepted ? 'true' : 'false'); + } + } + + return newState; +}; + +/** + * Delete selected data categories from localStorage and return updated state + * @param currentState Current application state + * @param options Which categories to delete + * @returns Partial state with defaults for deleted categories + */ +export const deleteSelectedData = ( + currentState: AppState, + options: ExportOptions +): Partial => { + const defaults = getDefaultState(); + const newState: Partial = {}; + + // Track if main localStorage should be removed + let shouldRemoveMainStorage = false; + + if (options.includeSchedules) { + // Delete schedules - but always keep template day with at least one dose + // Never allow complete deletion as this breaks the app + const defaults = getDefaultState(); + newState.days = [ + { + id: 'day-template', + isTemplate: true, + doses: [ + { id: 'dose-default', time: '06:00', ldx: '70' } + ] + } + ]; + shouldRemoveMainStorage = true; + } + + if (options.includeDiagramSettings) { + if (!newState.uiSettings) { + newState.uiSettings = { ...currentState.uiSettings }; + } + // Reset diagram settings to defaults + newState.uiSettings.showDayTimeOnXAxis = defaults.uiSettings.showDayTimeOnXAxis; + newState.uiSettings.showTemplateDay = defaults.uiSettings.showTemplateDay; + newState.uiSettings.showDayReferenceLines = defaults.uiSettings.showDayReferenceLines; + newState.uiSettings.showTherapeuticRange = defaults.uiSettings.showTherapeuticRange; + newState.uiSettings.stickyChart = defaults.uiSettings.stickyChart; + shouldRemoveMainStorage = true; + } + + if (options.includeSimulationSettings) { + if (!newState.uiSettings) { + newState.uiSettings = { ...currentState.uiSettings }; + } + // Reset simulation settings to defaults + newState.uiSettings.simulationDays = defaults.uiSettings.simulationDays; + newState.uiSettings.displayedDays = defaults.uiSettings.displayedDays; + newState.uiSettings.yAxisMin = defaults.uiSettings.yAxisMin; + newState.uiSettings.yAxisMax = defaults.uiSettings.yAxisMax; + newState.uiSettings.chartView = defaults.uiSettings.chartView; + newState.uiSettings.steadyStateDaysEnabled = defaults.uiSettings.steadyStateDaysEnabled; + shouldRemoveMainStorage = true; + } + + if (options.includePharmacoSettings) { + // Reset pharmacokinetic settings to defaults + newState.pkParams = { + ...currentState.pkParams, + ldx: defaults.pkParams.ldx, + damph: defaults.pkParams.damph, + }; + newState.therapeuticRange = defaults.therapeuticRange; + newState.doseIncrement = defaults.doseIncrement; + shouldRemoveMainStorage = true; + } + + if (options.includeAdvancedSettings) { + if (!newState.pkParams) { + newState.pkParams = { ...currentState.pkParams }; + } + // Reset advanced settings to defaults + newState.pkParams.advanced = defaults.pkParams.advanced; + shouldRemoveMainStorage = true; + } + + if (options.includeOtherData) { + // Reset theme to default + if (!newState.uiSettings) { + newState.uiSettings = { ...currentState.uiSettings }; + } + newState.uiSettings.theme = defaults.uiSettings.theme; + + // Remove UI state from localStorage + localStorage.removeItem('settingsCardStates_v1'); + localStorage.removeItem('dayScheduleCollapsedDays_v1'); + localStorage.removeItem('medPlanAssistant_language'); + localStorage.removeItem('medPlanDisclaimerAccepted_v1'); + shouldRemoveMainStorage = true; + } + + // If any main state category was deleted, we'll trigger a save by returning the partial state + // The useAppState hook will handle saving to localStorage + return newState; };