Break the Dashboard's age-4 stat down per parent

The Dashboard summed both parents' expiring days into one figure while
the Plan tab already showed them separately. Each parent's own count is
now shown alongside the combined total, which stays and is relabelled as
a sum.

The per-parent numbers were already on the wire as
parentProjections[].expiringAtB4 -- no backend change, and no arithmetic
here. Both figures are rendered exactly as the backend computed them,
since re-deriving them is what previously doubled a parent's entitlement
(87b3eb5).

A single-parent workspace shows only the combined figure, where a
breakdown would just repeat it.

nameResolver moves out of PlanResults.tsx into src/utils/parentNames.ts
so both screens resolve uuid -> name the same way. PlanResults.test.tsx
passes untouched, which is the evidence the extraction preserved
behaviour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RXMhc9nT6sNz1SL4j8dznL
This commit is contained in:
2026-09-14 18:54:50 +02:00
parent f685b739f8
commit cf378288f0
5 changed files with 186 additions and 10 deletions
@@ -18,6 +18,7 @@ import type {
PlanApplyResponse,
} from '@/types'
import { useTranslation, toTranslationParams, type TranslationKey, type TranslationParams } from '@/i18n'
import { nameResolver } from '@/utils/parentNames'
export interface PlanResultsProps {
proposal: PlanProposal
@@ -102,10 +103,6 @@ const REJECTION_KEYS: Record<string, TranslationKey> = {
'planApply.rejection.insufficientBalance': 'planResults.rejectionInsufficientBalance',
}
function nameResolver(members: PersonalData[]): (uuid: string) => string {
return (uuid: string) => members.find((m) => m.uuid === uuid)?.name ?? uuid
}
/** `data` plus the resolved parent name (when the surface carries a
* `parent_personal_data_uuid`) — every warning/advice body template below
* references `{parent_name}`, and the backend only ever sends the uuid.