Skip to main content

Viewing Your Shifts

This guide covers how to view your upcoming shifts, navigate the schedule calendar, and understand shift information displayed in Shyfts.


Overview

What is the Shift View?

The shift view displays your scheduled work assignments:

  1. Personal Schedule - Your assigned shifts only
  2. Team View - All shifts in your company (optional)
  3. Calendar Navigation - Week, month, and day views
  4. Shift Details - Time, room, and shift type information

Accessing Your Schedule

  1. Navigate to Staff PortalMy Schedule from the sidebar
  2. The current week's shifts load by default
  3. Use navigation controls to change dates

Staff Shifts API

Fetch Your Shifts

Endpoint: GET /api/staff/shifts

// Source: src/app/api/staff/shifts/route.ts:25-65
const shiftsQuerySchema = z.object({
start_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
end_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
include_all: z.enum(['true', 'false']).optional().default('false'),
status: z.enum(['draft', 'confirmed', 'cancelled']).optional()
})

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoStart of date range (YYYY-MM-DD)
end_datestringNoEnd of date range (YYYY-MM-DD)
include_allbooleanNoInclude all company shifts
statusstringNoFilter by shift status

Example Request

// Fetch this week's shifts
const startDate = moment().startOf('isoWeek').format('YYYY-MM-DD')
const endDate = moment().endOf('isoWeek').format('YYYY-MM-DD')

const response = await fetch(
`/api/staff/shifts?start_date=${startDate}&end_date=${endDate}`
)

const data = await response.json()

Response Format

// Source: src/app/api/staff/shifts/route.ts:120-160
// Shifts response structure
{
success: true,
data: {
shifts: [
{
id: "shift-uuid-1",
staff_id: "staff-uuid",
company_id: "company-uuid",
room_id: "room-uuid",
start_time: "2025-01-14T09:00:00Z",
end_time: "2025-01-14T17:30:00Z",
shift_type: "standard",
status: "confirmed",
notes: "Regular shift",
is_owner: true, // Indicates this is your shift
room: {
id: "room-uuid",
name: "Consultation Room 1"
},
staff: {
id: "staff-uuid",
first_name: "John",
last_name: "Smith"
}
},
// ... more shifts
],
meta: {
total: 5,
my_shifts: 5,
period: {
start: "2025-01-13",
end: "2025-01-19"
}
}
}
}

Calendar Views

Weekly View

The default view showing your shifts for the week:

DayMonTueWedThuFriSatSun
Shifts---
// Weekly view structure
interface WeeklyView {
weekStart: string // Monday
weekEnd: string // Sunday
days: {
date: string
dayName: string
shifts: Shift[]
isToday: boolean
isPast: boolean
}[]
}

Daily View

Focus on a single day's shifts:

// Daily view request
const viewDay = async (date: string) => {
const response = await fetch(
`/api/staff/shifts?start_date=${date}&end_date=${date}`
)
return response.json()
}

Monthly View

Overview of the entire month:

// Monthly calendar generation
const generateMonthCalendar = (year: number, month: number) => {
const firstDay = moment({ year, month }).startOf('month')
const lastDay = moment({ year, month }).endOf('month')

// Start from Monday of the first week
const calendarStart = firstDay.clone().startOf('isoWeek')
const calendarEnd = lastDay.clone().endOf('isoWeek')

return {
start: calendarStart.format('YYYY-MM-DD'),
end: calendarEnd.format('YYYY-MM-DD'),
weeks: calculateWeeks(calendarStart, calendarEnd)
}
}

Schedule Navigation

// Navigation controls
const ScheduleNavigation = ({
currentDate,
onNavigate,
view
}) => {
const goToPrevious = () => {
const newDate = moment(currentDate).subtract(1, view)
onNavigate(newDate)
}

const goToNext = () => {
const newDate = moment(currentDate).add(1, view)
onNavigate(newDate)
}

const goToToday = () => {
onNavigate(moment())
}

return (
<div className="flex items-center gap-4">
<button onClick={goToPrevious}>Previous</button>
<button onClick={goToToday}>Today</button>
<button onClick={goToNext}>Next</button>
</div>
)
}

Week Navigation

ActionDescription
Previous WeekNavigate to prior week
TodayJump to current week
Next WeekNavigate to following week

Date Selection

Click on any date to view shifts for that day:

// Date click handler
const handleDateClick = (date: string) => {
setSelectedDate(date)
fetchShiftsForDate(date)
}

Shift Display

Shift Card Layout

Each shift displays:

ElementDescription
TimeStart and end time (24-hour)
RoomAssigned room/location
TypeShift type (Standard, Night, etc.)
StatusConfirmed, Draft, or Cancelled
DurationTotal hours

Shift Card Component

// Shift card display
const ShiftCard = ({ shift }) => (
<div className={`card-glass p-4 border-l-4 ${getStatusBorderColor(shift.status)}`}>
<div className="flex justify-between items-start">
<div>
<div className="font-semibold">
{formatTime(shift.start_time)} - {formatTime(shift.end_time)}
</div>
<div className="text-secondary-text">
{shift.room?.name || 'No room assigned'}
</div>
</div>
<StatusBadge status={shift.status} />
</div>
<div className="mt-2 text-sm">
<span className="text-secondary-text">Type:</span> {shift.shift_type}
</div>
{shift.notes && (
<div className="mt-2 text-sm text-secondary-text">
{shift.notes}
</div>
)}
</div>
)

Status Colours

StatusColourMeaning
ConfirmedGreenShift is scheduled
DraftGreyTentative, not confirmed
CancelledRedShift was cancelled

Team Schedule View

Viewing All Shifts

To see all company shifts (not just yours):

// Fetch all company shifts
const fetchTeamSchedule = async (startDate: string, endDate: string) => {
const response = await fetch(
`/api/staff/shifts?start_date=${startDate}&end_date=${endDate}&include_all=true`
)
return response.json()
}

Team View Benefits

BenefitDescription
Coverage CheckSee who's working when
Swap OpportunitiesFind shifts to trade
CoordinationPlan with colleagues

Ownership Indicator

// Response includes is_owner flag
{
id: "shift-uuid",
staff_id: "colleague-uuid",
is_owner: false, // Not your shift
// ... other fields
}

Filtering Shifts

By Status

// Filter by shift status
const getConfirmedShifts = () => {
return fetch(`/api/staff/shifts?status=confirmed`)
}

const getDraftShifts = () => {
return fetch(`/api/staff/shifts?status=draft`)
}

By Date Range

// Custom date range
const getShiftsInRange = (start: string, end: string) => {
return fetch(`/api/staff/shifts?start_date=${start}&end_date=${end}`)
}

Filter Options

FilterOptionsDefault
Statusconfirmed, draft, cancelledAll
Viewmy_shifts, all_shiftsmy_shifts
Periodday, week, monthweek

UK Date/Time Display

Time Format

All times displayed in 24-hour format (UK standard):

FormatExample
Time09:00, 17:30, 22:00
Duration8h 30m
Date14/01/2025

Timezone Handling

// Source: src/lib/utils/timezone.ts
export const UK_TIMEZONE = 'Europe/London'

// Format shift time for display
const formatShiftTime = (utcTime: string): string => {
return moment.tz(utcTime, UK_TIMEZONE).format('HH:mm')
}

// Format shift date for display
const formatShiftDate = (utcTime: string): string => {
return moment.tz(utcTime, UK_TIMEZONE).format('DD/MM/YYYY')
}

Shift Summary

Weekly Summary

// Weekly summary statistics
interface WeeklySummary {
totalShifts: number
totalHours: number
daysWorking: number
daysOff: number
shifts: Shift[]
}

const calculateWeeklySummary = (shifts: Shift[]): WeeklySummary => {
const totalHours = shifts.reduce((sum, shift) => {
const duration = moment(shift.end_time).diff(moment(shift.start_time), 'hours', true)
return sum + duration
}, 0)

const workingDays = new Set(shifts.map(s =>
moment(s.start_time).format('YYYY-MM-DD')
)).size

return {
totalShifts: shifts.length,
totalHours: Math.round(totalHours * 10) / 10,
daysWorking: workingDays,
daysOff: 7 - workingDays,
shifts
}
}

Summary Display

MetricValue
Shifts This Week5
Total Hours40.5
Days Working5
Days Off2

Empty States

No Shifts Scheduled

When you have no shifts:

// Empty state component
const NoShiftsDisplay = ({ period }) => (
<div className="card-glass p-8 text-center">
<Calendar className="w-12 h-12 mx-auto text-secondary-text" />
<h3 className="mt-4 font-semibold">No Shifts Scheduled</h3>
<p className="text-secondary-text mt-2">
You don't have any shifts scheduled for {period}.
</p>
<p className="text-sm text-secondary-text mt-1">
Contact your manager if you believe this is incorrect.
</p>
</div>
)

Future Date

// Future date message
const FutureDateNote = () => (
<div className="text-sm text-secondary-text">
Shifts may be added or changed. Check back closer to the date.
</div>
)

Mobile View

Responsive Schedule

On mobile devices:

  • Shifts displayed as stacked cards
  • Swipe navigation between days/weeks
  • Touch-friendly 44px+ targets
  • Simplified day headers

Mobile Navigation

// Mobile swipe navigation
const MobileSchedule = ({ shifts, currentDate }) => {
const handleSwipeLeft = () => navigateToNextDay()
const handleSwipeRight = () => navigateToPreviousDay()

return (
<div
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
className="mobile-schedule"
>
<DayHeader date={currentDate} />
<ShiftList shifts={getShiftsForDay(currentDate)} />
</div>
)
}

Calendar Integration

Export to External Calendar

Export shifts to your personal calendar:

// Generate iCal format
const generateICalEvent = (shift: Shift): string => {
return `BEGIN:VEVENT
DTSTART:${moment(shift.start_time).format('YYYYMMDDTHHmmss')}Z
DTEND:${moment(shift.end_time).format('YYYYMMDDTHHmmss')}Z
SUMMARY:Work Shift - ${shift.room?.name || 'TBC'}
LOCATION:${shift.room?.name || ''}
DESCRIPTION:${shift.notes || 'Work shift'}
END:VEVENT`
}

Supported Calendars

CalendarMethod
Google CalendarAdd via link
Apple Calendar.ics download
Outlook.ics download

Best Practices

For Viewing Your Schedule

  1. Check Regularly - Review your schedule daily
  2. Note Changes - Watch for schedule updates
  3. Plan Ahead - View upcoming weeks
  4. Verify Details - Confirm room and times
  5. Report Issues - Contact manager for errors

Schedule Awareness Tips

TipBenefit
Check on Sunday eveningPlan your week
Enable notificationsGet shift reminders
Export important shiftsBackup in personal calendar
Note room assignmentsKnow where to report

Troubleshooting

Common Issues

IssueCauseSolution
Shifts not loadingNetwork issueRefresh page
Wrong dates showingNavigation errorClick "Today"
Missing shiftsFilter appliedCheck status filter
Wrong timesTimezone issueVerify UK time

Error Messages

ErrorMeaningAction
"No shifts found"None scheduledVerify date range
"Failed to load"Server errorRetry later
"Session expired"Login timeoutLog in again


Source Files:

  • src/app/api/staff/shifts/route.ts - Staff shifts API
  • src/components/staff/StaffScheduleCalendar.tsx - Schedule component
  • src/lib/utils/timezone.ts - UK timezone utilities
  • src/types/shift.types.ts - Shift type definitions