Files
med-plan-assistant/src/App.tsx

157 lines
4.8 KiB
TypeScript

/**
* Medication Plan Assistant - Main Application
*
* A pharmacokinetic simulation tool for lisdexamfetamine (Elvanse/Vyvanse)
* medication planning. Helps users visualize drug concentration profiles,
* manage deviations, and get dose correction suggestions.
*
* @author Andreas Weyer
* @license MIT
*/
import React from 'react';
// Components
import DaySchedule from './components/day-schedule';
import SimulationChart from './components/simulation-chart';
import Settings from './components/settings';
import LanguageSelector from './components/language-selector';
import { Button } from './components/ui/button';
// Custom Hooks
import { useAppState } from './hooks/useAppState';
import { useSimulation } from './hooks/useSimulation';
import { useLanguage } from './hooks/useLanguage';
// --- Main Component ---
const MedPlanAssistant = () => {
const { currentLanguage, t, changeLanguage } = useLanguage();
const {
appState,
updateNestedState,
updateUiSetting,
handleReset,
addDay,
removeDay,
addDoseToDay,
removeDoseFromDay,
updateDoseInDay
} = useAppState();
const {
pkParams,
days,
therapeuticRange,
doseIncrement,
uiSettings
} = appState;
const {
showDayTimeOnXAxis,
chartView,
yAxisMin,
yAxisMax,
showTemplateDay,
simulationDays,
displayedDays
} = uiSettings;
const {
combinedProfile,
templateProfile
} = useSimulation(appState);
return (
<div className="min-h-screen bg-background p-4 sm:p-6 lg:p-8">
<div className="max-w-7xl mx-auto">
<header className="mb-8">
<div className="flex justify-between items-start">
<div>
<h1 className="text-3xl md:text-4xl font-bold tracking-tight">{t.appTitle}</h1>
<p className="text-muted-foreground mt-1">{t.appSubtitle}</p>
</div>
<LanguageSelector currentLanguage={currentLanguage} onLanguageChange={changeLanguage} t={t} />
</div>
</header>
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6">
{/* Both Columns - Chart */}
<div className="xl:col-span-2 bg-card p-6 rounded-lg border min-h-[600px] flex flex-col">
<div className="flex justify-center gap-2 mb-4">
<Button
onClick={() => updateUiSetting('chartView', 'damph')}
variant={chartView === 'damph' ? 'default' : 'secondary'}
>
{t.dAmphetamine}
</Button>
<Button
onClick={() => updateUiSetting('chartView', 'ldx')}
variant={chartView === 'ldx' ? 'default' : 'secondary'}
>
{t.lisdexamfetamine}
</Button>
<Button
onClick={() => updateUiSetting('chartView', 'both')}
variant={chartView === 'both' ? 'default' : 'secondary'}
>
{t.both}
</Button>
</div>
<SimulationChart
combinedProfile={combinedProfile}
templateProfile={showTemplateDay ? templateProfile : null}
chartView={chartView}
showDayTimeOnXAxis={showDayTimeOnXAxis}
therapeuticRange={therapeuticRange}
simulationDays={simulationDays}
displayedDays={displayedDays}
yAxisMin={yAxisMin}
yAxisMax={yAxisMax}
t={t}
/>
</div>
{/* Left Column - Controls */}
<div className="xl:col-span-1 space-y-6">
<DaySchedule
days={days}
doseIncrement={doseIncrement}
onAddDay={addDay}
onRemoveDay={removeDay}
onAddDose={addDoseToDay}
onRemoveDose={removeDoseFromDay}
onUpdateDose={updateDoseInDay}
t={t}
/>
</div>
{/* Right Column - Settings */}
<div className="xl:col-span-1 space-y-6">
<Settings
pkParams={pkParams}
therapeuticRange={therapeuticRange}
uiSettings={uiSettings}
onUpdatePkParams={(key: any, value: any) => updateNestedState('pkParams', key, value)}
onUpdateTherapeuticRange={(key: any, value: any) => updateNestedState('therapeuticRange', key, value)}
onUpdateUiSetting={updateUiSetting}
onReset={handleReset}
t={t}
/>
</div>
</div>
<footer className="mt-8 p-4 bg-muted rounded-lg text-sm text-muted-foreground border">
<h3 className="font-semibold mb-2 text-foreground">{t.importantNote}</h3>
<p>{t.disclaimer}</p>
</footer>
</div>
</div>
);
};
export default MedPlanAssistant;