Update custome translations to i18n and various improvements
This commit is contained in:
@@ -25,6 +25,8 @@ const CHART_COLORS = {
|
||||
correctedLdx: '#059669', // emerald-600 (success, dash-dot)
|
||||
|
||||
// Reference lines
|
||||
regularPlanDivider: '#22c55e', // green-500
|
||||
deviationDayDivider: '#9ca3af', // gray-400
|
||||
therapeuticMin: '#22c55e', // green-500
|
||||
therapeuticMax: '#ef4444', // red-500
|
||||
dayDivider: '#9ca3af', // gray-400
|
||||
@@ -38,6 +40,7 @@ const SimulationChart = ({
|
||||
templateProfile,
|
||||
chartView,
|
||||
showDayTimeOnXAxis,
|
||||
showDayReferenceLines,
|
||||
therapeuticRange,
|
||||
simulationDays,
|
||||
displayedDays,
|
||||
@@ -46,15 +49,27 @@ const SimulationChart = ({
|
||||
t
|
||||
}: any) => {
|
||||
const totalHours = (parseInt(simulationDays, 10) || 3) * 24;
|
||||
const dispDays = parseInt(displayedDays, 10) || 2;
|
||||
|
||||
// Generate ticks for continuous time axis (every 6 hours)
|
||||
// Dynamically calculate tick interval based on displayed days
|
||||
// Aim for ~40-50 pixels per tick for readability
|
||||
const xTickInterval = React.useMemo(() => {
|
||||
// Scale interval with displayed days: 1 day = 1h, 2 days = 2h, 3-4 days = 3h, 5+ days = 6h
|
||||
if (dispDays <= 1) return 1;
|
||||
if (dispDays <= 2) return 2;
|
||||
if (dispDays <= 4) return 3;
|
||||
if (dispDays <= 6) return 4;
|
||||
return 6;
|
||||
}, [dispDays]);
|
||||
|
||||
// Generate ticks for continuous time axis
|
||||
const chartTicks = React.useMemo(() => {
|
||||
const ticks = [];
|
||||
for (let i = 0; i <= totalHours; i += 6) {
|
||||
for (let i = 0; i <= totalHours; i += xTickInterval) {
|
||||
ticks.push(i);
|
||||
}
|
||||
return ticks;
|
||||
}, [totalHours]);
|
||||
}, [totalHours, xTickInterval]);
|
||||
|
||||
const chartDomain = React.useMemo(() => {
|
||||
const numMin = parseFloat(yAxisMin);
|
||||
@@ -107,7 +122,6 @@ const SimulationChart = ({
|
||||
}, []);
|
||||
|
||||
const simDays = parseInt(simulationDays, 10) || 3;
|
||||
const dispDays = parseInt(displayedDays, 10) || 2;
|
||||
|
||||
// Y-axis takes ~80px, scrollable area gets the rest
|
||||
const yAxisWidth = 80;
|
||||
@@ -134,7 +148,7 @@ const SimulationChart = ({
|
||||
{(chartView === 'damph' || chartView === 'both') && (
|
||||
<Line
|
||||
dataKey="combinedDamph"
|
||||
name={`${t.dAmphetamine}`}
|
||||
name={`${t('dAmphetamine')}`}
|
||||
stroke={CHART_COLORS.idealDamph}
|
||||
strokeWidth={2.5}
|
||||
dot={false}
|
||||
@@ -144,7 +158,7 @@ const SimulationChart = ({
|
||||
{(chartView === 'ldx' || chartView === 'both') && (
|
||||
<Line
|
||||
dataKey="combinedLdx"
|
||||
name={`${t.lisdexamfetamine}`}
|
||||
name={`${t('lisdexamfetamine')}`}
|
||||
stroke={CHART_COLORS.idealLdx}
|
||||
strokeWidth={2}
|
||||
strokeDasharray="3 3"
|
||||
@@ -155,7 +169,7 @@ const SimulationChart = ({
|
||||
{templateProfile && (chartView === 'damph' || chartView === 'both') && (
|
||||
<Line
|
||||
dataKey="templateDamph"
|
||||
name={`${t.dAmphetamine} (${t.regularPlan} ${t.continuation || 'continuation'})`}
|
||||
name={`${t('dAmphetamine')} (${t('regularPlan')} ${t('continuation')})`}
|
||||
stroke={CHART_COLORS.idealDamph}
|
||||
strokeWidth={2}
|
||||
strokeDasharray="3 3"
|
||||
@@ -166,7 +180,7 @@ const SimulationChart = ({
|
||||
{templateProfile && (chartView === 'ldx' || chartView === 'both') && (
|
||||
<Line
|
||||
dataKey="templateLdx"
|
||||
name={`${t.lisdexamfetamine} (${t.regularPlan} ${t.continuation || 'continuation'})`}
|
||||
name={`${t('lisdexamfetamine')} (${t('regularPlan')} ${t('continuation')})`}
|
||||
stroke={CHART_COLORS.idealLdx}
|
||||
strokeWidth={1.5}
|
||||
strokeDasharray="3 3"
|
||||
@@ -190,6 +204,8 @@ const SimulationChart = ({
|
||||
syncId="medPlanChart"
|
||||
>
|
||||
<XAxis
|
||||
xAxisId="hours"
|
||||
label={{ value: showDayTimeOnXAxis === 'continuous' ? t('axisLabelHours') : t('axisLabelTimeOfDay'), position: 'insideBottom', offset: -10, style: { fontStyle: 'italic', color: '#666' } }}
|
||||
dataKey="timeHours"
|
||||
type="number"
|
||||
domain={[0, totalHours]}
|
||||
@@ -197,28 +213,35 @@ const SimulationChart = ({
|
||||
tickCount={chartTicks.length}
|
||||
interval={0}
|
||||
tickFormatter={(h) => {
|
||||
if (showDayTimeOnXAxis) {
|
||||
if (showDayTimeOnXAxis === '24h') {
|
||||
// Show 24h repeating format (0-23h)
|
||||
return `${h % 24}${t.hour}`;
|
||||
return `${h % 24}${t('hour')}`;
|
||||
} else if (showDayTimeOnXAxis === '12h') {
|
||||
// Show 12h AM/PM format
|
||||
const hour12 = h % 24;
|
||||
if (hour12 === 12) return t('tickNoon');
|
||||
const displayHour = hour12 === 0 ? 12 : hour12 > 12 ? hour12 - 12 : hour12;
|
||||
const period = hour12 < 12 ? 'a' : 'p';
|
||||
return `${displayHour}${period}`;
|
||||
} else {
|
||||
// Show continuous time (0, 6, 12, 18, 24, 30, 36, ...)
|
||||
return `${h}${t.hour}`;
|
||||
return `${h}`;
|
||||
}
|
||||
}}
|
||||
xAxisId="hours"
|
||||
/>
|
||||
<YAxis
|
||||
yAxisId="concentration"
|
||||
//label={{ value: t.concentration, angle: -90, position: 'insideLeft', offset: -10 }}
|
||||
domain={chartDomain as any}
|
||||
allowDecimals={false}
|
||||
/>
|
||||
yAxisId="concentration"
|
||||
label={{ value: t('axisLabelConcentration'), angle: -90, position: 'insideLeft', offset: '0 -10', style: { fontStyle: 'italic', color: '#666' } }}
|
||||
domain={chartDomain as any}
|
||||
allowDecimals={false}
|
||||
tickCount={20}
|
||||
/>
|
||||
<Tooltip
|
||||
formatter={(value: any, name) => [`${typeof value === 'number' ? value.toFixed(1) : value} ${t.ngml}`, name]}
|
||||
formatter={(value: any, name) => [`${typeof value === 'number' ? value.toFixed(1) : value} ${t('ngml')}`, name]}
|
||||
labelFormatter={(label, payload) => {
|
||||
// Extract timeHours from the payload data point
|
||||
const timeHours = payload?.[0]?.payload?.timeHours ?? label;
|
||||
return `${t.hour.replace('h', 'Hour')}: ${timeHours}${t.hour}`;
|
||||
return `${t('hour').replace('h', 'Hour')}: ${timeHours}${t('hour')}`;
|
||||
}}
|
||||
wrapperStyle={{ pointerEvents: 'none', zIndex: 200 }}
|
||||
allowEscapeViewBox={{ x: false, y: false }}
|
||||
@@ -227,11 +250,29 @@ const SimulationChart = ({
|
||||
/>
|
||||
<CartesianGrid strokeDasharray="1 1" xAxisId="hours" yAxisId="concentration" />
|
||||
|
||||
|
||||
{showDayReferenceLines !== false && [...Array(dispDays).keys()].map(day => (
|
||||
<ReferenceLine
|
||||
key={`day-${day+1}`}
|
||||
x={24 * (day+1)}
|
||||
label={{
|
||||
value: (day === 0 ? t('refLineRegularPlan') : t('refLineDeviatingPlan')) + ' (' + t('refLineDayX', { x: day+1 }) + ')',
|
||||
position: 'insideTopRight',
|
||||
style: {
|
||||
fontSize: '0.75rem',
|
||||
fontStyle: 'italic',
|
||||
fill: day === 0 ? CHART_COLORS.regularPlanDivider : CHART_COLORS.deviationDayDivider
|
||||
}
|
||||
}}
|
||||
stroke={day === 0 ? CHART_COLORS.regularPlanDivider : CHART_COLORS.deviationDayDivider}
|
||||
//strokeDasharray="0 0"
|
||||
xAxisId="hours"
|
||||
yAxisId="concentration"
|
||||
/>
|
||||
))}
|
||||
{(chartView === 'damph' || chartView === 'both') && (
|
||||
<ReferenceLine
|
||||
y={parseFloat(therapeuticRange.min) || 0}
|
||||
label={{ value: t.min, position: 'insideTopLeft' }}
|
||||
label={{ value: t('refLineMin'), position: 'insideTopLeft' }}
|
||||
stroke={CHART_COLORS.therapeuticMin}
|
||||
strokeDasharray="3 3"
|
||||
xAxisId="hours"
|
||||
@@ -241,7 +282,7 @@ const SimulationChart = ({
|
||||
{(chartView === 'damph' || chartView === 'both') && (
|
||||
<ReferenceLine
|
||||
y={parseFloat(therapeuticRange.max) || 0}
|
||||
label={{ value: t.max, position: 'insideTopLeft' }}
|
||||
label={{ value: t('refLineMax'), position: 'insideTopLeft' }}
|
||||
stroke={CHART_COLORS.therapeuticMax}
|
||||
strokeDasharray="3 3"
|
||||
xAxisId="hours"
|
||||
@@ -265,7 +306,7 @@ const SimulationChart = ({
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="combinedDamph"
|
||||
name={`${t.dAmphetamine}`}
|
||||
name={`${t('dAmphetamine')}`}
|
||||
stroke={CHART_COLORS.idealDamph}
|
||||
strokeWidth={2.5}
|
||||
dot={false}
|
||||
@@ -278,7 +319,7 @@ const SimulationChart = ({
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="combinedLdx"
|
||||
name={`${t.lisdexamfetamine}`}
|
||||
name={`${t('lisdexamfetamine')}`}
|
||||
stroke={CHART_COLORS.idealLdx}
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
@@ -293,7 +334,7 @@ const SimulationChart = ({
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="templateDamph"
|
||||
name={`${t.dAmphetamine} (${t.regularPlan} ${t.continuation || 'continuation'})`}
|
||||
name={`${t('dAmphetamine')} (${t('regularPlan')} ${t('continuation')})`}
|
||||
stroke={CHART_COLORS.idealDamph}
|
||||
strokeWidth={2}
|
||||
strokeDasharray="3 3"
|
||||
@@ -308,7 +349,7 @@ const SimulationChart = ({
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="templateLdx"
|
||||
name={`${t.lisdexamfetamine} (${t.regularPlan} ${t.continuation || 'continuation'})`}
|
||||
name={`${t('lisdexamfetamine')} (${t('regularPlan')} ${t('continuation')})`}
|
||||
stroke={CHART_COLORS.idealLdx}
|
||||
strokeWidth={1.5}
|
||||
strokeDasharray="3 3"
|
||||
|
||||
Reference in New Issue
Block a user