diff --git a/frontend/src/components/planning/PlanResults.test.tsx b/frontend/src/components/planning/PlanResults.test.tsx
index 1ae1b6a..ec945bf 100644
--- a/frontend/src/components/planning/PlanResults.test.tsx
+++ b/frontend/src/components/planning/PlanResults.test.tsx
@@ -363,6 +363,39 @@ describe('PlanResults', () => {
expect(table).toHaveTextContent('10')
})
+ // The Dashboard's own expiring-at-4 figure reflects the currently saved
+ // plan; this table reflects an unsaved proposal and can legitimately show
+ // a different number. The title/intro must say so, so the two screens are
+ // never mistaken for showing the same thing (types/entities.ts:
+ // PlanAge4Projection vs Age4Projection).
+ it('labels the age-4 projection section as previewing this unsaved proposal, in Swedish', () => {
+ const proposal = buildProposal({
+ age4Projections: [
+ { parentPersonalDataUuid: 'pd1', childId: 'child1', fourthBirthday: '2030-03-01', projectedLeftAtB4: 106, savableAfterB4: 96, expiringAtB4: 10 },
+ ],
+ })
+ renderLocalized(, 'sv')
+
+ const section = screen.getByTestId('plan-age4-projections')
+ expect(section).toHaveTextContent('Vid barnets 4-årsdag, om detta förslag tillämpas')
+ expect(section).toHaveTextContent('om just detta förslag tillämpas')
+ expect(section).toHaveTextContent('Din sparade plan')
+ })
+
+ it('labels the age-4 projection section as previewing this unsaved proposal, in English', () => {
+ const proposal = buildProposal({
+ age4Projections: [
+ { parentPersonalDataUuid: 'pd1', childId: 'child1', fourthBirthday: '2030-03-01', projectedLeftAtB4: 106, savableAfterB4: 96, expiringAtB4: 10 },
+ ],
+ })
+ renderLocalized(, 'en')
+
+ const section = screen.getByTestId('plan-age4-projections')
+ expect(section).toHaveTextContent("At the child's 4th birthday, if this proposal is applied")
+ expect(section).toHaveTextContent('if this proposal is applied')
+ expect(section).toHaveTextContent('Your saved plan')
+ })
+
it('shows an assumed badge for a vacation year with no entered data (§3.2)', () => {
const proposal = buildProposal({
vacationBalances: [
diff --git a/frontend/src/hooks/useLeaveWishes.test.ts b/frontend/src/hooks/useLeaveWishes.test.ts
index e0931c5..ec3fb93 100644
--- a/frontend/src/hooks/useLeaveWishes.test.ts
+++ b/frontend/src/hooks/useLeaveWishes.test.ts
@@ -11,6 +11,7 @@ const mockWish = {
workspaceId: 'ws1',
childId: null,
name: 'Sommar',
+ nameMessageKey: null,
windowStartMonth: 6,
windowStartDay: 15,
windowEndMonth: 7,
diff --git a/frontend/src/i18n/en/dashboard.ts b/frontend/src/i18n/en/dashboard.ts
index 62295a3..23b161d 100644
--- a/frontend/src/i18n/en/dashboard.ts
+++ b/frontend/src/i18n/en/dashboard.ts
@@ -8,8 +8,8 @@ export const dashboard = {
'dashboard.createChildError': 'Could not create child',
'dashboard.daysLeft': 'Days left',
'dashboard.enterManually': 'Enter details manually',
- 'dashboard.expiringAtB4': 'Total expiring at age 4 (sum of all parents)',
- 'dashboard.expiringAtB4ForParent': 'Expiring at age 4 – {name}',
+ 'dashboard.expiringAtB4': 'Expiring at age 4 if the current plan is followed (all parents)',
+ 'dashboard.expiringAtB4ForParent': 'Expiring at age 4 if the current plan is followed – {name}',
'dashboard.expiringAtB4ParentFallback': 'Parent {number}',
'dashboard.fetchFromFk': 'Fetch from Försäkringskassan',
'dashboard.fillAllFields': 'Fill in all fields',
diff --git a/frontend/src/i18n/en/plan.ts b/frontend/src/i18n/en/plan.ts
index 79f102b..9173bc3 100644
--- a/frontend/src/i18n/en/plan.ts
+++ b/frontend/src/i18n/en/plan.ts
@@ -9,8 +9,8 @@ export const plan = {
'plan.title': 'Planning',
'plan.updateWishError': 'Could not save wish',
'plan.wishesTitle': 'Your wishes',
- 'planResults.age4ProjectionsIntro': 'Here\'s what the 4th birthday looks like if this plan is taken as proposed — life may of course work out differently.',
- 'planResults.age4ProjectionsTitle': 'At the child\'s 4th birthday, if this plan is followed',
+ 'planResults.age4ProjectionsIntro': 'Here\'s what the 4th birthday looks like if this proposal is applied, including future recurring wishes. Your saved plan (under Overview) may show a different result.',
+ 'planResults.age4ProjectionsTitle': 'At the child\'s 4th birthday, if this proposal is applied',
'planResults.applyButton': 'Use plan',
'planResults.applySavedPrefix': 'The plan has been saved!',
'planResults.applyingButton': 'Saving...',
diff --git a/frontend/src/i18n/sv/dashboard.ts b/frontend/src/i18n/sv/dashboard.ts
index 0c1777b..bf51f53 100644
--- a/frontend/src/i18n/sv/dashboard.ts
+++ b/frontend/src/i18n/sv/dashboard.ts
@@ -8,8 +8,8 @@ export const dashboard = {
'dashboard.createChildError': 'Kunde inte skapa barn',
'dashboard.daysLeft': 'Kvarvarande dagar',
'dashboard.enterManually': 'Ange uppgifter manuellt',
- 'dashboard.expiringAtB4': 'Totalt förfaller vid 4 års ålder (summa av alla föräldrar)',
- 'dashboard.expiringAtB4ForParent': 'Förfaller vid 4 års ålder – {name}',
+ 'dashboard.expiringAtB4': 'Förfaller vid 4 år om nuvarande plan följs (alla föräldrar)',
+ 'dashboard.expiringAtB4ForParent': 'Förfaller vid 4 år om nuvarande plan följs – {name}',
'dashboard.expiringAtB4ParentFallback': 'Förälder {number}',
'dashboard.fetchFromFk': 'Hämta från Försäkringskassan',
'dashboard.fillAllFields': 'Fyll i alla fält',
diff --git a/frontend/src/i18n/sv/plan.ts b/frontend/src/i18n/sv/plan.ts
index 851402e..cb9ccec 100644
--- a/frontend/src/i18n/sv/plan.ts
+++ b/frontend/src/i18n/sv/plan.ts
@@ -9,8 +9,8 @@ export const plan = {
'plan.title': 'Planering',
'plan.updateWishError': 'Kunde inte spara önskemål',
'plan.wishesTitle': 'Dina önskemål',
- 'planResults.age4ProjectionsIntro': 'Så här ser det ut vid 4-årsdagen om den här planen tas ut som föreslaget — livet kan förstås bli annorlunda.',
- 'planResults.age4ProjectionsTitle': 'Vid barnets 4-årsdag, om planen genomförs',
+ 'planResults.age4ProjectionsIntro': 'Så här ser det ut vid 4-årsdagen om just detta förslag tillämpas, inklusive kommande års återkommande önskemål. Din sparade plan (under Översikt) kan visa ett annat resultat.',
+ 'planResults.age4ProjectionsTitle': 'Vid barnets 4-årsdag, om detta förslag tillämpas',
'planResults.applyButton': 'Använd plan',
'planResults.applySavedPrefix': 'Planen har sparats!',
'planResults.applyingButton': 'Sparar...',
diff --git a/frontend/src/pages/Dashboard.test.tsx b/frontend/src/pages/Dashboard.test.tsx
index 050cff6..11819c2 100644
--- a/frontend/src/pages/Dashboard.test.tsx
+++ b/frontend/src/pages/Dashboard.test.tsx
@@ -201,6 +201,38 @@ describe('Dashboard', () => {
expect(screen.getByText(/Återstående till 4 års ålder/)).toBeInTheDocument()
})
+ // The combined expiring-at-4 figure reflects the currently saved plan, while
+ // the Plan tab's own figure (PlanResults.tsx) reflects an unsaved proposal —
+ // the label must say so, so the two screens are never confused for showing
+ // the same thing. See PlanAge4Projection vs Age4Projection in types/entities.ts.
+ it('labels the combined expiring-at-4 metric as reflecting the current saved plan', () => {
+ renderWithRouter()
+ expect(screen.getByTestId('metric-expiring-combined')).toHaveTextContent(
+ 'Förfaller vid 4 år om nuvarande plan följs (alla föräldrar)',
+ )
+ })
+
+ it('labels the per-parent expiring-at-4 metric as reflecting the current saved plan', () => {
+ vi.mocked(hooks.useAnalytics).mockReturnValue({
+ data: {
+ ...mockAnalyticsData,
+ parentProjections: [
+ { personalDataUuid: 'pd-1', childId: 'c-1', birthDate: '2022-01-01', fourthBirthday: '2026-01-01', totalDays: 240, daysUsed: 30, plannedDaysBeforeB4: 10, projectedLeftAtB4: 200, savableAfterB4: 96, expiringAtB4: 60 },
+ { personalDataUuid: 'pd-2', childId: 'c-1', birthDate: '2022-01-01', fourthBirthday: '2026-01-01', totalDays: 240, daysUsed: 20, plannedDaysBeforeB4: 5, projectedLeftAtB4: 210, savableAfterB4: 96, expiringAtB4: 44 },
+ ],
+ combinedExpiringAtB4: 104,
+ },
+ isLoading: false,
+ error: null,
+ refresh: vi.fn(),
+ } as any)
+
+ renderWithRouter()
+ expect(screen.getByTestId('metric-expiring-parent-pd-1')).toHaveTextContent(
+ 'Förfaller vid 4 år om nuvarande plan följs – Alex',
+ )
+ })
+
it('displays error message if analytics fails', () => {
vi.mocked(hooks.useAnalytics).mockReturnValue({
data: null,