Review Timesheets
The admin surface for every user's time entries — filter, approve, reject, edit, create manually, and export.
Review Timesheets
This is the manager's view of every clock-in and clock-out across the tenant. It's where you approve hours before payroll, correct missed clocks, reject bogus entries, and drill into the geolocation detail on any row.
The page lives at Time & Payroll → Timesheets → Review Entries. It's visible only to users with the admin or fleet_manager role (or dazzle-staff super admins).
Aggregate cards
A strip of four cards sits at the top and reflects the currently filtered set of entries — not the tenant total. Apply a filter and the numbers follow.
| Card | What it shows |
|---|---|
| Payable hours | Sum of total_minutes − break_minutes across the filtered rows, in hours |
| Active people | Distinct users in the filtered set |
| Approved | Count of approved entries, plus pending count in the hint row |
| Flagged | Count of entries carrying at least one flag, plus rejected count |
Filters
The filter bar supports:
| Filter | Notes |
|---|---|
| Employee | Async user picker — type to search by name or email |
| Approval | Pending / Approved / Rejected / All (defaults to Pending for the inbox workflow) |
| Status | Active / Completed / Cancelled / All |
| From / To | Inclusive date range applied to clock_in_at |
| Flagged only | Restrict to entries where flags is non-empty |
The URL doesn't reflect the filter state — bookmark-friendly filter links aren't built yet. Hit Reset to clear everything except the default pending filter.
Table columns
| Column | What it means |
|---|---|
| User | Display name + email. Click a row to open the detail drawer. |
| Date / Clock in / Clock out | Plain wall-clock, localised to the browser. |
| Duration | total_minutes as Xh Ym. |
| Break | break_minutes as Xh Ym. |
| Payable | Bolded total − break. This is what feeds the payroll calculation. |
| Site | Name of the nearest geofenced site at clock-in, if any. |
| Flags | Orange badge with a count. Hover to see which flags. |
| Approval | Badge (Pending / Approved / Rejected) + a lock icon if the entry is frozen by a locked pay period. |
Selecting rows
Tick the header checkbox to select every visible row; individual checkboxes toggle a single row. When anything is selected a sticky action bar appears at the top with Approve, Reject, and Clear — those fire against the Custom POST /api/{tenant}/time-entries/bulk-approve endpoint and skip locked entries silently.
Bulk approve and reject both accept an optional note that gets stamped on every affected entry as approval_notes. The UI doesn't currently prompt for that note — the note is only set when you reject a single entry from the drawer.
The detail drawer
Click any row and a right-hand drawer slides in with:
- Approval badge + status badge + flag badges — every flag is shown as a separate pill so it's obvious why an entry needs attention.
- Metadata grid — Clock in / Clock out / Duration / Break / Payable / Site.
- Map — a Leaflet tile view centred on the fix. Clock-in and clock-out pins are both drawn; a dashed blue line connects them if they differ. The configured site's geofence is drawn as a translucent green circle. Under the map, the raw coordinates and the accuracy radius (±N m) appear as small text.
- Notes blocks — the worker's note on one line and the most recent review note on another, stamped with the reviewer name.
- Action buttons — Edit, Approve, Reject, Delete. Approve and Reject both flip the approval status and stamp
approved_by_id+approved_at. Edit opens the edit dialog. Delete is a destructive; confirm before it fires. All four are disabled once the entry is locked.
Editing an entry
The edit dialog lets a manager change:
- Clock in / Clock out — datetime-local inputs. Duration is recomputed on save.
- Unpaid break (minutes) — deducted from duration when calculating payable.
- Notes — free text.
Owners of an entry can also edit their own, but only while the entry is still pending_approval and isn't locked. Managers can edit any entry that isn't locked.
Editing an approved entry after it's been approved reverts it to pending? No — by design, the current implementation leaves the approval state intact, so this is a trust-the-admin flow. Rejecting and re-editing is the explicit path if you want to reset approval.
Manual entry
For missed clocks. Click Manual entry in the page header to open the dialog. You pick:
- Employee — any user in the tenant
- Clock in / Clock out — datetime-local pickers; clock-out must be after clock-in
- Unpaid break (minutes)
- Notes
The entry is created with status = completed, approval_status = pending_approval, and a manual_entry flag so reviewers can tell it wasn't captured live. Geo columns stay null — there's nothing to record.
The flag catalogue
| Flag | Fired when |
|---|---|
low_accuracy | Clock-in GPS fix had accuracy > 100 m |
low_accuracy_out | Same threshold at clock-out |
outside_geofence | The nearest site with a configured geofence radius was further than that radius from the clock-in fix |
long_shift | total_minutes ≥ 16 × 60 — usually a forgotten clock-out |
manual_entry | Created via the Manual entry dialog, not via the clock button |
Accuracy and geofence checks run on clock-in and clock-out independently. A shift can pick up both low_accuracy and low_accuracy_out.
Deleting
Admins and fleet managers can delete any unlocked entry. The row disappears and the audit trail stores the deletion. Locked entries (i.e. contained in a locked pay period) cannot be deleted — reopen the pay period first.
Export CSV
The Export CSV button at the top downloads the currently filtered rows to a CSV. Columns: id, user, clock-in, clock-out, total minutes, break minutes, payable hours, approval status, site, flags (comma-joined), notes.
This is distinct from the pay-period payroll CSV — that one has gross-pay columns and only counts approved, locked entries. See Pay Periods.