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:
- Personal Schedule - Your assigned shifts only
- Team View - All shifts in your company (optional)
- Calendar Navigation - Week, month, and day views
- Shift Details - Time, room, and shift type information
Accessing Your Schedule
- Navigate to Staff Portal → My Schedule from the sidebar
- The current week's shifts load by default
- 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| start_date | string | No | Start of date range (YYYY-MM-DD) |
| end_date | string | No | End of date range (YYYY-MM-DD) |
| include_all | boolean | No | Include all company shifts |
| status | string | No | Filter 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:
| Day | Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|---|
| 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
Navigating Dates
// 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
| Action | Description |
|---|---|
| Previous Week | Navigate to prior week |
| Today | Jump to current week |
| Next Week | Navigate 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:
| Element | Description |
|---|---|
| Time | Start and end time (24-hour) |
| Room | Assigned room/location |
| Type | Shift type (Standard, Night, etc.) |
| Status | Confirmed, Draft, or Cancelled |
| Duration | Total 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
| Status | Colour | Meaning |
|---|---|---|
| Confirmed | Green | Shift is scheduled |
| Draft | Grey | Tentative, not confirmed |
| Cancelled | Red | Shift 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
| Benefit | Description |
|---|---|
| Coverage Check | See who's working when |
| Swap Opportunities | Find shifts to trade |
| Coordination | Plan 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
| Filter | Options | Default |
|---|---|---|
| Status | confirmed, draft, cancelled | All |
| View | my_shifts, all_shifts | my_shifts |
| Period | day, week, month | week |
UK Date/Time Display
Time Format
All times displayed in 24-hour format (UK standard):
| Format | Example |
|---|---|
| Time | 09:00, 17:30, 22:00 |
| Duration | 8h 30m |
| Date | 14/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
| Metric | Value |
|---|---|
| Shifts This Week | 5 |
| Total Hours | 40.5 |
| Days Working | 5 |
| Days Off | 2 |
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
| Calendar | Method |
|---|---|
| Google Calendar | Add via link |
| Apple Calendar | .ics download |
| Outlook | .ics download |
Best Practices
For Viewing Your Schedule
- Check Regularly - Review your schedule daily
- Note Changes - Watch for schedule updates
- Plan Ahead - View upcoming weeks
- Verify Details - Confirm room and times
- Report Issues - Contact manager for errors
Schedule Awareness Tips
| Tip | Benefit |
|---|---|
| Check on Sunday evening | Plan your week |
| Enable notifications | Get shift reminders |
| Export important shifts | Backup in personal calendar |
| Note room assignments | Know where to report |
Troubleshooting
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Shifts not loading | Network issue | Refresh page |
| Wrong dates showing | Navigation error | Click "Today" |
| Missing shifts | Filter applied | Check status filter |
| Wrong times | Timezone issue | Verify UK time |
Error Messages
| Error | Meaning | Action |
|---|---|---|
| "No shifts found" | None scheduled | Verify date range |
| "Failed to load" | Server error | Retry later |
| "Session expired" | Login timeout | Log in again |
Related Documentation
- Shift Details - View shift information
- Shift Trading - Trade with colleagues
- Dashboard - Staff dashboard
- Clock In/Out - Time tracking
Source Files:
src/app/api/staff/shifts/route.ts- Staff shifts APIsrc/components/staff/StaffScheduleCalendar.tsx- Schedule componentsrc/lib/utils/timezone.ts- UK timezone utilitiessrc/types/shift.types.ts- Shift type definitions