Update custome translations to i18n and various improvements

This commit is contained in:
2025-12-03 21:53:04 +00:00
parent a54c729e46
commit 6fb6583ae3
16 changed files with 364 additions and 195 deletions

View File

@@ -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"