Skip to main content

Break Tracking

This guide covers how to record breaks during your shift, including automatic break calculations, break policies, and best practices for accurate time tracking.


Overview

What is Break Tracking?

Break tracking ensures accurate working hours calculation:

  1. Break Recording - Log breaks taken during shifts
  2. Automatic Deduction - Breaks deducted from total hours
  3. Policy Compliance - Ensure legal break requirements met
  4. Accurate Payroll - Correct pay calculation

Break Types

TypeTypical DurationPaid/Unpaid
Lunch Break30-60 minutesUsually unpaid
Tea/Coffee Break10-15 minutesUsually paid
Rest Break20 minutesLegally required
Personal BreakVariableDepends on policy

Recording Breaks

Method 1: At Clock Out

The simplest method is recording total break time when clocking out:

  1. Click Clock Out on the Time Clock widget
  2. Enter total break time in minutes
  3. Add notes if needed
  4. Confirm to save
// Clock out with break duration
const response = await fetch(`/api/staff/timesheet/entries/${entryId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
clock_out_time: '2025-01-14T17:30:00Z',
break_duration: 45, // 45 minutes total break
notes: '30 min lunch + 15 min afternoon break'
})
})

Method 2: Start/End Break

For real-time break tracking:

  1. Click Start Break when taking a break
  2. The timer shows break duration
  3. Click End Break when returning
  4. Break time automatically recorded

Method 3: Edit After Clock Out

If you forgot to record breaks:

  1. Go to TimesheetView Entries
  2. Find the relevant entry
  3. Click Edit
  4. Add break duration
  5. Save changes

Break Duration Validation

Minimum and Maximum Limits

// Source: src/app/api/staff/timesheet/entries/route.ts:70-78
const breakDurationSchema = z.number()
.min(0, 'Break duration cannot be negative')
.max(480, 'Break duration cannot exceed 8 hours')
.optional()

Validation Rules

RuleLimitReason
Minimum0 minutesCannot be negative
Maximum480 minutes (8 hours)Cannot exceed shift length
Shift Check< Total shiftBreak must be less than shift

Break vs Shift Validation

// Ensure break doesn't exceed shift duration
const validateBreakDuration = (
clockIn: string,
clockOut: string,
breakMinutes: number
): boolean => {
const shiftDuration = moment(clockOut).diff(moment(clockIn), 'minutes')

if (breakMinutes >= shiftDuration) {
throw new Error('Break duration cannot exceed shift duration')
}

return true
}

Automatic Break Rules

Policy-Based Breaks

Some companies have automatic break policies:

// Automatic break calculation example
const calculateAutoBreak = (shiftHours: number): number => {
// Example policy: 30 min break for shifts over 6 hours
if (shiftHours >= 6) {
return 30 // 30 minutes
}
// 15 min break for shifts 4-6 hours
if (shiftHours >= 4) {
return 15
}
return 0 // No automatic break
}
Shift LengthRequired BreakNotes
< 6 hoursNone requiredAt employer discretion
6+ hours20 minutes minimumUninterrupted rest break
Long shiftsAdditional breaksAs per policy

Break Time Calculation

How Breaks Affect Total Hours

// Source: src/app/api/staff/timesheet/entries/route.ts:120-145
// Total hours = Shift duration - Break duration
const calculateWorkingHours = (entry: TimeEntry): number => {
const clockIn = moment.tz(entry.clock_in_time, UK_TIMEZONE)
const clockOut = moment.tz(entry.clock_out_time, UK_TIMEZONE)

// Raw shift duration in hours
const shiftHours = clockOut.diff(clockIn, 'hours', true)

// Break duration in hours
const breakHours = (entry.break_duration || 0) / 60

// Net working hours
const workingHours = shiftHours - breakHours

return Math.round(workingHours * 100) / 100
}

Example Calculations

ShiftClock InClock OutRaw HoursBreakNet Hours
Morning09:0013:004.000 min4.00
Full Day09:0017:308.5030 min8.00
Long Shift08:0020:0012.0060 min11.00

Break Recording Interface

Time Clock Widget

// Break recording component structure
interface BreakRecording {
entryId: string
breakDuration: number // minutes
breakNotes?: string
}

// Display break input
const BreakInput = ({ value, onChange }) => (
<div className="space-y-2">
<label className="text-sm font-medium">Break Duration (minutes)</label>
<input
type="number"
min={0}
max={480}
value={value}
onChange={(e) => onChange(parseInt(e.target.value))}
className="form-input"
placeholder="Enter break time in minutes"
/>
<p className="text-xs text-secondary-text">
Total break time taken during this shift
</p>
</div>
)

Quick Break Presets

PresetDurationUse Case
No Break0 minShort shifts
Tea Break15 minQuick break
Lunch30 minStandard lunch
Extended Lunch60 minLong lunch break

Multiple Breaks

Recording Multiple Breaks

When taking multiple breaks, record the total:

// Example: Recording multiple breaks
const breaks = [
{ type: 'morning tea', duration: 15 },
{ type: 'lunch', duration: 30 },
{ type: 'afternoon tea', duration: 15 }
]

const totalBreakMinutes = breaks.reduce((sum, b) => sum + b.duration, 0)
// Result: 60 minutes total

// Record total in time entry
await updateTimeEntry(entryId, {
break_duration: totalBreakMinutes,
notes: 'Morning tea (15), Lunch (30), Afternoon tea (15)'
})

Break Notes

Use notes to detail break breakdown:

Good NotesBad Notes
"30 min lunch, 15 min afternoon break""45 min"
"Two 20-minute breaks""breaks"
"Extended lunch - 60 min (approved)"""

Break Policies

Company Break Policies

Companies may have specific break policies:

// Break policy configuration
interface BreakPolicy {
minimumShiftForBreak: number // hours
mandatoryBreakDuration: number // minutes
paidBreaks: boolean
maxBreakDuration: number // minutes
autoApplyBreaks: boolean
}

// Example GP Practice policy
const gpPracticeBreakPolicy: BreakPolicy = {
minimumShiftForBreak: 6,
mandatoryBreakDuration: 30,
paidBreaks: false,
maxBreakDuration: 60,
autoApplyBreaks: false
}

Industry-Specific Guidelines

IndustryTypical Policy
GP Practice30 min unpaid lunch for 6+ hour shifts
RestaurantStaggered breaks during service
DentalBetween patient appointments
OfficeFlexible break timing

Editing Break Records

Modifying Break Duration

To edit a previously recorded break:

// Update break duration
const updateBreak = async (entryId: string, newBreakMinutes: number) => {
const response = await fetch(`/api/staff/timesheet/entries/${entryId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
break_duration: newBreakMinutes,
notes: 'Updated break duration'
})
})

return response.json()
}

Edit Restrictions

Entry StatusCan Edit Break?
Draft✅ Yes
Submitted❌ No - recall first
Approved❌ No - contact manager
Rejected✅ Yes - then resubmit

Break Time Display

Timesheet View

ColumnFormatExample
BreakMinutes30 min
BreakHours:Minutes0:30
PercentageOf shift5.9%

Summary Statistics

// Calculate break statistics for period
const calculateBreakStats = (entries: TimeEntry[]) => {
const totalBreakMinutes = entries.reduce(
(sum, e) => sum + (e.break_duration || 0), 0
)

const averageBreak = totalBreakMinutes / entries.length

return {
totalBreakMinutes,
averageBreakMinutes: Math.round(averageBreak),
totalBreakHours: Math.round(totalBreakMinutes / 60 * 10) / 10
}
}

Best Practices

For Accurate Break Recording

  1. Record Immediately - Log breaks as you take them
  2. Be Precise - Round to nearest 5 minutes
  3. Include All Breaks - Tea, lunch, personal
  4. Add Context - Note reason for extended breaks
  5. Review Daily - Check entries before end of day

Break Timing Tips

TipBenefit
Set break remindersDon't forget to log
Use presetsQuick recording
Check policyEnsure compliance
Track patternsOptimise scheduling

Troubleshooting

Common Issues

IssueCauseSolution
"Break exceeds shift"Break longer than shiftReduce break duration
Break not savedForm not submittedClick save/confirm
Wrong break recordedEntry errorEdit the time entry
Break missing from hoursNot includedAdd break duration

Error Messages

ErrorMeaningAction
"Break duration cannot be negative"Negative value enteredEnter positive number
"Break duration cannot exceed 8 hours"Value too largeCheck break minutes
"Break duration exceeds shift"Break > shift lengthReduce break time
"Entry is submitted"Cannot edit submittedRecall entry first

Compliance Considerations

RequirementDetails
6+ hour shifts20 minutes uninterrupted break
Young workers30 minutes if shift > 4.5 hours
Workplace rest11 consecutive hours between shifts
Weekly rest24 hours uninterrupted per week

Recording for Compliance

// Check legal break compliance
const checkBreakCompliance = (entry: TimeEntry): ComplianceResult => {
const shiftHours = calculateShiftHours(entry)
const breakMinutes = entry.break_duration || 0

const warnings = []

// Check 6+ hour shift has 20 min break
if (shiftHours >= 6 && breakMinutes < 20) {
warnings.push('Shifts over 6 hours require minimum 20 minute break')
}

return {
compliant: warnings.length === 0,
warnings
}
}


Source Files:

  • src/app/api/staff/timesheet/entries/route.ts - Time entries API
  • src/lib/validation/timesheet.schemas.ts - Break validation schemas
  • src/components/staff/BreakRecorder.tsx - Break recording component
  • src/lib/utils/time-calculations.ts - Time calculation utilities