c3ba580e30
Clicking a planned day raises the calendar toast with a plain-language
reason (sv + en) taken from the live in-memory proposal; the backend
field-parity walk now covers ProposedDay.
Conflicts in Calendar.tsx / Calendar.test.tsx against the day-assertions
restructure and the two earlier merges; both intents kept:
- usePlannedDayExclusions stays replaced by useDayAssertions; the branch's
usePlanProposal watch, reasonProposal state, reasonByDay map and the
handleBandClick reason toast are added alongside main's band logic.
- runSync keeps the security branch's background refresh and also records
the sync's proposal for the reason toast. main's applyWishSyncResult
(every wish save on this page) records result.sync.proposal the same way,
so an edit's fresh reasons reach the toast — the stale-response guards
in usePlanSync/usePlanProposal only gate hook state, never the returned
response the reason rides in on.
- One main test ("no success toast when sync-with-wish throws") now
dismisses the click's own reason toast first; its assertion is unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4wjgbVL4HAC5Rdaw75VbV
220 lines
13 KiB
TypeScript
220 lines
13 KiB
TypeScript
export const calendar = {
|
||
'calendar.selectMonthAria': 'Select month',
|
||
'calendar.selectYearAria': 'Select year',
|
||
'calendar.deleteError': 'Failed to delete the planned day',
|
||
'calendar.nextMonthAria': 'Next month',
|
||
'calendar.partner': 'Partner',
|
||
'calendar.pinnedDayAllFreeError':
|
||
'None of the selected days can be saved as that type — free days (weekends/red days) can never be vacation, and parental leave on them needs the Settings toggle turned on.',
|
||
'calendar.prevMonthAria': 'Previous month',
|
||
'calendar.saveError': 'Failed to save the planned days',
|
||
'calendar.today': 'Today',
|
||
'calendar.weekdayFri': 'Fri',
|
||
'calendar.weekdayMon': 'Mon',
|
||
'calendar.weekdaySat': 'Sat',
|
||
'calendar.weekdaySun': 'Sun',
|
||
'calendar.weekdayThu': 'Thu',
|
||
'calendar.weekdayTue': 'Tue',
|
||
'calendar.weekdayWed': 'Wed',
|
||
'calendar.you': 'You',
|
||
'calendarDay.excludedAria': 'removed day — the planner skips it',
|
||
'calendarDay.klamdagAria': 'bridge day',
|
||
'calendarDay.overrideFreeAria': 'marked as a day off (exception)',
|
||
'calendarDay.overrideWorkingAria': 'marked as a working day (exception)',
|
||
'calendarDay.pinnedAria': 'pinned by you — the planner will not retype this day',
|
||
'calendarDay.sundayAria': 'Sunday',
|
||
'calendarEvent.dismissAria': 'Dismiss {leaveType}',
|
||
'plannedDayModal.cancelButton': 'Cancel',
|
||
'plannedDayModal.closeAria': 'Close',
|
||
'plannedDayModal.confirmDelete': 'Are you sure you want to delete this planned day?',
|
||
'plannedDayModal.deleteButton': 'Delete',
|
||
'plannedDayModal.deleteConfirmButton': 'Yes, delete',
|
||
'plannedDayModal.deleteError': 'Failed to delete planned day',
|
||
'plannedDayModal.deletingButton': 'Deleting…',
|
||
'plannedDayModal.doubleDayHint': 'Double days do not apply to vacation',
|
||
'plannedDayModal.doubleDayLabel': 'Double day (both parents taking leave)',
|
||
'plannedDayModal.editTitle': 'Edit Planned Day',
|
||
'plannedDayModal.lagstaOption': 'Lägstanivå (minimum-rate, 90-day tier)',
|
||
'plannedDayModal.leaveTypeLabel': 'Leave Type',
|
||
'plannedDayModal.newTitle': 'Plan a Day',
|
||
'plannedDayModal.parentLabel': 'Parent',
|
||
'plannedDayModal.pinnedNotice': 'This day is pinned by you — the planner will not change it automatically.',
|
||
'plannedDayModal.pinExcludesFromSyncNotice':
|
||
'Pinning excludes this day from the planner’s automatic re-planning.',
|
||
'plannedDayModal.freeDaysStayOffNotice':
|
||
'Free days (weekends/red days) in your selection are left as days off — vacation can never go there, and parental leave needs "Take parental leave on red days" turned on in Settings.',
|
||
'plannedDayModal.excludedNotice': 'You removed this day for {parent}.',
|
||
'plannedDayModal.restoreExcludedButton': 'Put the day back',
|
||
'plannedDayModal.rangeTitle': 'Plan {count} days',
|
||
'plannedDayModal.parentModeLabel': 'Who is this for?',
|
||
'plannedDayModal.wantsDubbeldagLabel': 'Allow double days (dubbeldagar)',
|
||
'plannedDayModal.wantsDubbeldagHint':
|
||
"Both parents are off the same day and each spend one of their own parental-benefit days (no vacation day is used) — only available in the child's first 15 months, capped at 60 dates per child, shared between you.",
|
||
'plannedDayModal.wantsDubbeldagRequiresBothHint': 'Requires both parents to be selected above.',
|
||
'plannedDayModal.showAdvanced': 'Advanced: pick type and parent manually',
|
||
'plannedDayModal.hideAdvanced': 'Hide advanced',
|
||
'plannedDayModal.saveButton': 'Save',
|
||
'plannedDayModal.saveError': 'Failed to save planned day',
|
||
'plannedDayModal.savingButton': 'Saving…',
|
||
'plannedDayModal.sjukpenningOption': 'Sjukpenningnivå (income-based, 390-day tier)',
|
||
'plannedDayModal.vacationOption': 'Vacation',
|
||
'plannedDayModal.autoOption': 'Let the planner choose',
|
||
'redDaysList.effectiveFree': 'Off',
|
||
'redDaysList.effectiveWorking': 'Working day',
|
||
'redDaysList.emptyYear': 'No public holidays or exceptions this year.',
|
||
'redDaysList.loading': 'Loading public holidays...',
|
||
'redDaysList.nextWindow': 'Next 4 years',
|
||
'redDaysList.overrideFree': 'Exception: day off',
|
||
'redDaysList.overrideWorking': 'Exception: working day',
|
||
'redDaysList.prevWindow': 'Previous 4 years',
|
||
'redDaysList.toggleError': 'Failed to update this day. Try again.',
|
||
'redDaysList.toggleToFreeAria': 'Mark {date} as a day off',
|
||
'redDaysList.toggleToWorkingAria': 'Mark {date} as a working day',
|
||
|
||
// §Task7 — the calendar becomes the plan: drag-select, period popover,
|
||
// preset rail, and the sync toast/undo.
|
||
'calendar.periodCreateError': 'Failed to create the period',
|
||
'calendar.syncError': 'Failed to sync the plan',
|
||
'calendar.syncingLabel': 'Syncing…',
|
||
'calendar.toastChangedDays': '{name}: {count} {count|day|days} changed',
|
||
// A `removed` change with `evicted: true` — a row removed because a
|
||
// DIFFERENT wish's edit won a shared FP/vacation pool ahead of it, not
|
||
// because its own wish moved (see `PlanChange.evicted`'s doc comment in
|
||
// src/types/entities.ts). `sync_plan` always writes now, so this is
|
||
// reported here rather than as a separate rejection/preview.
|
||
'calendar.toastDisplacedDays':
|
||
'{name}: {count} {count|day|days} removed to make room for a higher-priority period',
|
||
'calendar.toastGenericPeriod': 'The period',
|
||
'calendar.toastShortfallNone':
|
||
'{name} ({start}–{end}): none of the {weeksWished} {weeksWished|week|weeks} requested could be funded — {shortfallDays} {shortfallDays|day|days} short',
|
||
'calendar.toastShortfallPartial':
|
||
'{name} ({start}–{end}): only {weeksFunded} of {weeksWished} weeks funded — {shortfallDays} {shortfallDays|day|days} short',
|
||
'calendar.toastShortfallNoneDays':
|
||
'{name} ({start}–{end}): none of the {daysWished} {daysWished|day|days} requested could be funded — {shortfallDays} {shortfallDays|day|days} short',
|
||
'calendar.toastShortfallPartialDays':
|
||
'{name} ({start}–{end}): only {daysFunded} of {daysWished} days funded — {shortfallDays} {shortfallDays|day|days} short',
|
||
'calendar.toastRedDayShift':
|
||
'{name}: moved to {start} – {end} to catch {days} extra free {days|day|days}',
|
||
// Reallocation pass — `reallocate_vacation_by_value` swaps vacation onto
|
||
// better dates 1-for-1 with parental leave. `{from}`/`{to}` already carry
|
||
// the period name plus its dates (e.g. "Summer (Jun 20, Jun 21)"), or the
|
||
// dates alone when no single period can be named — see vacationSwaps.ts.
|
||
'calendar.toastVacationSwap':
|
||
'{count} {count|vacation day|vacation days} moved from {from} to {to} — replaced with parental leave',
|
||
'calendar.undoButton': 'Undo',
|
||
'calendar.undoError': 'Failed to undo the change',
|
||
'calendar.dismissToastAria': 'Dismiss the message',
|
||
|
||
// The "?" beside the month title — replaces the legend that used to sit
|
||
// under the grid. One line per mark the calendar draws.
|
||
'calendar.helpAria': 'What the calendar marks mean',
|
||
'calendar.helpTitle': 'Days',
|
||
'calendar.helpBandsTitle': 'Periods',
|
||
'calendar.helpRedDay': 'Public holiday (R) — a red day or a Sunday',
|
||
'calendar.helpKlamdag': 'Bridge day (K)',
|
||
'calendar.helpSaturday': 'Saturday',
|
||
'calendar.helpToday': 'Today',
|
||
'calendar.helpOverride': 'Exception — marked as a working day or a day off',
|
||
'calendar.helpExcluded': 'Removed day — the planner skips it',
|
||
'calendar.helpVacation': 'Vacation',
|
||
'calendar.helpSjukpenning': 'Income-based rate (sjukpenningnivå)',
|
||
'calendar.helpLagsta': 'Minimum rate (lägstanivå)',
|
||
'calendar.helpSelf': 'Your leave',
|
||
'calendar.helpPartner': "Your partner's leave",
|
||
'calendar.helpDubbeldag': 'Double day — both parents on the same day',
|
||
'calendar.helpPinned': 'Pinned by you — the planner leaves the day alone',
|
||
|
||
'calendar.railHeading': 'Add leave',
|
||
'calendar.railHint': 'Click to add — the calendar jumps to wherever it fits best.',
|
||
'calendar.presetAddAria': 'Add {name}',
|
||
'calendar.presetChipsLabel': 'Add leave',
|
||
'calendar.presetWeeksShort': '{count} wk',
|
||
|
||
'calendar.periodAdHocTitle': 'Period',
|
||
'calendar.periodAdHocNotice': "This period isn't saved as a recurring wish yet. Give it a name and save.",
|
||
'calendar.periodNameLabel': 'Name',
|
||
'calendar.periodNameAria': "The period's name",
|
||
'calendar.periodStartLabel': 'Start date',
|
||
'calendar.periodEndLabel': 'End date',
|
||
|
||
// §Planering (restructure step 4) — replaces the three-way radio ladder
|
||
// with a toggle (where the planner may place the period) plus a separate
|
||
// lock/unlock action (see calendar.periodLock*). Same vocabulary as
|
||
// calendarDay.pinnedAria/plannedDayModal.autoOption.
|
||
'calendar.periodMoveableLegend': 'Planning',
|
||
'calendar.periodMoveableLabel': 'The planner may move the period',
|
||
'calendar.periodMoveableHint': 'The planner picks the best placement inside the chosen months.',
|
||
'calendar.periodFixedHint':
|
||
"The dates stay fixed. The planner still chooses each day's type unless it's locked.",
|
||
'calendar.periodBoundFromLabel': 'From month',
|
||
'calendar.periodBoundToLabel': 'To month',
|
||
'calendar.periodBoundLengthHint':
|
||
'{count} {count|day|days} — the planner picks where in the chosen period they land.',
|
||
|
||
// Lock/unlock is an action on the period's actually-saved days, not a form
|
||
// mode — locking can therefore be partial (see restructure step 4).
|
||
'calendar.periodLockLegend': 'Locking',
|
||
'calendar.periodLockStatus': '{locked} of {total} {total|day|days} locked',
|
||
'calendar.periodLockButton': 'Lock the days',
|
||
'calendar.periodUnlockButton': 'Unlock',
|
||
'calendar.periodLockUpdatingButton': 'Updating…',
|
||
'calendar.toastDaysLocked': '{count} {count|day|days} locked',
|
||
'calendar.toastDaysUnlocked': '{count} {count|day|days} unlocked',
|
||
|
||
'calendar.periodRepeatLabel': 'Repeat',
|
||
'calendar.periodRepeatNever': 'Never',
|
||
'calendar.periodRepeatYearly': 'Yearly',
|
||
'calendar.periodLastYearLabel': 'Last year',
|
||
|
||
// One year vs the whole series. A repeating period is stored as one row per
|
||
// year, so "only this year" can finally be honoured — Easter moves, and a
|
||
// single year has to be able to move without dragging the rest with it.
|
||
// See backend/app/entities/leave_wish.py.
|
||
'calendar.periodEditScopeLabel': 'Apply the change to',
|
||
'calendar.periodEditScopeYear': 'Only this year',
|
||
// §Planering (step 4) — the previously silent trap: this is the default,
|
||
// so its limiting consequence must be as visible as "Every year"'s effect,
|
||
// or a saved edit looks like a no-op the moment you check another year.
|
||
'calendar.periodEditScopeYearHint': 'Other years in the series are not affected.',
|
||
'calendar.periodEditScopeSeries': 'Every year',
|
||
'calendar.periodEditScopeHint': 'Every year shifts the other years to match, keeping the weekdays.',
|
||
'calendar.periodLastYearNeedsSeriesHint': 'Choose "Every year" to change the last year.',
|
||
'calendar.periodSaveButton': 'Save period',
|
||
'calendar.periodSavingButton': 'Saving…',
|
||
'calendar.periodDeletingButton': 'Deleting…',
|
||
'calendar.periodDeleteConfirmButton': 'Yes, delete',
|
||
'calendar.periodDeleteAdHocButton': 'Delete these days',
|
||
'calendar.periodCancelButton': 'Cancel',
|
||
'calendar.periodCloseAria': 'Close',
|
||
'calendar.periodDeleteMenuButton': 'Remove…',
|
||
|
||
// todo.md #9 — three-way remove: this day / this period (this year) / this
|
||
// period every year.
|
||
'calendar.periodDeleteDayButton': 'This day',
|
||
'calendar.periodDeleteYearButton': 'This period',
|
||
'calendar.periodDeleteAllYearsButton': 'This period, every year',
|
||
// "This day" now works on planner-placed days too: the removal is stored
|
||
// as a `DayAssertion` with `dayType: 'none'` and survives every subsequent
|
||
// sync.
|
||
'calendar.periodDeleteDayHint':
|
||
'Only that day is removed. The rest of the period stays, and the planner will not add the day back.',
|
||
'calendar.periodDeleteAllYearsDisabledHint': 'This period is not linked to a recurring plan.',
|
||
'calendar.periodDeleteConfirmDay': 'Are you sure you want to remove this day?',
|
||
// Names both the date and the parent: a day is removed for ONE parent, and
|
||
// the partner's day on the same date stays (see Calendar.tsx's `excludeDay`).
|
||
'calendar.periodDeleteConfirmDayNamed':
|
||
'Remove {date} for {parent}? The day stays removed until you restore it.',
|
||
'calendar.toastDayExcluded': '{date} removed for {parent}',
|
||
'calendar.toastDayRestored': '{date} restored for {parent}',
|
||
// Clicking a planned day's band (`handleBandClick`) — explains why that
|
||
// day got the type it got, read off the freshest plan proposal held in
|
||
// memory (see `frontend/src/utils/planReasons.ts`).
|
||
'calendar.toastDayReason': '{date}, {parent}: {reason}',
|
||
'calendar.periodDeleteConfirmYear': 'Are you sure you want to remove this period (this year only)?',
|
||
'calendar.periodDeleteConfirmAllYears': 'Are you sure you want to remove the period — every year?',
|
||
'calendar.wantsDubbeldagLabel': 'Allow double days (dubbeldagar)',
|
||
'calendar.wantsDubbeldagHint':
|
||
"Both parents are off the same day and each spend one of their own parental-benefit days (no vacation day is used) — only available in the child's first 15 months, capped at 60 dates per child, shared between you.",
|
||
'calendar.wantsDubbeldagRequiresBothHint': 'Requires the period to apply to both parents.',
|
||
} as const
|