fix: 'Pause sending by' is off by default everywhere
The optional 'Pause sending by' deadline was defaulting to 18 (= 6 PM)
in three places:
- reminders.delivery_window_end_hour schema default (NOT NULL DEFAULT 18)
- createReminderAction / editScheduleAction fallback when the field
is missing on the input
- the Zod refine validator's secondary fallback
Net effect: any reminder created before this change has 18 in the DB,
so the edit form's checkbox flips ON automatically (the wizard treats
'value !== undefined && value !== 24' as 'opted in'). The wizard's
own create flow always sends 24 explicitly when the box is unchecked
— but legacy / direct API payloads + the schema default for older rows
don't carry that intent through.
Switch every default to 24 (the off-sentinel the wizard already uses)
so the optional toggle stays off until the operator ticks it. New
migration 0012 also backfills existing rows from 18 → 24 so editing
old reminders no longer auto-checks 'Pause sending by'.
Tests in when-form-deadline.test.tsx already lock in the UI contract
(off when initialDeliveryEndHour is undefined or 24, on for any other
value). No assertion changes needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5c48e0e85f
commit
e800882d15
@ -271,7 +271,7 @@ const createReminderSchema = z
|
||||
path: ["messages"],
|
||||
},
|
||||
)
|
||||
.refine((d) => (d.deliveryWindowStartHour ?? 6) < (d.deliveryWindowEndHour ?? 18), {
|
||||
.refine((d) => (d.deliveryWindowStartHour ?? 6) < (d.deliveryWindowEndHour ?? 24), {
|
||||
message: "Delivery window start must be earlier than end",
|
||||
path: ["deliveryWindowStartHour"],
|
||||
});
|
||||
@ -328,7 +328,11 @@ export async function createReminderAction(
|
||||
timezone,
|
||||
} = parsed.data;
|
||||
const deliveryWindowStartHour = parsed.data.deliveryWindowStartHour ?? 6;
|
||||
const deliveryWindowEndHour = parsed.data.deliveryWindowEndHour ?? 18;
|
||||
// 24 = "no deadline" (off). The wizard sends 24 explicitly when the
|
||||
// operator hasn't ticked the optional "Pause sending by" checkbox;
|
||||
// fall back to 24 here so legacy payloads / direct API calls don't
|
||||
// accidentally enable the deadline at 6pm.
|
||||
const deliveryWindowEndHour = parsed.data.deliveryWindowEndHour ?? 24;
|
||||
const parts = resolveMessageParts(parsed.data);
|
||||
|
||||
const op = await getSeededOperator();
|
||||
@ -442,7 +446,11 @@ export async function updateReminderAction(
|
||||
timezone,
|
||||
} = parsed.data;
|
||||
const deliveryWindowStartHour = parsed.data.deliveryWindowStartHour ?? 6;
|
||||
const deliveryWindowEndHour = parsed.data.deliveryWindowEndHour ?? 18;
|
||||
// 24 = "no deadline" (off). The wizard sends 24 explicitly when the
|
||||
// operator hasn't ticked the optional "Pause sending by" checkbox;
|
||||
// fall back to 24 here so legacy payloads / direct API calls don't
|
||||
// accidentally enable the deadline at 6pm.
|
||||
const deliveryWindowEndHour = parsed.data.deliveryWindowEndHour ?? 24;
|
||||
const parts = resolveMessageParts(parsed.data);
|
||||
|
||||
const op = await getSeededOperator();
|
||||
|
||||
10
packages/db/migrations/0012_lucky_masked_marvel.sql
Normal file
10
packages/db/migrations/0012_lucky_masked_marvel.sql
Normal file
@ -0,0 +1,10 @@
|
||||
-- Switch the default to 24 ("no deadline" sentinel) so newly-created
|
||||
-- reminders are off-by-default for the optional "Pause sending by"
|
||||
-- toggle, matching the wizard's UX contract.
|
||||
ALTER TABLE "reminders" ALTER COLUMN "delivery_window_end_hour" SET DEFAULT 24;
|
||||
-- Existing rows still hold the old default (18). Treat those as
|
||||
-- "schema-default, never opted in by the operator" and clear them to
|
||||
-- 24 so editing an old reminder doesn't auto-check the deadline box.
|
||||
-- Operators who actually wanted a 6pm deadline can re-enable it from
|
||||
-- the edit form.
|
||||
UPDATE "reminders" SET "delivery_window_end_hour" = 24 WHERE "delivery_window_end_hour" = 18;
|
||||
1050
packages/db/migrations/meta/0012_snapshot.json
Normal file
1050
packages/db/migrations/meta/0012_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -85,6 +85,13 @@
|
||||
"when": 1778464002000,
|
||||
"tag": "0011_premium_grandmaster",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"version": "7",
|
||||
"when": 1778412502601,
|
||||
"tag": "0012_lucky_masked_marvel",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -92,8 +92,11 @@ export const reminders = pgTable("reminders", {
|
||||
// Delivery window (operator timezone). End hour is enforced at runtime
|
||||
// by fire-reminder when window enforcement lands; start hour is documented
|
||||
// here but not gated in v1.
|
||||
// 24 is the "no deadline" sentinel — it's the off-by-default state so a
|
||||
// reminder created without the operator explicitly opting into "Pause
|
||||
// sending by" stays unbounded.
|
||||
deliveryWindowStartHour: integer("delivery_window_start_hour").notNull().default(6),
|
||||
deliveryWindowEndHour: integer("delivery_window_end_hour").notNull().default(18),
|
||||
deliveryWindowEndHour: integer("delivery_window_end_hour").notNull().default(24),
|
||||
});
|
||||
|
||||
export const reminderTargets = pgTable(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user