Bulk Operations
This guide covers all bulk scheduling operations in Shyfts: template-based creation, copying weeks, CSV import/export, and bulk editing.
Who Can Use Bulk Operations?
| Operation | System Admin | Company Manager | Staff |
|---|---|---|---|
| Template Create | Yes | Yes (own company) | No |
| Copy Week | Yes | Yes (own company) | No |
| CSV Import | Yes | Yes (own company) | No |
| CSV Export | Yes | Yes (own company) | No |
| Bulk Edit | Yes | Yes (own company) | No |
Staff members cannot perform any bulk operations. Company Managers can only manage shifts within their own company.
Accessing Bulk Operations
- Navigate to Dashboard → Scheduling
- Click the Bulk Scheduling button in the calendar header
- A modal opens with three tabs: Template, Copy Week, Import CSV
For Bulk Edit, select multiple shifts in the calendar first, then click the Bulk Edit button that appears.
For CSV Export, use the Export function from the calendar view.
Template Mode
What It Does
Generates multiple shifts from a pattern. You define a date range, time window, shift type, which days of the week, and which staff members — and the system creates all the individual shifts in one go.
Step-by-Step
1. Set the Date Range
| Field | Default | Description |
|---|---|---|
| Start Date | Today | First day to create shifts |
| End Date | 7 days from today | Last day to create shifts |
2. Define the Shift Pattern
| Field | Format | Description |
|---|---|---|
| Start Time | HH:mm (24-hour) | When the shift begins |
| End Time | HH:mm (24-hour) | When the shift ends |
| Shift Type | Dropdown | See shift types table below |
3. Select Days of Week
Click the day buttons to toggle. Defaults to Monday–Friday.
| Button | Day |
|---|---|
| Mon | Monday |
| Tue | Tuesday |
| Wed | Wednesday |
| Thu | Thursday |
| Fri | Friday |
| Sat | Saturday |
| Sun | Sunday |
4. Select Staff Members
Use the searchable staff list to choose one or more active staff members. Options:
- Search by name or email
- Select All to add everyone
- Clear to deselect all
5. Select a Room (Required)
Choose the room these shifts will be assigned to. Only active rooms for your company are shown.
6. Review the Preview
The preview shows how many shifts will be created:
"Will create X shifts for Y staff members in [Room Name]"
The formula: (matching days in range) × (number of staff) = total shifts
7. Click "Create Shifts"
Shift Types
| Type | Use Case |
|---|---|
| Regular | Standard working shift |
| Overtime | Extra hours beyond contract |
| On Call | Available but not on-site |
| Emergency | Urgent cover |
| Training | Training and development |
| Meeting | Team meetings, reviews |
| Break | Scheduled break period |
Example
Scenario: Create shifts for 2 staff, Monday–Friday, for one week.
- Date Range: 23/03/2026 – 27/03/2026
- Time: 09:00 – 17:00
- Type: Regular
- Staff: Dr Sarah Smith, Nurse Amy Jones
- Room: Surgery 1
Result: 5 days × 2 staff = 10 shifts created
Limits and Behaviour
- Maximum 365 shifts per template creation
- Conflicting shifts are automatically skipped (not blocked)
- Overnight shifts are supported — if end time is before start time, the system adds 1 day to the end
- A progress overlay shows real-time creation status
Copy Week
What It Does
Duplicates all shifts from a source week to a target week. Staff assignments, rooms, shift types, and notes are preserved. Status is always reset to Scheduled.
Step-by-Step
1. Select Source Week — the week to copy FROM (shows Monday start date)
2. Select Target Week — the week to copy TO (must be a different week)
3. Configure Conflict Handling
- Skip conflicting shifts (checkbox): When checked, shifts that overlap with existing shifts in the target week are silently skipped. When unchecked, if conflicts are detected, a Retry & Skip Conflicts button appears.
4. Optional Filters
| Filter | Purpose | Default |
|---|---|---|
| Staff Filter | Only copy shifts for selected staff | All staff (empty) |
| Room Filter | Only copy shifts in selected rooms | All rooms (empty) |
5. Review Copy Summary — shows the source and target week date ranges
6. Click "Copy Shifts"
What Gets Copied
| Field | Copied? | Notes |
|---|---|---|
| Staff assignment | Yes | Same staff member |
| Room assignment | Yes | Same room |
| Start/End time | Yes | Offset by the week difference |
| Shift type | Yes | Preserved |
| Notes | Yes | Preserved |
| Requirements | Yes | Deep-copied |
| Status | No | Always reset to "Scheduled" |
| Recurring settings | No | Not copied |
Conflict Handling
When conflicts are detected:
- First attempt — if "Skip conflicts" is unchecked, you see a list of conflicting shifts with a "Retry & Skip Conflicts" button
- Retry — click the button to re-run, this time skipping all conflicting shifts and creating only the non-conflicting ones
If you know the target week already has some shifts, check "Skip conflicting shifts" before copying to avoid the two-step process.
CSV Import
What It Does
Upload a CSV file containing shift data. Staff members are matched by email address or full name. Rooms are matched by name. All lookups are case-insensitive and scoped to your company.
CSV Column Reference
Your CSV must include these headers (case-insensitive, spaces and dashes are converted to underscores automatically):
| Column | Required | Format | Description |
|---|---|---|---|
date | Yes | DD/MM/YYYY or YYYY-MM-DD or DD-MM-YYYY | The calendar date of the shift |
start_time | Yes | HH:mm (24-hour) | When the shift starts |
end_time | Yes | HH:mm (24-hour) | When the shift ends |
staff_email | No | Email address | Staff member's email — used for matching |
staff_name | No | First Last | Staff member's full name — used as fallback |
room_name | No | Text | Room name — matched against your company's rooms |
shift_type | No | See types below | Defaults to regular if omitted |
notes | No | Free text (max 500 chars) | Additional information |
At least one of staff_email or staff_name should be provided per row. The system tries email first, then falls back to name. Rows without a matched staff member are either skipped or flagged as errors.
Valid shift type values (lowercase in CSV): regular, overtime, on_call, emergency, training, meeting, break
Fields Set Automatically
These are handled by the system — do not include them in your CSV:
| Field | Value |
|---|---|
| Company | Your logged-in company |
| Status | Always scheduled |
| ID | Auto-generated |
| Timestamps | Auto-set |
Download the CSV Template
Click "Download CSV Template" in the Import CSV tab. The template is pre-populated with your company's actual rooms and staff members, so you can fill it in without looking up names or room labels.
The downloaded file includes:
- The correct headers in the right order
- Example rows using your company's real staff emails, names, and room names
- Future dates (next week's Monday onwards)
Open the template in Excel or Google Sheets, replace the example rows with your shift data, and save as .csv before uploading.
Example CSV
date,start_time,end_time,staff_email,staff_name,room_name,shift_type,notes
18/03/2026,08:30,17:00,dr.smith@practice.com,Dr Sarah Smith,Surgery 1,regular,Morning surgery
18/03/2026,09:00,13:00,nurse.jones@practice.com,Nurse Amy Jones,Treatment Room,regular,Morning clinic
19/03/2026,18:00,08:00,dr.smith@practice.com,Dr Sarah Smith,,on_call,Overnight on-call
Key points:
- UK date format (
DD/MM/YYYY) is fully supported - Overnight shifts (18:00–08:00) are auto-detected — the system adds 1 day to the end time
- Room name left empty for on-call (room will be unassigned)
- Staff can be identified by email or name (email takes priority)
Step-by-Step Import
- Download Template — click "Download CSV Template" to get the file pre-populated with your company data
- Fill in your data — open in a spreadsheet, add your shifts, save as
.csv - Upload — click the upload area or drag-and-drop your file
- Review the preview — the system parses your CSV immediately and shows:
- Green checkmark = valid shifts parsed
- Red errors = rows with invalid dates, times, or missing columns (rejected)
- Yellow warnings = unresolved staff/rooms, unknown shift types (may still import)
- Preview table showing the first 5 parsed shifts
- Configure options:
- Skip rows with unresolved staff — silently skip rows where the staff member can't be found
- Skip conflicting shifts — skip shifts that overlap with existing ones
- Click "Import Shifts"
- Review results — shows created, skipped, and failed counts with error details
Common Errors
| Error | Cause | Fix |
|---|---|---|
Missing required columns: date | Wrong header names | Use exactly date, start_time, end_time |
| Invalid date format | Non-standard date (e.g., "March 18") | Use 18/03/2026 or 2026-03-18 |
| Invalid start time format | 12-hour format (e.g., "9am") | Use 09:00 (24-hour) |
| Could not resolve staff member | Email/name doesn't match active staff | Check the email or use First Last format |
| Skipped due to scheduling conflict | Staff already has a shift at that time | Enable "Skip conflicts" or change the time |
CSV Export
What It Does
Exports shifts within a date range to a CSV file. The exported file includes staff names, emails, and room names (not just IDs).
How to Use
- Open the Export function from the calendar view
- Select a date range (maximum 90 days)
- Optionally filter by specific staff or rooms
- Click Export
Exported Columns
| Column | Format | Example |
|---|---|---|
| Date | DD/MM/YYYY | 18/03/2026 |
| Day | Full name | Wednesday |
| Staff Name | First Last | Dr Sarah Smith |
| Staff Email | dr.smith@practice.com | |
| Room | Room name | Surgery 1 |
| Start Time | HH:mm | 08:30 |
| End Time | HH:mm | 17:00 |
| Shift Type | Lowercase | regular |
| Status | Lowercase | scheduled |
| Notes | Free text | Morning surgery |
All times are displayed in UK timezone (Europe/London).
Re-Importing an Exported CSV
The export format cannot be directly re-imported because the column headers differ. To re-import, rename the headers:
| Export Header | Change To |
|---|---|
| Date | date |
| Start Time | start_time |
| End Time | end_time |
| Staff Email | staff_email |
| Staff Name | staff_name |
| Room | room_name |
| Shift Type | shift_type |
| Notes | notes |
Delete the Day and Status columns before importing.
Bulk Edit
What It Does
Updates properties of multiple selected shifts at once. You can change the room, shift type, status, and/or adjust times.
How to Access
- In the calendar, enter selection mode (click "Select Multiple")
- Click on the shifts you want to edit (they highlight with a coral border)
- Click the "Bulk Edit" button that appears
- The Bulk Edit modal opens showing how many shifts are selected
Available Operations
Each operation is opt-in — tick the checkbox to enable it:
Change Room
- Select a new room from the dropdown
- Can also set to "No Room"
Change Shift Type
- Select from: Regular, Overtime, On Call, Emergency, Training, Meeting, Break
Change Status
- Select from: Scheduled, Confirmed, Cancelled
Only 3 statuses are available in bulk edit. To mark shifts as Completed, In Progress, or No Show, edit them individually.
Adjust Time
| Field | Description | Example |
|---|---|---|
| Start Time Offset (mins) | Positive = later, negative = earlier | +30 moves start 30 min later |
| End Time Offset (mins) | Positive = later, negative = earlier | -60 ends shift 1 hour earlier |
Common patterns:
- Move entire shift 30 min later: Start
+30, End+30 - Shorten shift by 1 hour at the end: Start
0, End-60 - Start 15 min earlier: Start
-15, End0
Time adjustment shifts each individual shift by the offset — it does not set all shifts to the same time.
Limits
- Maximum 100 shifts per bulk update
- All selected shifts must belong to the same company
- At least one edit option must be enabled
Keyboard Shortcuts
| Shortcut | Action | Condition |
|---|---|---|
Escape | Close the modal | Not currently processing |
Enter | Submit the current action | Focus not in an input field |
Best Practices
Template Mode
- Start small — test with a single week before creating months of shifts
- Check leave first — review approved leave in the target date range
- Select the correct room — shifts cannot be created without a room assignment
Copy Week
- Review the source week — ensure it represents the pattern you want
- Use filters — copy only relevant staff or rooms to reduce conflicts
- Check "Skip conflicts" if the target week already has some shifts
CSV Import
- Always download the template first — it's pre-populated with your company's rooms and staff
- Use UK date format —
DD/MM/YYYYworks naturally - Test with a small file — import 3–5 rows first to verify formatting
- Enable both skip options — "Skip unresolved staff" and "Skip conflicts" prevent partial failures
Bulk Edit
- Double-check your selection — review the count shown in the modal header
- Use time adjustment carefully — it applies to every selected shift
- Exit selection mode when done to avoid accidental selections
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| No shifts created | All shifts conflicted with existing ones | Enable "Skip conflicts" and review which days are already filled |
| Template shows 0 shifts in preview | No matching days in the date range | Check the day selection (Mon–Fri vs specific days) |
| CSV import rejects all rows | Wrong column headers | Download the template and use it as a base |
| Staff not found during import | Email doesn't match or staff is deactivated | Verify the email in Staff Management |
| Room not found during import | Room name doesn't match exactly | Check room names in Settings → Rooms |
| Export is empty | No shifts in the selected date range | Expand the date range or remove filters |
| Bulk edit fails | Shifts belong to different companies | Only select shifts within your company |
Related Documentation
- Calendar Overview — Calendar interface guide
- Creating Shifts — Single shift creation
- Editing Shifts — Modify existing shifts
- Conflict Resolution — Handle scheduling conflicts
- Rooms & Facilities — Manage rooms
Source Files:
src/components/calendar/BulkSchedulingTool.tsx— Bulk scheduling modal (Template, Copy Week, Import)src/components/calendar/BulkEditModal.tsx— Bulk edit modalsrc/lib/utils/csv-parser.ts— CSV parsing and template generationsrc/app/api/scheduling/shifts/import/route.ts— CSV import APIsrc/app/api/scheduling/shifts/export/route.ts— CSV export APIsrc/app/api/scheduling/shifts/copy-week/route.ts— Copy week APIsrc/app/api/scheduling/shifts/bulk-update/route.ts— Bulk update API