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 Portal → My 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