yiekheng a7a5c6821b feat(recurrence): redesign as a Temenos-style trigger + dialog picker
The previous flat radio list with N-minutes / N-hours / Custom-cron
options is gone. Per the Temenos UUX `date-recurrence-picker` pattern
(developer.temenos.com/uux/docs/components/date-recurrence-picker), the
form now shows a single read-only trigger field summarising the saved
rule:

  ┌────────────────────────────────────────────────────┐
  │ 📅  Don't repeat                                ▾  │
  └────────────────────────────────────────────────────┘

Clicking the trigger opens a modal with the recurrence types as a
tab strip and per-type config swapped in below:

  ┌──────────────────────────────────────────────────┐
  │  Repeat schedule                            ✕    │
  ├──────────────────────────────────────────────────┤
  │  [Don't repeat] [Daily] [Weekly] [Monthly] [Yearly] │
  │                                                  │
  │  <per-type config>                               │
  │                                                  │
  │  Fires: <plain-text confirmation>                │
  │                                                  │
  │  [Reset]                    [Cancel] [Save]      │
  └──────────────────────────────────────────────────┘

Per-tab config:
  - Don't repeat — informational text only
  - Daily       — radio: "Every day" / "Every weekday (Mon–Fri)"
  - Weekly      — Mon..Sun chip multi-select
  - Monthly     — day-of-month input (1-31)
  - Yearly      — month select + day input

The "Fires: …" sentence updates live as the user edits and reflects
the outer time-picker's HH:MM. Save commits, Cancel discards.

Removed:
  - Every N minutes
  - Every N hours
  - Custom cron expression…
  - The standalone helpers `flowToCron` / `flowFromCron` /
    `freqChoices` / `defaultFlowState` / `FlowState` / `FreqChoice`
    in `lib/recurrence.ts`. Their job (compile a UI state to a cron
    string and parse one back) now lives privately inside the picker.

Storage / runtime
- Output is still a `CRON:` prefixed rule in `reminders.rrule`. The
  bot's `nextOccurrence` already dispatches cron rules through
  cron-parser, so no schema or scheduler changes were needed.

Tests (132 web)
- recurrence.test.ts trimmed to keep only what survives: CRON-rule
  round-trip via buildRrule + specFromRrule, and the ISO→cron
  weekday helper.
- Existing wizard / edit-when-form integration tests are unaffected
  because the picker exports the same `<RecurrencePicker>` props.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 11:02:16 +08:00
..