Let a day removed from a period stay removed
Taking one day out of a period the planner placed did nothing that lasted: the period still asked for a full week, so the next sync put the day straight back. The option was disabled rather than lying about it. A removed day is now recorded as its own thing — no leave for this parent, this child, this date — and the planner honours it on every later sync. It is kept apart from the working-day overrides, which answer a different question about the calendar rather than about the plan. The day belongs to the parent whose band was clicked, so removing one parent's day leaves their partner's alone; where both parents were to be off on one funding arrangement, the partner is simply funded on their own instead. A removed day shortens what the period is asking for rather than counting as a day the plan failed to find, so the advice about closing a shortfall does not start arguing for a day nobody wants. Nothing is removed without a way back: the toast undoes it, and the day itself is marked in the calendar and offers to restore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ei7gCZzdd751uZtPzb1Pep
This commit is contained in:
@@ -23,6 +23,12 @@ export interface PlannedDayModalSavePinnedPayload {
|
||||
isDubbeldag: boolean
|
||||
}
|
||||
|
||||
/** One day the user removed by hand, ready to be offered back. */
|
||||
export interface PlannedDayExclusionEntry {
|
||||
id: string
|
||||
parentName: string
|
||||
}
|
||||
|
||||
export interface PlannedDayModalProps {
|
||||
date: string
|
||||
isOpen: boolean
|
||||
@@ -39,6 +45,11 @@ export interface PlannedDayModalProps {
|
||||
onSaveWish: (payload: PlannedDayModalSaveWishPayload) => Promise<void>
|
||||
onSavePinned: (payload: PlannedDayModalSavePinnedPayload) => Promise<void>
|
||||
onDelete?: (() => Promise<void>) | undefined
|
||||
/** Removals recorded for THIS date (see `PlannedDayExclusion`), one per
|
||||
* parent. Shown with a way back: a day the user can't restore is a trap,
|
||||
* and the undo toast is gone as soon as it times out. */
|
||||
excludedEntries?: PlannedDayExclusionEntry[] | undefined
|
||||
onRestoreExcluded?: ((exclusionId: string) => Promise<void>) | undefined
|
||||
onClose: () => void
|
||||
isSaving?: boolean | undefined
|
||||
error?: string | null | undefined
|
||||
@@ -57,6 +68,8 @@ export function PlannedDayModal({
|
||||
onSaveWish,
|
||||
onSavePinned,
|
||||
onDelete,
|
||||
excludedEntries = [],
|
||||
onRestoreExcluded,
|
||||
onClose,
|
||||
isSaving = false,
|
||||
error = null,
|
||||
@@ -217,6 +230,28 @@ export function PlannedDayModal({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isRangeMode &&
|
||||
excludedEntries.map((entry) => (
|
||||
<div
|
||||
key={entry.id}
|
||||
className="planned-day-modal__excluded-notice"
|
||||
data-testid="excluded-notice"
|
||||
>
|
||||
<span>{t('plannedDayModal.excludedNotice', { parent: entry.parentName })}</span>
|
||||
{onRestoreExcluded && (
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn--secondary btn--sm"
|
||||
onClick={() => void onRestoreExcluded(entry.id)}
|
||||
disabled={isSaving}
|
||||
data-testid={`restore-excluded-${entry.id}`}
|
||||
>
|
||||
{t('plannedDayModal.restoreExcludedButton')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="stack">
|
||||
{!forcedAdvanced && hasMultipleParents && (
|
||||
<div className="field">
|
||||
|
||||
Reference in New Issue
Block a user