WorkingHours
A WorkingHours component lets users define daily start and end times for availability. It also supports adding multiple break intervals within the availabilty and validates to prevent overlaps or out-of-range times.
Quick Start
- Installation
npm install @adaptavant/working-hours- Import
import { WorkingHours } from '@adaptavant/working-hours';
Key Features
A comprehensive time management widget for configuring business availability and break schedules:
- Dual-mode operation - Configure working hours or break times with multi-slot scheduling per day. Supports complex schedules like split shifts and multiple availability windows.
- Intelligent validation - Real-time overlap detection, error highlighting, and change tracking. Prevents conflicting time slots with immediate feedback and unsaved change notifications.
- Flexible time input - Supports multiple formats (9:30 AM, 21:30, 930) with automatic parsing.
- Permission & bulk controls - Role-based access with apply-to-all functionality for quick setup. Control add/delete capabilities, time intervals, and bulk day configuration copying.
- 24 Hours support - Enable permission-based 24-hour scheduling options for round-the-clock availability configuration.
- Full internationalization - Customizable labels for UI text, day names, and error messages for multi-language support.
Working Hours Mode
The example displays "Monday to Friday 8 AM to 5 PM" time schedule with weekends off. Demonstrates full permission settings, custom labels, and event tracking setup.
Use componentBaseType prop to define the type of the component (Working hours or Break) and initialWeekDayConfig prop can be used to set the initial time slots for each day.
The prop workingHoursPermisions controls the visibility of the delete and add slot buttons, the apply to all button, the 24 hour slot option and the time picker interval.
<WorkingHours
componentBaseType="workingHours"
initialWeekDayConfig={{
MO: { hours: [{ start: 480, end: 1020 }], breaks: [] },
TU: { hours: [{ start: 480, end: 1020 }], breaks: [] },
WE: { hours: [{ start: 480, end: 1020 }], breaks: [] },
TH: { hours: [{ start: 480, end: 1020 }], breaks: [] },
FR: { hours: [{ start: 480, end: 1020 }], breaks: [] },
SA: {},
SU: {},
}}
workingHoursPermisions={{
isValidUserToRenderDeleteAndAddSlot: true,
isValidUserToRenderApplyToAll: true,
allow24HourSlot: false,
timePickerInterval: 15,
}}
customLables={{
toggleOffTitle: 'Closed',
toggleDisabledTitle: 'Not Available',
errorMessage: 'Invalid time range',
applyToAllButtonTitle: 'Apply to all days',
addSlotButtonTitle: 'Add Slot',
deleteButtonTitle: 'Delete Slot',
dayLabels: {
Monday: 'Monday',
Tuesday: 'Tuesday',
Wednesday: 'Wednesday',
Thursday: 'Thursday',
Friday: 'Friday',
Saturday: 'Saturday',
Sunday: 'Sunday',
},
}}
gtmEventsCallBack={(eventDescription) => {}}
onWeekDayConfigChange={(config) => {}}
onValidationChange={(hasErrors, errors) => {}}
onUpdateStatusChange={(hasUpdates) => {}}
/>
Breaks Mode
Set componentBaseType="breaks" to configure break times. This mode allows you to set single or multiple break times for each day.
<WorkingHours
componentBaseType="breaks"
initialWeekDayConfig={{
MO: {
hours: [{ start: 480, end: 1020 }],
breaks: [{ start: 720, end: 780 }]
},
TU: {
hours: [{ start: 480, end: 1020 }],
breaks: [{ start: 720, end: 780 }]
},
WE: { hours: [{ start: 480, end: 1020 }], breaks: [] },
TH: { hours: [{ start: 480, end: 1020 }], breaks: [] },
FR: { hours: [{ start: 480, end: 1020 }], breaks: [] },
SA: {},
SU: {},
}}
workingHoursPermisions={{
isValidUserToRenderDeleteAndAddSlot: true,
isValidUserToRenderApplyToAll: true,
allow24HourSlot: false,
timePickerInterval: 15,
}}
customLables={{
toggleOffTitle: 'No breaks',
toggleDisabledTitle: 'Day off',
errorMessage: 'Invalid time range',
deleteButtonTitle: 'Delete Break',
addSlotButtonTitle: 'Add Break',
applyToAllButtonTitle: 'Apply to All',
dayLabels: {
Monday: 'Monday',
Tuesday: 'Tuesday',
Wednesday: 'Wednesday',
Thursday: 'Thursday',
Friday: 'Friday',
Saturday: 'Saturday',
Sunday: 'Sunday',
},
}}
/>
API Reference
WorkingHours
| Props | Type | Description | Default |
|---|---|---|---|
children? | React.ReactNode | Optional React children to be rendered within the widget | _ |
componentBaseType? | 'workingHours' | 'breaks' | Determines the base configuration type for the widget. 'workingHours' for configuring working hours, 'breaks' for configuring break times | 'workingHours' |
initialWeekDayConfig? | WeekDayConfig | Initial configuration for each day of the week including hours and breaks. Times are specified in minutes from midnight (e.g., 540 = 9:00 AM, 1020 = 5:00 PM) | {} |
workingHoursPermisions? | WorkingHoursPermissions | Permission settings that control what actions users can perform (add/remove slots, apply to all, 24-hour slots, time intervals) | _ |
workingHoursPermisions?. isValidUserToRenderDeleteAndAddSlot | boolean | Permission settings that control what actions users can perform (add/remove slots) | false |
workingHoursPermisions?. isValidUserToRenderApplyToAll | boolean | Permission settings that control what actions users can perform (apply to all) | false |
workingHoursPermisions?. allow24HourSlot | boolean | Permission settings that control what actions users can perform (24-hour slots) | false |
workingHoursPermisions?. timePickerInterval | 15 | 60 | 30 | 45 | undefined | Permission settings that control what actions users can perform (time intervals) | _ |
customLables? | CustomLablesType | Custom text labels for UI elements to support internationalization. Includes day labels, button titles, error messages | _ |
customLables?.toggleOffTitle | string | Custom text label for the toggle off title | "Closed" |
customLables?. toggleDisabledTitle | string | Custom text label for the toggle disabled title | "Closed" |
customLables?.errorMessage | string | Custom text label for the error message | "slots overlapping" |
customLables?.deleteButtonTitle | string | Custom text label for the delete button title | "Delete" |
customLables?. addSlotButtonTitle | string | Custom text label for the add slot button title | "Add Slot" |
customLables?. applyToAllButtonTitle | string | Custom text label for the apply to all button title | "Apply to All" |
customLables?.dayLabels | Record<string, string> | Custom text labels for the day labels | {} |
onWeekDayConfigChange? | (config: WeekDayConfig) => void | Callback fired when the week day configuration changes. Use this to sync changes with parent state or API | _ |
onValidationChange? | (hasErrors: boolean, errors: string[]) => void | Callback fired when validation state changes. Critical for form validation and user feedback | _ |
onUpdateStatusChange? | (hasUpdates: boolean) => void | Callback fired when the update status changes. Indicates if user has made unsaved modifications | _ |
gtmEventsSetUp? | GtmEventsSetUpTypes | Google Tag Manager events configuration for analytics tracking. Optional configuration for tracking user interactions | _ |
gtmEventsSetUp?.sendGtmAnalytics | (event: string, shouldPushToGTM: boolean, shouldPushToAmp: boolean) => void | Google Tag Manager events configuration for analytics tracking. Optional configuration for tracking user interactions | _ |
gtmEventsSetUp?.gtmEventsObject | GtmEventsObject | Google Tag Manager events configuration for analytics tracking. Optional configuration for tracking user interactions | _ |
gtmEventsSetUp?.gtmEventsObject?. toggleOn | string | Google Tag Manager event for the toggle on action | _ |
gtmEventsSetUp?.gtmEventsObject?. toggleOff | string | Google Tag Manager event for the toggle off action | _ |
gtmEventsSetUp?.gtmEventsObject?. deleteSlot | string | Google Tag Manager event for the delete slot action | _ |
gtmEventsSetUp?.gtmEventsObject?. addSlot | string | Google Tag Manager event for the add slot action | _ |
gtmEventsSetUp?.gtmEventsObject?. applyToAll | string | Google Tag Manager event for the apply to all action | _ |
Style API
Our design system components include style props that allow you to easily customize different parts of each component to match your design needs.
Please refer to the Style API documentation for more insights.
WorkingHours parts
<WorkingHours
className="border-primary border-2"
componentBaseType="workingHours"
initialWeekDayConfig={{
MO: { hours: [{ start: 480, end: 1020 }], breaks: [] },
TU: { hours: [{ start: 480, end: 1020 }], breaks: [] },
WE: { hours: [{ start: 480, end: 1020 }], breaks: [] },
TH: { hours: [{ start: 480, end: 1020 }], breaks: [] },
FR: { hours: [{ start: 480, end: 1020 }], breaks: [] },
SA: {},
SU: {},
}}
workingHoursPermisions={{
isValidUserToRenderDeleteAndAddSlot: true,
isValidUserToRenderApplyToAll: true,
allow24HourSlot: false,
timePickerInterval: 15,
}}
customLables={{
toggleOffTitle: 'Closed',
toggleDisabledTitle: 'Not Available',
errorMessage: 'Invalid time range',
applyToAllButtonTitle: 'Apply to all days',
addSlotButtonTitle: 'Add Slot',
deleteButtonTitle: 'Delete Slot',
dayLabels: {
Monday: 'Monday',
Tuesday: 'Tuesday',
Wednesday: 'Wednesday',
Thursday: 'Thursday',
Friday: 'Friday',
Saturday: 'Saturday',
Sunday: 'Sunday',
},
}}
gtmEventsCallBack={(eventDescription) => {}}
onWeekDayConfigChange={(config) => {}}
onValidationChange={(hasErrors, errors) => {}}
onUpdateStatusChange={(hasUpdates) => {}}
/>
| Stylable Parts | Description |
|---|---|
| root | The container that wraps the WorkingHours component |