Overview

Reusable EventScheduler component in livehealth-frontend for recurring schedules (daily, weekly, monthly, yearly)

πŸ‘€ Utsav KatiyarπŸ“… Updated: Apr 7, 2026🏷️ utils🏷️ frontend

Event Scheduler

EventScheduler is a livehealth-frontend reusable UI for defining repeating schedules: pick a cadence (daily / weekly / monthly / yearly), set frequency (every occurrence, alternate, or custom interval), define when the series ends (after N events or on a date), then generate a list of ISO datetime occurrences.

Source: src/components/reusable/EventScheduler/


Purpose

  • Centralize recurrence UX (tabs + shared frequency/end form) instead of reimplementing it per feature.
  • Produce an array of { date: string } entries via generateRepeatEventDates, which parents store under a configurable key (e.g. scheduled_trips).

Where it is used

The primary integration today is B2B Collection β†’ Trip Management β†’ Create trip, when the user enables a repeat trip and has not yet materialized scheduled instances: AddEditTripModal passes dateKey="scheduled_trips" and wires repeatTripDetails into the trip form so POST …/trips/new/bulk can run with those dates.

Other features can reuse the same component with a different dateKey and eventType label.


Props

PropTypeRole
dateKeystringKey under which generated dates are merged into repeatEventDetails (e.g. "scheduled_trips")
activeTabnumberSelected tab index: 0 daily, 1 weekly, 2 monthly, 3 yearly
setActiveTab(index: number) => voidUpdates active tab when user switches recurrence type
startDatestringAnchor for time-of-day; first occurrence scheduling is derived relative to this
eventTypestringDisplay label for the recurring entity (e.g. localized "Trip")
repeatEventDetailsJsonObjectStateful recurrence payload (see shape below)
setRepeatEventDetails(value: JsonObject) => voidParent updates state when user edits or clicks Next
isRtlbooleanOptional RTL layout

On mount, the component initializes repeatEventDetails with defaults (scheduledOn, repeatCycleType, frequency, ends, etc.).


Repeat details shape (conceptual)

Parents should treat repeatEventDetails as the single source of truth. Important fields used by generateRepeatEventDates:

FieldMeaning
scheduledOnFirst anchor date/time for the series (component sets this from startDate + tab)
repeatCycleType0–3: daily, weekly, monthly, yearly (REPEAT_CYCLE_TYPE_* in utils/constants.ts)
frequency{ value } where 0 = every, 1 = alternate, 2 = custom (repeatEvery required)
repeatEveryCustom interval when frequency.value === 2
ends{ value } where 0 = after N events, 1 = end on date
endAfterEventsMax count when ending β€œafter” (capped at 365 in UI validation)
endOnDateEnd boundary when ending β€œon”
[dateKey]After Next, array of { date: string } (e.g. scheduled_trips)

Frequency option lists are REPEAT_EVENT_*_FREQUENCY_OPTIONS; end options are REPEAT_EVENT_ENDS_OPTIONS.


Next button

Next runs generateRepeatEventDates(repeatEventDetails, startDate) and sets:

setRepeatEventDetails({ ...repeatEventDetails, [dateKey]: dates }).

Next is disabled when:

  • Custom frequency is selected but repeatEvery is missing or invalid.
  • End is β€œon date” but endOnDate is empty.
  • End is β€œafter” but endAfterEvents is invalid or > 365.

generateRepeatEventDates

File: EventScheduler/utils/helpers.ts

  • Copies time of day from startDate onto the computed occurrence dates.
  • Supports consecutive, alternate, and custom intervals per cycle type.
  • Monthly / yearly: skips invalid calendar days (e.g. day 31 in a short month) instead of producing bad dates.
  • Stops when max event count or end date is reached.

Internal structure

PathRole
index.tsxEventScheduler β€” tabs, init effect, Next handler
Components/RepeatEventDaily.tsx (and Weekly, Monthly, Yearly)Per-tab wrapper around shared form
Components/RepeatEventFrequencyAndEndForm.tsxFrequency + end criteria inputs
utils/helpers.tsgenerateRepeatEventDates
utils/constants.tsCycle types, frequency enums, DAYS_IN_YEAR, i18n option lists
utils/controls.scssStyles; imports react-datetime CSS from root

On this page