feat(web): create/update actions accept delivery window hours
createReminderAction and updateReminderAction now read deliveryWindowStartHour / deliveryWindowEndHour off the input and persist them on the reminders row. Both fields are optional in the input shape (default 6/18) so existing callers don't break, and a refine validates start < end when provided. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7039d57a41
commit
f50a1fc0a7
@ -248,6 +248,12 @@ const createReminderSchema = z
|
|||||||
scheduledAtIso: z.string().datetime({ offset: true }),
|
scheduledAtIso: z.string().datetime({ offset: true }),
|
||||||
rrule: z.string().nullable().optional(),
|
rrule: z.string().nullable().optional(),
|
||||||
timezone: z.string().default(DEFAULT_TIMEZONE),
|
timezone: z.string().default(DEFAULT_TIMEZONE),
|
||||||
|
// Delivery window in the operator's timezone. End hour will gate
|
||||||
|
// the runtime fan-out in a later phase; start is documented but
|
||||||
|
// not yet enforced. Optional in the input shape for backward
|
||||||
|
// compatibility — the action body falls back to 6/18.
|
||||||
|
deliveryWindowStartHour: z.number().int().min(0).max(24).optional(),
|
||||||
|
deliveryWindowEndHour: z.number().int().min(0).max(24).optional(),
|
||||||
})
|
})
|
||||||
.refine(
|
.refine(
|
||||||
(d) =>
|
(d) =>
|
||||||
@ -258,7 +264,11 @@ const createReminderSchema = z
|
|||||||
message: "Add a message or attach a file",
|
message: "Add a message or attach a file",
|
||||||
path: ["messages"],
|
path: ["messages"],
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
.refine((d) => (d.deliveryWindowStartHour ?? 6) < (d.deliveryWindowEndHour ?? 18), {
|
||||||
|
message: "Delivery window start must be earlier than end",
|
||||||
|
path: ["deliveryWindowStartHour"],
|
||||||
|
});
|
||||||
|
|
||||||
/** Resolve the schema's union of new + legacy fields into a flat list. */
|
/** Resolve the schema's union of new + legacy fields into a flat list. */
|
||||||
function resolveMessageParts(parsed: z.infer<typeof createReminderSchema>): Array<{
|
function resolveMessageParts(parsed: z.infer<typeof createReminderSchema>): Array<{
|
||||||
@ -304,7 +314,15 @@ export async function createReminderAction(
|
|||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
return { ok: false, error: parsed.error.issues[0]?.message ?? "Invalid input" };
|
return { ok: false, error: parsed.error.issues[0]?.message ?? "Invalid input" };
|
||||||
}
|
}
|
||||||
const { accountId, groupIds, scheduledAtIso, rrule, timezone } = parsed.data;
|
const {
|
||||||
|
accountId,
|
||||||
|
groupIds,
|
||||||
|
scheduledAtIso,
|
||||||
|
rrule,
|
||||||
|
timezone,
|
||||||
|
} = parsed.data;
|
||||||
|
const deliveryWindowStartHour = parsed.data.deliveryWindowStartHour ?? 6;
|
||||||
|
const deliveryWindowEndHour = parsed.data.deliveryWindowEndHour ?? 18;
|
||||||
const parts = resolveMessageParts(parsed.data);
|
const parts = resolveMessageParts(parsed.data);
|
||||||
|
|
||||||
const op = await getSeededOperator();
|
const op = await getSeededOperator();
|
||||||
@ -358,6 +376,8 @@ export async function createReminderAction(
|
|||||||
scheduledAt,
|
scheduledAt,
|
||||||
rrule: rrule ?? null,
|
rrule: rrule ?? null,
|
||||||
timezone,
|
timezone,
|
||||||
|
deliveryWindowStartHour,
|
||||||
|
deliveryWindowEndHour,
|
||||||
status: "active",
|
status: "active",
|
||||||
createdBy: op.id,
|
createdBy: op.id,
|
||||||
})
|
})
|
||||||
@ -407,7 +427,16 @@ export async function updateReminderAction(
|
|||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
return { ok: false, error: parsed.error.issues[0]?.message ?? "Invalid input" };
|
return { ok: false, error: parsed.error.issues[0]?.message ?? "Invalid input" };
|
||||||
}
|
}
|
||||||
const { reminderId, accountId, groupIds, scheduledAtIso, rrule, timezone } = parsed.data;
|
const {
|
||||||
|
reminderId,
|
||||||
|
accountId,
|
||||||
|
groupIds,
|
||||||
|
scheduledAtIso,
|
||||||
|
rrule,
|
||||||
|
timezone,
|
||||||
|
} = parsed.data;
|
||||||
|
const deliveryWindowStartHour = parsed.data.deliveryWindowStartHour ?? 6;
|
||||||
|
const deliveryWindowEndHour = parsed.data.deliveryWindowEndHour ?? 18;
|
||||||
const parts = resolveMessageParts(parsed.data);
|
const parts = resolveMessageParts(parsed.data);
|
||||||
|
|
||||||
const op = await getSeededOperator();
|
const op = await getSeededOperator();
|
||||||
@ -467,6 +496,8 @@ export async function updateReminderAction(
|
|||||||
scheduledAt,
|
scheduledAt,
|
||||||
rrule: rrule ?? null,
|
rrule: rrule ?? null,
|
||||||
timezone,
|
timezone,
|
||||||
|
deliveryWindowStartHour,
|
||||||
|
deliveryWindowEndHour,
|
||||||
// Preserve the lifecycle status. Editing fields shouldn't
|
// Preserve the lifecycle status. Editing fields shouldn't
|
||||||
// implicitly re-activate a paused or ended reminder — the
|
// implicitly re-activate a paused or ended reminder — the
|
||||||
// user can use the explicit Restart action for that.
|
// user can use the explicit Restart action for that.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user