Schedule & Date Overrides
Weekly availability, exceptional date overrides, and minimum booking notice as one schedule-domain system.
Domain-owned availability editing: weekly hours (ScheduleComponent / DayRanges), exceptional dates (DateOverrideInputDialog + DateOverrideList), and minimum booking notice (MinimumBookingNoticeField). Callers own schedule persistence and shell chrome; the Feature package owns day-range editing and override UX.
import { AvailabilitySettings } from "@calcom/features/schedules/components/availability-settings";
import {
DayRanges,
ScheduleComponent,
} from "@calcom/features/schedules/components/schedule-component";
import { DateOverrideInputDialog } from "@calcom/features/schedules/components/date-override-input-dialog";
import { DateOverrideList } from "@calcom/features/schedules/components/date-override-list";
import { MinimumBookingNoticeField } from "@calcom/features/schedules/components/minimum-booking-notice-field";Ownership
Feature — not @coss/ui/shared. Lives under packages/features/schedules/components because it depends on availability form shapes (TimeRange, working hours), react-hook-form field arrays, locale weekday names, and schedule-domain copy.
Coss chrome vs schedule behavior: pages wrap sections in Shared composites (CardFrame, Card, InfoTooltip, InlineEditableText, DurationUnitField). Do not recreate weekly day ranges or override calendars from those Shared pieces alone — import the Feature schedule controls.
Use when
- Editing a user’s weekly availability or date overrides.
- Wiring minimum booking notice on a schedule or event-type limits tab.
- Reusing the same override dialog/list outside the full availability page (timezone-buddy sheet).
Do not reimplement Lexical-style mirrors of day ranges or override calendars in docs or product.
Canonical usage
Weekly schedule
AvailabilitySettings injects a Schedule component (web wraps ScheduleComponent with the user’s time format). Production weekly hours:
<CardFrame>
<CardFrameHeader>
<CardFrameTitle>{t("weekly_hours")}</CardFrameTitle>
<CardFrameDescription>{t("weekly_hours_description")}</CardFrameDescription>
</CardFrameHeader>
<Card>
<CardPanel className="p-0">
<Schedule
labels={{
addTime: t("add_time_availability"),
copyTime: t("copy_times_to"),
deleteTime: t("delete"),
}}
control={form.control}
name="schedule"
userTimeFormat={timeFormat}
weekStart={weekStartNum(weekStart)}
/>
</CardPanel>
</Card>
</CardFrame>Web injection (time format from the current user):
<ScheduleComponent
userTimeFormat={timeFormat}
listItemClassName={scheduleListItemClassName}
{...passThroughProps}
/>DayRanges is the per-day range editor used inside ScheduleComponent and inside DateOverrideInputDialog for override hours — import from schedule-component, not as a standalone product page.
Date overrides
Same orchestrator composes add-dialog + list under Shared card chrome:
<DateOverrideInputDialog
workingHours={workingHours}
excludedDates={excludedDates}
onChange={(ranges) => {
append(groupDateOverrides(ranges));
handleAvailabilityUpdate();
}}
userTimeFormat={userTimeFormat}
weekStart={weekStart}
Trigger={
<Button variant="outline" data-testid="add-override">
<PlusIcon aria-hidden="true" />
<span className="sm:hidden">{t("add")}</span>
<span className="hidden sm:inline">{t("add_an_override")}</span>
</Button>
}
/>
{/* … */}
<DateOverrideList
excludedDates={excludedDates}
replace={replace}
fields={fields}
weekStart={weekStart}
workingHours={workingHours}
userTimeFormat={userTimeFormat}
hour12={Boolean(userTimeFormat === 12)}
travelSchedules={travelSchedules}
handleAvailabilityUpdate={handleAvailabilityUpdate}
/>Timezone-buddy reuses the same Feature pair without the full availability shell — see AvailabilityEditSheet.tsx.
Minimum booking notice
Schedule limits panel (when showScheduleLimits) and event-type limits both use the Feature field, which wraps Shared DurationUnitField and converts to minutes:
<MinimumBookingNoticeField
inputId="schedule-minimum-notice"
value={value}
onChange={onChange}
/><MinimumBookingNoticeField
inputId={field.name}
value={field.value}
onChange={field.onChange}
onBlur={field.onBlur}
inputRef={field.ref}
disabled={shouldLockDisableProps("minimumBookingNotice").disabled}
/>API (public entry points)
| Export | Import path | Role |
|---|---|---|
AvailabilitySettings | …/availability-settings | Full availability page orchestrator (inject Shell + Schedule) |
ScheduleComponent / DayRanges | …/schedule-component | Weekly day list and per-day ranges |
DateOverrideInputDialog | …/date-override-input-dialog | Dialog to add/edit exception dates + hours |
DateOverrideList | …/date-override-list | List/edit/delete existing overrides |
MinimumBookingNoticeField | …/minimum-booking-notice-field | Duration + unit → minutes |
ScheduleComponent expects react-hook-form control + a name path to TimeRange[][], userTimeFormat, and optional weekStart / labels.
Call sites
| File | Notes |
|---|---|
apps/web/modules/availability/[schedule]/schedule-view.tsx | Web wrapper → AvailabilitySettings |
apps/web/modules/schedules/components/Schedule.tsx | Injects ScheduleComponent + user time format |
packages/features/schedules/components/availability-settings.tsx | Weekly hours, overrides, schedule limits |
apps/web/modules/timezone-buddy/components/AvailabilityEditSheet.tsx | Override dialog + list outside full page |
packages/features/eventtypes/components/tabs/limits/EventLimitsTab.tsx | Minimum booking notice on event type |
Example URLs
Not exhaustive — a few places you can open locally (e.g. http://localhost:3000) to see this in product.
| Path | Notes |
|---|---|
/availability/<scheduleId> | Weekly hours + date overrides |
/availability?type=team | Team availability — override sheet (team permission) |
Source
packages/features/schedules/components/availability-settings.tsxpackages/features/schedules/components/schedule-component.tsxpackages/features/schedules/components/date-override-input-dialog.tsxpackages/features/schedules/components/date-override-list.tsxpackages/features/schedules/components/minimum-booking-notice-field.tsx