feat(cycle): fertile-window reminder for the conception goal

Add a CYCLE_FERTILE_SOON reminder that fires two days before the
predicted fertile-window start. Twice-gated and default-OFF: it only
surfaces when CycleProfile.goal is TRYING_TO_CONCEIVE and fertileWindowStart
is populated, so fertile language never reaches the avoid / general / peri
goals. Reuses the existing cycle-reminder cron, discreet mode, clientManaged
suppression, idempotency ledger, and push-attempts plumbing verbatim; the
body carries the non-medical, not-a-contraceptive framing.
This commit is contained in:
Marc-André Bombeck committed 2026-06-06 16:39:45 +02:00
1 parent e391150455
commit 93d47ddd05
10 files changed
+376 -90

No files matched your search

+23
View File
@@ -205,6 +205,29 @@ export function CycleSettings({ profile }: { profile: CycleProfileDTO }) {
</Button>
</div>
{/* Fertile-window reminder — surfaced ONLY under the conception goal.
The toggle itself is the default-OFF per-channel CYCLE_FERTILE_SOON
switch on the notifications page; here we just point a TTC user to
it, so the affordance never appears (and fertile language never
shows) for the other goals (the inclusive-framing rule). */}
{goal === "TRYING_TO_CONCEIVE" ? (
<div className="flex items-start justify-between gap-4">
<div className="space-y-0.5">
<p className="text-sm font-medium">
{t("cycle.settings.fertileReminder")}
</p>
<p className="text-muted-foreground text-xs">
{t("cycle.settings.fertileReminderDescription")}
</p>
</div>
<Button variant="outline" size="sm" asChild className="shrink-0">
<Link href="/notifications">
{t("cycle.settings.remindersLink")}
</Link>
</Button>
</div>
) : null}
<Separator />
{/* Data export / delete */}