Complete guide to requesting time off, managing PTO requests, approval workflows, and tracking analytics in XShift AI. Learn employee request process, manager review, and PTO management best practices.
Understanding XShift AI time-off request and approval workflow
Employees can REQUEST time off for vacation, sick leave, personal days, or other reasons
Managers can REVIEW and APPROVE/DENY requests with optional comments
3 request statuses: Pending, Approved, Denied
Auto-refresh every 30 seconds to catch status updates in real-time
Complete audit trail with submission dates, review dates, and manager comments
Employee dashboard shows:
- Stats cards: Pending requests, Approved requests, Days taken this year
- Request form modal for submitting new requests
- Complete history of all past requests with status
Manager dashboard shows:
- Filter tabs: All, Pending, Approved, Denied
- Table view with all employee requests
- Review modal for approve/deny actions
- 3 analytics charts: PTO distribution, monthly trends, top requesters
Step-by-step process for submitting time-off requests
Step 1: Navigate to Time Off page
- Access: /{orgId}/employee-timeoff
- Available to: All EMPLOYEE role users
Step 2: Click "Request Time Off" button
- Location: Top right of page
- Icon: Plus icon with "Request Time Off" label
- Button color: Blue (bg-blue-600)
Step 3: Request Form Modal appears
- Modal title: "Request Time Off"
- Modal background: Semi-transparent gray overlay
- Form fields shown below
Step 4: Fill out form fields
Field 1: Type (required dropdown)
- Options:
• Vacation
• Sick Leave
• Personal
• Other
- Default: Vacation selected
Field 2: Start Date (required)
- Type: Date picker (calendar input)
- Format: YYYY-MM-DD
- Validation: Cannot be empty
Field 3: End Date (required)
- Type: Date picker
- Validation: Must be on or after start date
Field 4: Reason (required)
- Type: Textarea (3 rows)
- Placeholder: "Please provide a reason for your time off request..."
- Validation: Cannot be empty
- Purpose: Helps manager understand context
Step 5: Submit or Cancel
- Cancel button: Gray background, closes modal without saving
- Submit button: Blue background, submits request
Step 6: Confirmation
- Success: Alert "Request submitted successfully!"
- Modal closes automatically
- Request appears in list with status: PENDING (yellow)
- Stats cards update: "Pending Requests" count increases by 1
API Endpoint: POST /api/orgs/{orgId}/pto/requests
Request body format:
{
"type": "vacation" | "sick" | "personal" | "other",
"startDate": "YYYY-MM-DD",
"endDate": "YYYY-MM-DD",
"reason": "string"
}
Response on success:
- HTTP 200 OK
- Request saved to database with status: PENDING
- Employee receives confirmation
Response on error:
- HTTP 400/500 with error message
- Alert shown: "Failed to submit request: {error}"
Tracking your time-off requests and their approval status
Card 1: Pending Requests
- Icon: Yellow clock icon
- Label: "Pending Requests"
- Value: Count of requests with status = PENDING
- Color: Yellow (text-yellow-600)
Card 2: Approved Requests
- Icon: Green checkmark icon
- Label: "Approved Requests"
- Value: Count of requests with status = APPROVED
- Color: Green (text-green-600)
Card 3: Days Taken This Year
- Icon: Purple calendar icon
- Label: "Days Taken This Year"
- Value: Total days from approved requests
- Calculation: Sum of (endDate - startDate + 1) for all approved requests
- Color: Purple (text-purple-600)
Section title: "Time Off Requests"
Layout: Vertical list of cards
Each request card shows:
Header section:
- Status icon: Clock (pending), Checkmark (approved), X (denied)
- Type label: "Vacation", "Sick Leave", "Personal", or "Other"
- Date range: "Jan 25, 2024 - Jan 27, 2024" format
- Status badge: Colored pill in top right
Body section:
- Reason: Bold "Reason:" label + your submitted reason
- Submitted: Submission timestamp
- Reviewed: Review timestamp (if reviewed) + reviewer name
- Manager Comments: Shown in red if present (denial reasons)
Status badge colors:
- Pending: Yellow background (bg-yellow-100), yellow text (text-yellow-800)
- Approved: Green background (bg-green-100), green text (text-green-800)
- Denied: Red background (bg-red-100), red text (text-red-800)
Frequency: Every 30 seconds
What it does: Automatically reloads request list to catch status updates
Why it matters:
- When manager approves/denies your request, you see it within 30 seconds
- No need to manually refresh the page
- Status badges, stats cards, and list all update automatically
Technical: setInterval calls loadRequests() every 30000ms
- File: employee-timeoff/page.tsx lines 86-90
Shown when: No time-off requests have been submitted yet
Display:
- Large gray calendar icon (h-12 w-12)
- Heading: "No time off requests"
- Subtext: "You haven't submitted any time off requests yet."
- Centered layout
Manager dashboard for reviewing employee time-off requests
URL: /{orgId}/timeoff
Required role: MANAGER or HEAD_MANAGER
Page title: "Time Off Requests"
Subtitle: "Manage employee time off requests and approvals"
Dashboard sections:
1. Filter tabs (top)
2. Requests table (main content)
3. PTO Analytics charts (bottom)
Tab 1: All
- Shows: All requests regardless of status
- Use case: Complete overview
Tab 2: Pending
- Shows: Only requests with status = PENDING
- Default tab: Opens by default when page loads
- Use case: See what needs your review
Tab 3: Approved
- Shows: Only requests with status = APPROVED
- Use case: See upcoming/past time off
Tab 4: Denied
- Shows: Only requests with status = DENIED
- Use case: Review denied requests and reasons
Visual design:
- Active tab: Blue background (bg-blue-100), blue text (text-blue-700)
- Inactive tabs: Gray background (bg-gray-100), gray text
- Hover effect: Darker gray on hover
- Icon: Funnel icon (Filter) shown before tabs
Viewing and managing employee requests in table format
Column 1: Employee
- Shows: Employee full name
- Font: Medium weight (font-medium)
- Color: Dark gray
Column 2: Type
- Shows: Badge with request type
- Colors:
• Vacation: Blue badge (bg-blue-100, text-blue-600)
• Sick: Red badge (bg-red-100, text-red-600)
• Personal: Purple badge (bg-purple-100, text-purple-600)
• Other: Gray badge (bg-gray-100, text-gray-600)
Column 3: Dates
- Shows: Start date - End date
- Format: "1/25/2024 - 1/27/2024"
- Uses browser locale formatting
Column 4: Reason
- Shows: Truncated reason text
- Max width: max-w-xs with truncate
- Hover to see full text
Column 5: Status
- Shows: Colored status badge
- Same colors as employee view (yellow/green/red)
Column 6: Actions
- Pending requests: Blue "Review" button
- Approved/Denied: Gray "Completed" text (no action)
Row hover: Background changes to light gray (hover:bg-gray-50)
Responsive: Horizontal scroll on small screens
Header styling: Gray background (bg-gray-50), uppercase labels
Empty state: Shows when filtered list is empty
Reviewing individual requests and making approval decisions
Trigger: Click "Review" button on any pending request
Modal title: "Review Time Off Request"
Background: Semi-transparent gray overlay (bg-gray-600 bg-opacity-50)
Modal position: Centered, top offset (relative top-20)
Field 1: Employee
- Label: "Employee" (gray, font-medium)
- Value: Employee full name
Field 2: Type
- Label: "Type"
- Value: Request type capitalized (e.g., "Vacation")
Field 3: Dates
- Label: "Dates"
- Value: Start date - End date in locale format
Field 4: Reason
- Label: "Reason"
- Value: Full reason text submitted by employee
- Style: Small text (text-sm)
Label: "Manager Comment"
Type: Textarea (3 rows)
Placeholder: "Add a comment (optional)"
Purpose: Provide context for approval or explanation for denial
Usage:
- Optional for approvals
- Recommended for denials (helps employee understand why)
- Comment is stored and shown to employee in their request history
Button 1: Cancel
- Position: Left
- Color: Gray (bg-gray-100)
- Action: Closes modal without saving
- Clears comment field
Button 2: Deny
- Position: Middle
- Color: Red (bg-red-600)
- Icon: X circle icon
- Action: Denies the request
Button 3: Approve
- Position: Right
- Color: Green (bg-green-600)
- Icon: Checkmark circle icon
- Action: Approves the request
API workflows for approving and denying requests
API Endpoint: POST /api/orgs/{orgId}/time-off/{requestId}/approve
Request body:
{
"comment": "optional manager comment"
}
What happens:
1. Request status updated to APPROVED
2. reviewedAt timestamp set to current time
3. reviewedBy set to manager ID
4. Manager comment saved (if provided)
5. Employee sees status change within 30 seconds (auto-refresh)
6. Email notification sent to employee (if enabled)
Success response:
- HTTP 200 OK
- Modal closes
- Requests table refreshes
- Request moves from "Pending" to "Approved" filter
API Endpoint: POST /api/orgs/{orgId}/time-off/{requestId}/deny
Request body:
{
"comment": "manager comment explaining denial"
}
Validation: Comment field is optional in UI but recommended
What happens:
1. Request status updated to DENIED
2. reviewedAt timestamp set
3. reviewedBy set to manager ID
4. Manager comment saved (shown in red to employee)
5. Employee notified via auto-refresh
6. Email notification sent
Success response:
- HTTP 200 OK
- Modal closes
- Request moves to "Denied" filter
Best practice: Always provide a comment when denying to explain why
Visual analytics for tracking PTO trends and patterns
Title: "📊 PTO Distribution by Type"
Chart type: Donut/Pie chart with gradient fills
Data source: ALL requests (not just approved)
Breakdown:
- Vacation requests: Blue gradient
- Sick leave requests: Red gradient
- Personal requests: Purple gradient
- Other requests: Gray gradient
Labels show: Type name + percentage
- Example: "Vacation (45%)"
Tooltip: Shows exact count
- Example: "15 requests"
Legend: Bottom, circular icons
Empty state: "No time off requests yet" if no data
Title: "📈 Monthly PTO Trend (Last 6 Months)"
Chart type: Area chart with gradient fill
Data source: APPROVED requests only from last 6 months
X-axis: Month labels (e.g., "Dec 2025", "Jan 2026")
Y-axis: Request count (integer values only)
Visual design:
- Line color: Primary blue
- Fill: Gradient from blue (top) to transparent (bottom)
- Line thickness: 3px
- Grid: Dotted lines (3 3 pattern)
Tooltip: Shows "{count} requests" and "Approved PTO" label
Sorting: Chronological order (oldest to newest)
Empty state: "No approved requests in the last 6 months"
Use case: Identify busy PTO periods, plan coverage
Title: "👥 Top Employees by PTO Requests"
Chart type: Horizontal bar chart
Data source: ALL requests, shows top 5 employees
Y-axis: Employee names (120px width)
X-axis: Request count
Bars:
- Color: Gradient from secondary color
- Rounded corners on right side
- Animation: 1-second slide-in
Sorting: Descending by request count
- Most requests at top
Tooltip: "{count} requests" for each employee
Empty state: "No time off requests yet"
Use case: Identify employees who request time off frequently
How employees and managers stay informed about request status changes
Frequency: Every 30 seconds
What updates:
- Request status badges (pending → approved/denied)
- Stats cards (pending count, approved count)
- Request list (new reviews appear)
- Manager comments (shown when available)
Technical implementation:
- useEffect hook with setInterval
- Calls loadRequests() every 30000ms
- Cleans up interval on component unmount
User experience:
- No page reload needed
- Silent background update
- New data appears seamlessly
Request submitted:
- Sent to: Manager
- Subject: "New Time Off Request from {employee}"
- Content: Employee name, dates, type, reason
Request approved:
- Sent to: Employee
- Subject: "Time Off Request Approved"
- Content: Dates, type, manager comment (if any)
Request denied:
- Sent to: Employee
- Subject: "Time Off Request Denied"
- Content: Dates, type, denial reason from manager comment
Note: Email notifications depend on organization notification settings
Recommendations for effective time-off management
1. Submit requests early
- Give managers time to plan coverage
- Recommended: At least 1-2 weeks in advance
2. Provide clear reasons
- Helps manager understand context
- Increases approval likelihood
3. Check status regularly
- Page auto-refreshes every 30 seconds
- Look for manager comments (especially if denied)
4. Use correct request type
- Vacation: Planned time off
- Sick: Illness or medical appointments
- Personal: Personal matters, family emergencies
- Other: Anything else
5. Track your balance
- Check "Days Taken This Year" stat card
- Know your organization's PTO policy
1. Review requests promptly
- Check "Pending" tab daily
- Don't leave employees waiting
2. Always comment when denying
- Explain why the request was denied
- Suggest alternative dates if possible
- Be professional and respectful
3. Use analytics to plan staffing
- Check "Monthly PTO Trend" for busy periods
- Identify patterns in "PTO Distribution by Type"
- Monitor "Top Employees" for fairness
4. Consider coverage before approving
- Check if other employees are off same dates
- Ensure minimum staffing levels
5. Be consistent and fair
- Apply same standards to all employees
- Document denial reasons clearly
6. Set clear PTO policies
- Communicate blackout dates (e.g., holidays, busy seasons)
- Define notice requirements
- Explain approval criteria
Solutions to common time-off request problems
Problem: Submitted request doesn't appear in list
Solutions:
1. Wait 30 seconds for auto-refresh
2. Manually refresh page (F5)
3. Check if you got success alert "Request submitted successfully!"
4. Look in browser console for errors
5. Contact manager if issue persists
Common causes:
1. Missing required fields
- All 4 fields are required (type, start date, end date, reason)
2. End date before start date
- End date must be same as or after start date
3. Network connection issue
- Check internet connection
Solutions:
- Fill out all fields completely
- Verify date logic
- Try again or contact support
Problem: Request shows "Pending" for days
Causes:
- Manager hasn't reviewed yet
- Manager missed notification
Solutions:
1. Follow up with manager directly
2. Send reminder email/message
3. Check if manager has access to timeoff page
Problem: Stats cards show wrong counts
Solutions:
1. Wait for 30-second auto-refresh
2. Hard refresh page (Ctrl+Shift+R)
3. Clear browser cache
4. Log out and log back in
Problem: Analytics charts show empty or don't render
Causes:
1. No data yet (new organization)
2. Browser doesn't support chart library
Solutions:
- If no data: Charts will populate after requests are submitted
- If technical: Try different browser (Chrome, Edge, Firefox)
- Clear cache and reload
XShift AI automates PTO tracking, approvals, and analytics so you can focus on your team.