Update migrated js to ts and shadcn
This commit is contained in:
186
src/components/simulation-chart.tsx
Normal file
186
src/components/simulation-chart.tsx
Normal file
@@ -0,0 +1,186 @@
|
||||
import React from 'react';
|
||||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ReferenceLine, ResponsiveContainer } from 'recharts';
|
||||
|
||||
const SimulationChart = ({
|
||||
idealProfile,
|
||||
deviatedProfile,
|
||||
correctedProfile,
|
||||
chartView,
|
||||
showDayTimeOnXAxis,
|
||||
therapeuticRange,
|
||||
simulationDays,
|
||||
displayedDays,
|
||||
yAxisMin,
|
||||
yAxisMax,
|
||||
t
|
||||
}: any) => {
|
||||
const totalHours = (parseInt(simulationDays, 10) || 3) * 24;
|
||||
|
||||
// Generate ticks for continuous time axis (every 6 hours)
|
||||
const chartTicks = React.useMemo(() => {
|
||||
const ticks = [];
|
||||
for (let i = 0; i <= totalHours; i += 6) {
|
||||
ticks.push(i);
|
||||
}
|
||||
return ticks;
|
||||
}, [totalHours]);
|
||||
|
||||
const chartWidthPercentage = Math.max(100, (totalHours / ( (parseInt(displayedDays, 10) || 2) * 25)) * 100);
|
||||
|
||||
const chartDomain = React.useMemo(() => {
|
||||
const numMin = parseFloat(yAxisMin);
|
||||
const numMax = parseFloat(yAxisMax);
|
||||
const domainMin = !isNaN(numMin) ? numMin : 'auto';
|
||||
const domainMax = !isNaN(numMax) ? numMax : 'auto';
|
||||
return [domainMin, domainMax];
|
||||
}, [yAxisMin, yAxisMax]);
|
||||
|
||||
return (
|
||||
<div className="flex-grow w-full overflow-x-auto">
|
||||
<div style={{ width: `${chartWidthPercentage}%`, height: '100%', minWidth: '100%' }}>
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart margin={{ top: 20, right: 20, left: 0, bottom: 5 }}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis
|
||||
dataKey="timeHours"
|
||||
type="number"
|
||||
domain={[0, totalHours]}
|
||||
ticks={chartTicks}
|
||||
tickFormatter={(h) => {
|
||||
if (showDayTimeOnXAxis) {
|
||||
// Show 24h repeating format (0-23h)
|
||||
return `${h % 24}${t.hour}`;
|
||||
} else {
|
||||
// Show continuous time (0, 6, 12, 18, 24, 30, 36, ...)
|
||||
return `${h}${t.hour}`;
|
||||
}
|
||||
}}
|
||||
xAxisId="hours"
|
||||
/>
|
||||
<YAxis
|
||||
label={{ value: t.concentration, angle: -90, position: 'insideLeft', offset: -10 }}
|
||||
domain={chartDomain as any}
|
||||
allowDecimals={false}
|
||||
/>
|
||||
<Tooltip
|
||||
formatter={(value: any, name) => [`${typeof value === 'number' ? value.toFixed(1) : value} ${t.ngml}`, name]}
|
||||
labelFormatter={(label) => `${t.hour.replace('h', 'Hour')}: ${label}${t.hour}`}
|
||||
/>
|
||||
<Legend verticalAlign="top" height={36} />
|
||||
|
||||
{(chartView === 'damph' || chartView === 'both') && (
|
||||
<ReferenceLine
|
||||
y={parseFloat(therapeuticRange.min) || 0}
|
||||
label={{ value: t.min, position: 'insideTopLeft' }}
|
||||
stroke="green"
|
||||
strokeDasharray="3 3"
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)}
|
||||
{(chartView === 'damph' || chartView === 'both') && (
|
||||
<ReferenceLine
|
||||
y={parseFloat(therapeuticRange.max) || 0}
|
||||
label={{ value: t.max, position: 'insideTopLeft' }}
|
||||
stroke="red"
|
||||
strokeDasharray="3 3"
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)}
|
||||
|
||||
{[...Array(parseInt(simulationDays, 10) || 0).keys()].map(day => (
|
||||
day > 0 && (
|
||||
<ReferenceLine
|
||||
key={day}
|
||||
x={day * 24}
|
||||
stroke="#999"
|
||||
strokeDasharray="5 5"
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)
|
||||
))}
|
||||
|
||||
{(chartView === 'damph' || chartView === 'both') && (
|
||||
<Line
|
||||
type="monotone"
|
||||
data={idealProfile}
|
||||
dataKey="damph"
|
||||
name={`${t.dAmphetamine} (Ideal)`}
|
||||
stroke="#3b82f6"
|
||||
strokeWidth={2.5}
|
||||
dot={false}
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)}
|
||||
{(chartView === 'ldx' || chartView === 'both') && (
|
||||
<Line
|
||||
type="monotone"
|
||||
data={idealProfile}
|
||||
dataKey="ldx"
|
||||
name={`${t.lisdexamfetamine} (Ideal)`}
|
||||
stroke="#8b5cf6"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
strokeDasharray="3 3"
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)}
|
||||
|
||||
{deviatedProfile && (chartView === 'damph' || chartView === 'both') && (
|
||||
<Line
|
||||
type="monotone"
|
||||
data={deviatedProfile}
|
||||
dataKey="damph"
|
||||
name={`${t.dAmphetamine} (Deviation)`}
|
||||
stroke="#f59e0b"
|
||||
strokeWidth={2}
|
||||
strokeDasharray="5 5"
|
||||
dot={false}
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)}
|
||||
{deviatedProfile && (chartView === 'ldx' || chartView === 'both') && (
|
||||
<Line
|
||||
type="monotone"
|
||||
data={deviatedProfile}
|
||||
dataKey="ldx"
|
||||
name={`${t.lisdexamfetamine} (Deviation)`}
|
||||
stroke="#f97316"
|
||||
strokeWidth={1.5}
|
||||
strokeDasharray="5 5"
|
||||
dot={false}
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)}
|
||||
|
||||
{correctedProfile && (chartView === 'damph' || chartView === 'both') && (
|
||||
<Line
|
||||
type="monotone"
|
||||
data={correctedProfile}
|
||||
dataKey="damph"
|
||||
name={`${t.dAmphetamine} (Correction)`}
|
||||
stroke="#10b981"
|
||||
strokeWidth={2.5}
|
||||
strokeDasharray="3 7"
|
||||
dot={false}
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)}
|
||||
{correctedProfile && (chartView === 'ldx' || chartView === 'both') && (
|
||||
<Line
|
||||
type="monotone"
|
||||
data={correctedProfile}
|
||||
dataKey="ldx"
|
||||
name={`${t.lisdexamfetamine} (Correction)`}
|
||||
stroke="#059669"
|
||||
strokeWidth={2}
|
||||
strokeDasharray="3 7"
|
||||
dot={false}
|
||||
xAxisId="hours"
|
||||
/>
|
||||
)}
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};export default SimulationChart;
|
||||
Reference in New Issue
Block a user