# Hours ledger

A React block (a whole screen) in [Beamline](https://beamline.io/)'s [HR & payroll](https://beamline.io/components/apps/hr-payroll) app. Live demo: https://beamline.io/components/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 carrying its time zone on both ends, and a night across a clock change saying it ran an hour longer or shorter than the clock shows (and paid as it ran); a break not recorded is said, never read as none. Totals count from the rows shown (all, pending, approved, rejected), each status in its tone. The cycle's cutoff is said in the header: before it a shift is changed in a sheet and goes back as pending (a refusal kept with its reason), after it the closed shift stays as paid and a change becomes an adjustment request with a reason, linked to the shift with its reference.

## Use it for

- A worker's or admin's view of one pay cycle's shifts, before and after its cutoff.
- Hours paid by the clock where night shifts and clock changes must come out right.

## Not for

- A manager's day of sheets with planned and worked areas ([timesheet-review](https://beamline.io/components/timesheet-review)).
- Planning who works when ([shift-planner](https://beamline.io/components/shift-planner)).
- A company's pay run from hours to submission ([payroll-run](https://beamline.io/components/payroll-run)).

## Anatomy

- header: the product's mark, the worker and role, the cutoff (open with a clock, closed with a lock)
- toolbar: All, Pending, Approved, Rejected; the time zone
- totals: paid hours of the rows shown, and approved, pending, rejected hours
- table: date, clock span (zones on a night shift, next day, the clock change, an adjustment asked), break, paid hours, status, Change or Ask to adjust
- sheet: from, to, break; the paid hours before and after; why (after the cutoff); Save or Ask for the adjustment

## States

- loading; no shifts; no shifts match
- a shift: pending, approved, rejected; a night shift; across a clock change (longer or shorter); break not recorded; an adjustment asked
- before the cutoff: changing, saving, saved as pending, refused (draft kept)
- after the cutoff: asking needs a reason, sending, asked with its reference, refused (draft kept)
- phone: the table scrolls sideways
- right to left: mirrors

## Keyboard

- Tab through the filter, each shift's Change or Ask to adjust; the sheet's times are spinbuttons (arrows step them)

## Motion

None of its own.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `worker` (required) | `string` | — |  |
| `role` | `string` | — |  |
| `cycle` (required) | `string` | — | The cycle in words ("Oct 16 – 31"). |
| `timeZone` (required) | `string` | — | IANA zone the shifts were worked in; times and the cutoff are shown in it. |
| `cutoff` (required) | `string` | — | The cycle's cutoff (ISO instant): before it a shift is changed, after it an adjustment is asked for. |
| `shifts` (required) | `LedgerShift[] \| null` | — | Shifts in the cycle; null while loading. |
| `onChange` | `((id: string, change: ShiftChange) => Promise<LedgerShift>)` | — | Change a shift before the cutoff; resolve with it as saved, reject to keep it (said). |
| `onAdjust` | `((id: string, change: ShiftChange) => Promise<{ reference: string; }>)` | — | Ask for an adjustment of a closed shift; resolve with the request's reference. |
| `now` | `string` | — | The moment the ledger is read at (ISO instant); defaults to now. |
| `defaultFilter` | `"all" \| "approved" \| "pending" \| "rejected"` | — |  |
| `product` | `string` | — | Your product's name, shown as its mark. |
| `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](https://beamline.io/components/avatar.md)
- [Button](https://beamline.io/components/button.md)
- [Empty state](https://beamline.io/components/empty-state.md)
- [Label](https://beamline.io/components/label.md)
- [Number field](https://beamline.io/components/number-field.md)
- [Segmented control](https://beamline.io/components/segmented-control.md)
- [Select](https://beamline.io/components/select.md)
- [Sheet](https://beamline.io/components/sheet.md)
- [Skeleton](https://beamline.io/components/skeleton.md)
- [Spinner](https://beamline.io/components/spinner.md)
- [Text morph](https://beamline.io/components/text-morph.md)
- [Textarea](https://beamline.io/components/textarea.md)
- [Time picker](https://beamline.io/components/time-picker.md)
- [Tooltip](https://beamline.io/components/tooltip.md)

## Dependencies

`lucide-react`

## Import

```tsx
import { HoursLedger } from "@beamline/hours-ledger";
```

## Get it

Hours ledger is part of Beamline UI. Install the parts you need in your React app as compiled packages or editable source. [Get Beamline](https://beamline.io/checkout?pack=complete) · [Connect your agent](https://beamline.io/connect)

## More in HR & payroll

- [Shift planner](https://beamline.io/components/shift-planner): 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…
- [Shift rotations](https://beamline.io/components/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](https://beamline.io/components/roster-publish): 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](https://beamline.io/components/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](https://beamline.io/components/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…
- [Payroll run](https://beamline.io/components/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](https://beamline.io/components/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](https://beamline.io/components/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](https://beamline.io/components/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](https://beamline.io/components/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](https://beamline.io/components/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](https://beamline.io/components/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](https://beamline.io/components/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](https://beamline.io/components/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…

Part of [Beamline UI: polished, editable React components and complete screens for custom applications](https://beamline.io/). [Build your own style from any look; tokens, fonts, radii, motion; not only colours](https://beamline.io/docs/customize).
