Shift planner
A React block (a whole screen) in Beamline's HR & payroll app.
A workplace's week of staff shifts against what it needs: a row per person with their week's hours against their contract, each day a 24-hour track with its shifts drawn from start to end (an overnight shift running into the next morning, its hours counted on the start day or split at midnight, said); above, each need's people against its count, short ones marked; a shift made or changed in place with its break as any time, in a window or at a set time, checked against the shift; conflicts that block publishing (overlaps, impossible breaks) apart from warnings (short rest, weekly hours over contract), filterable; automatic filling that proposes shifts drawn as proposals and says the needs no one could fill, waiting for accept or discard; and Publish, asked in place, with who was told.
Use it for
- Scheduling hourly staff for a shop, café, clinic or warehouse week by week against staffing needs.
- Publishing a schedule only when nothing blocks it, with proposals reviewed before they count.
Not for
- A repeating pattern and who it applies to (shift-rotations).
- Meetings and events on a calendar (team-calendar).
Anatomy
- header: the mark, <workplace> shifts, the week
- needs: per day each need (role, window) with assigned of required and proposed, short ones marked
- week: a row per person (name, role, hours this week against the contract), a cell per day with a 24-hour track (shifts as bars, yesterday's overnight spill lighter, proposals outlined, conflicts red), each shift as a button (start–end, next day), add a shift on an empty day
- editor: who and which day, From and To, the hours worked or the overnight attribution in words, A break (any time, in a window, at a set time; minutes, at, between and; paid), the break in words or what's wrong, Remove, Cancel, Save shift
- conflicts: the count and how many block, All/Blocking, each with Blocks or Warning; Overnight hours count (start day · split at midnight)
- publishing: open needs, Fill open needs, Accept n proposals / Discard, the needs no one could fill with why; the publish state and Publish the week (asked in place), who was told
States
- loading
- an overnight shift (start day or split)
- a break outside the shift, too long, window too short
- overlap (blocks), short rest (warning), over weekly hours (warning)
- needs short; proposals pending (publish waits); unfilled with reasons
- published (who was told, who couldn't be reached)
Keyboard
- Tab through the shifts and the add buttons; Enter opens the editor
- Publish asks in place: Enter confirms, Escape backs out
Motion
Words and the editor fade in; nothing moves at rest.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
people / weekStart / needs / workplace | Person[] / string / Need[] / string | — | People with role, weekly limit and least rest; the week's first day; the needs (role, window, how many). |
shifts / defaultShifts / onShiftsChange | Shift[] | — | Each shift's person, start day, start and end (an end at or before the start is the next day), role, break, and whether it is only proposed. |
attribution / defaultAttribution / onAttributionChange | "startDay" | "calendarDay" | — | Which day owns overnight hours. |
onAutoFill / onPublish | (open) => Promise<{ proposals, unfilled }> / (shifts) => Promise<{ notified, failed }> | — | onAutoFill: Propose shifts for the needs not covered; resolve with the proposals and the needs no one could fill. onPublish: Publish the week; resolve with who was told. Reject: still a draft, said. |
people (required) | Person[] | — | |
weekStart (required) | string | — | The week's first day (ISO date). |
shifts | Shift[] | — | |
defaultShifts | Shift[] | — | |
onShiftsChange | ((s: Shift[]) => void) | — | |
needs (required) | Need[] | — | What the workplace needs this week. |
attribution | Attribution | — | |
defaultAttribution | Attribution | — | |
onAttributionChange | ((a: Attribution) => void) | — | |
onAutoFill | ((openNeeds: Need[]) => Promise<{ proposals: Shift[]; unfilled: { needId: string; reaso… | — | Propose shifts for the needs not covered; resolve with the proposals and the needs no one could fill. |
onPublish | ((shifts: Shift[]) => Promise<{ notified: number; failed: number; }>) | — | Publish the week; resolve with who was told. Reject: still a draft, said. |
workplace (required) | string | — | The workplace's name. |
canManage | boolean | — | |
loading | boolean | — | |
product | string | — | |
className | string | — | Classes on the documented visual root; no override by default. |
ref | Ref<HTMLDivElement> | — | Receives the documented native target or imperative handle; omitted by default. |
Built from
- Avatar
- Button
- Checkbox
- Confirm morph
- Label
- Number field
- Segmented control
- Select
- Skeleton
- Spinner
- Switch
- Text morph
- Tooltip
Dependencies
lucide-react
Import
import { ShiftPlanner } from "@beamline/shift-planner";
Get it
Shift planner is part of Beamline UI. Install the parts you need in your React app as compiled packages or editable source. Get Beamline · Connect your agent
More in HR & payroll
- Shift rotations: Rotating shift patterns from pattern to people: a pattern of one to four weeks painted day by day with a shift template, a rest day or nothing (pick the…
- Roster publishing: The week's roster before it goes out: areas down the side and days across, each shift a chip with who works it and its hours, its state its tone (not…
- My shift: The worker's own shift on their phone: today drawn to scale (the plan's areas as blocks on an hour axis, under them what was worked: on-plan time in…
- Timesheet review: Timesheets for a manager: the day's counts at the head (scheduled, on shift, late, on break, to approve), the ones that filter being buttons, an…
- Hours ledger: One worker's pay cycle of shifts, for the worker or their payroll admin: the wall-clock span and the paid hours as separate columns, a night shift…
- Payroll run: A pay period from report to submission, one payroll account at a time (a worker on two accounts is on both runs, never combined): the workers on one…
- Payroll cycles: The client's side of an outsourced payroll across countries: every entity's current cycle on one board, its stage drawn as steps, the one thing that…
- Payroll approvals: Payroll approvals for a company paying through a payroll provider. Expenses are split by whose move it is (you, another approver, the employee answering…
- Benefit changes: An employee's benefit changes after a life event. The centre puts their turn first: each task (a proof to upload, with its deadline in the warning tint…
- Hiring pipeline: A recruiting team's pipeline across every open job. Stage groups (reviewing, interviewing, closing) are counted across jobs above job sections that fold…
- Recruiter home: A recruiter's own work, in one place. Upcoming interviews with who sits in, today's first; feedback owed, overdue first and on the danger tone, written…
- Stage reports: Reports on how applications move through stages, built from each application's stage intervals. By week: applications present in each stage (or from each…
- Link booking: A candidate's booking link for one stage of one job: a column with the job, the stage's length, who they meet (each with their role), where and what the…
- Team & members: The people page of a workspace: seats used against the plan, members and pending invitations in one list with search and a role filter, role changes that…