Update new check for max daily dose waring and error
This commit is contained in:
@@ -99,13 +99,19 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
||||
// Get template day for comparison
|
||||
const templateDay = days.find(d => d.isTemplate);
|
||||
|
||||
// Calculate daily total
|
||||
const dayTotal = day.doses.reduce((sum, dose) => sum + (parseFloat(dose.ldx) || 0), 0);
|
||||
|
||||
// Check for daily total warnings/errors
|
||||
const isDailyTotalError = dayTotal > 200;
|
||||
const isDailyTotalWarning = !isDailyTotalError && dayTotal > 70;
|
||||
|
||||
// Calculate differences for deviation days
|
||||
let doseCountDiff = 0;
|
||||
let totalMgDiff = 0;
|
||||
|
||||
if (!day.isTemplate && templateDay) {
|
||||
doseCountDiff = day.doses.length - templateDay.doses.length;
|
||||
const dayTotal = day.doses.reduce((sum, dose) => sum + (parseFloat(dose.ldx) || 0), 0);
|
||||
const templateTotal = templateDay.doses.reduce((sum, dose) => sum + (parseFloat(dose.ldx) || 0), 0);
|
||||
totalMgDiff = dayTotal - templateTotal;
|
||||
}
|
||||
@@ -153,7 +159,7 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
||||
>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`text-xs ${doseCountDiff > 0 ? 'bg-blue-100 dark:bg-blue-900/60 dark:text-blue-200' : 'bg-orange-100 dark:bg-orange-900/60 dark:text-orange-200'}`}
|
||||
className={`text-xs ${doseCountDiff > 0 ? 'badge-trend-up' : 'badge-trend-down'}`}
|
||||
>
|
||||
{doseCountDiff > 0 ? <TrendingUp className="h-3 w-3 inline mr-1" /> : <TrendingDown className="h-3 w-3 inline mr-1" />}
|
||||
{day.doses.length} {day.doses.length === 1 ? t('dose') : t('doses')}
|
||||
@@ -180,27 +186,59 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
||||
>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`text-xs ${totalMgDiff > 0 ? 'bg-blue-100 dark:bg-blue-900/60 dark:text-blue-200' : 'bg-orange-100 dark:bg-orange-900/60 dark:text-orange-200'}`}
|
||||
className={`text-xs ${
|
||||
isDailyTotalError
|
||||
? 'badge-error'
|
||||
: isDailyTotalWarning
|
||||
? 'badge-warning'
|
||||
: totalMgDiff > 0
|
||||
? 'badge-trend-up'
|
||||
: 'badge-trend-down'
|
||||
}`}
|
||||
>
|
||||
{totalMgDiff > 0 ? <TrendingUp className="h-3 w-3 inline mr-1" /> : <TrendingDown className="h-3 w-3 inline mr-1" />}
|
||||
{day.doses.reduce((sum, dose) => sum + (parseFloat(dose.ldx) || 0), 0).toFixed(1)} mg
|
||||
{!isDailyTotalError && !isDailyTotalWarning && (totalMgDiff > 0 ? <TrendingUp className="h-3 w-3 inline mr-1" /> : <TrendingDown className="h-3 w-3 inline mr-1" />)}
|
||||
{dayTotal.toFixed(1)} mg
|
||||
</Badge>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p className="text-xs">
|
||||
{totalMgDiff > 0 ? '+' : ''}{totalMgDiff.toFixed(1)} mg {t('comparedToRegularPlan')}
|
||||
{isDailyTotalError
|
||||
? `${t('errorDailyTotalAbove200mg').replace('{{total}}', dayTotal.toFixed(1))}`
|
||||
: isDailyTotalWarning
|
||||
? `${t('warningDailyTotalAbove70mg').replace('{{total}}', dayTotal.toFixed(1))}`
|
||||
: `${totalMgDiff > 0 ? '+' : ''}${totalMgDiff.toFixed(1)} mg ${t('comparedToRegularPlan')}`
|
||||
}
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Badge variant="outline" className="text-xs">
|
||||
{day.doses.reduce((sum, dose) => sum + (parseFloat(dose.ldx) || 0), 0).toFixed(1)} mg
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`text-xs ${
|
||||
isDailyTotalError
|
||||
? 'badge-error'
|
||||
: isDailyTotalWarning
|
||||
? 'badge-warning'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{dayTotal.toFixed(1)} mg
|
||||
</Badge>
|
||||
)}
|
||||
</CollapsibleCardHeader>
|
||||
{!collapsedDays.has(day.id) && (
|
||||
<CardContent className="space-y-3">
|
||||
{/* Daily total warning/error box */}
|
||||
{(isDailyTotalWarning || isDailyTotalError) && (
|
||||
<div className={`p-3 rounded-md text-sm ${isDailyTotalError ? 'error-bg-box' : 'warning-bg-box'}`}>
|
||||
|
||||
{formatText(isDailyTotalError
|
||||
? t('errorDailyTotalAbove200mg').replace('{{total}}', dayTotal.toFixed(1))
|
||||
: t('warningDailyTotalAbove70mg').replace('{{total}}', dayTotal.toFixed(1))
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{/* Dose table header */}
|
||||
<div className="grid grid-cols-[120px_1fr_auto] sm:grid-cols-[120px_1fr_auto_auto] gap-2 text-sm font-medium text-muted-foreground">
|
||||
<div className="flex items-center gap-1">
|
||||
@@ -247,6 +285,23 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
||||
// Check for dose > 70 mg
|
||||
const isHighDose = parseFloat(dose.ldx) > 70;
|
||||
|
||||
// Determine the error/warning message priority:
|
||||
// 1. Daily total error (> 200mg) - ERROR
|
||||
// 2. Daily total warning (> 70mg) - WARNING
|
||||
// 3. Individual dose warning (zero dose or > 70mg) - WARNING
|
||||
let doseErrorMessage;
|
||||
let doseWarningMessage;
|
||||
|
||||
if (isDailyTotalError) {
|
||||
doseErrorMessage = formatText(t('errorDailyTotalAbove200mg').replace('{{total}}', dayTotal.toFixed(1)));
|
||||
} else if (isDailyTotalWarning) {
|
||||
doseWarningMessage = formatText(t('warningDailyTotalAbove70mg').replace('{{total}}', dayTotal.toFixed(1)));
|
||||
} else if (isZeroDose) {
|
||||
doseWarningMessage = formatText(t('warningZeroDose'));
|
||||
} else if (isHighDose) {
|
||||
doseWarningMessage = formatText(t('warningDoseAbove70mg'));
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={dose.id} className="space-y-2">
|
||||
<div className="grid grid-cols-[120px_1fr_auto] sm:grid-cols-[120px_1fr_auto_auto] gap-2 items-center">
|
||||
@@ -266,13 +321,10 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
||||
max={200}
|
||||
//unit="mg"
|
||||
required={true}
|
||||
warning={isZeroDose || isHighDose}
|
||||
errorMessage={formatText(t('errorNumberRequired'))}
|
||||
warningMessage={
|
||||
isZeroDose ? formatText(t('warningZeroDose'))
|
||||
: isHighDose ? formatText(t('warningDoseAbove70mg'))
|
||||
: undefined // should not happen since warning is false
|
||||
}
|
||||
error={isDailyTotalError}
|
||||
warning={isDailyTotalWarning || isZeroDose || isHighDose}
|
||||
errorMessage={doseErrorMessage || formatText(t('errorNumberRequired'))}
|
||||
warningMessage={doseWarningMessage}
|
||||
inputWidth="w-[72px]"
|
||||
/>
|
||||
<div className="flex gap-2 sm:contents">
|
||||
|
||||
@@ -296,6 +296,8 @@ export const de = {
|
||||
warningConversionOutOfRange: "⚠️ Typischer Bereich: 0,7-1,2h. Aktueller Wert könnte außerhalb klinischer Normen liegen.",
|
||||
warningEliminationOutOfRange: "⚠️ Typischer Bereich: 9-12h (normaler pH). Erweiterter Bereich 7-15h (pH-Effekte). Aktueller Wert ist ungewöhnlich.",
|
||||
warningDoseAbove70mg: "⚠️ FDA-zugelassenes Maximum: 70 mg. Höhere Dosen haben keine Sicherheitsdaten und erhöhen kardiovaskuläre Risiken.",
|
||||
warningDailyTotalAbove70mg: "⚠️ **Tagesgesamtdosis überschreitet empfohlenes Maximum.**\\n\\n__FDA-zugelassenes Maximum:__ **70 mg/Tag**.\\nIhre Tagesgesamtdosis: **{{total}} mg**.\\nKonsultieren Sie Ihren Arzt, bevor Sie diese Dosis überschreiten.",
|
||||
errorDailyTotalAbove200mg: "⛔ **Tagesgesamtdosis überschreitet sichere Grenzen erheblich!**\\n\\nIhre Tagesgesamtdosis **{{total}} mg** überschreitet 200 mg/Tag, was **deutlich über FDA-zugelassenen Grenzen** liegt. *Bitte konsultieren Sie Ihren Arzt.*",
|
||||
|
||||
// Day-based schedule
|
||||
regularPlan: "Regulärer Plan",
|
||||
|
||||
@@ -296,6 +296,8 @@ export const en = {
|
||||
warningConversionOutOfRange: "⚠️ Current value may be outside clinical norms.\\n\\n__Typical range:__ **0.7-1.2h**.",
|
||||
warningEliminationOutOfRange: "⚠️ Current value may be outside clinical norms.\\n\\n__Typical range:__ **9-12h** (normal pH).\\nExtended range 7-15h (pH effects).",
|
||||
warningDoseAbove70mg: "⚠️ Higher doses lack safety data and increase cardiovascular risk.\\n\\n__FDA-approved maximum:__ **70 mg**.\\n\\nConsult your physician before exceeding this dose.",
|
||||
warningDailyTotalAbove70mg: "⚠️ **Daily total exceeds recommended maximum.**\\n\\n__FDA-approved maximum:__ **70 mg/day**.\\nYour daily total: **{{total}} mg**.\\nConsult your physician before exceeding this dose.",
|
||||
errorDailyTotalAbove200mg: "⛔ **Daily total far exceeds safe limits!**\\n\\nYour daily total **{{total}} mg** exceeds 200 mg/day which is **significantly beyond FDA-approved limits**. *Please consult your physician.*",
|
||||
|
||||
// Time picker
|
||||
timePickerHour: "Hour",
|
||||
|
||||
@@ -123,4 +123,22 @@
|
||||
.info-text {
|
||||
@apply text-[hsl(var(--foreground))];
|
||||
}
|
||||
|
||||
/* Badge variants for validation states */
|
||||
.badge-error {
|
||||
@apply border-red-500 bg-red-500/20 text-red-700 dark:text-red-300;
|
||||
}
|
||||
|
||||
.badge-warning {
|
||||
@apply border-amber-500 bg-amber-500/20 text-amber-700 dark:text-amber-300;
|
||||
}
|
||||
|
||||
/* Badge variants for trend indicators */
|
||||
.badge-trend-up {
|
||||
@apply bg-blue-100 dark:bg-blue-900/60 text-blue-700 dark:text-blue-200;
|
||||
}
|
||||
|
||||
.badge-trend-down {
|
||||
@apply bg-orange-100 dark:bg-orange-900/60 text-orange-700 dark:text-orange-200;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user