# Product Requirements Document

## Validation Checklist

- [x] All required sections are complete
- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Problem statement is specific and measurable
- [x] Problem is validated by evidence (not assumptions)
- [x] Context → Problem → Solution flow makes sense
- [x] Every persona has at least one user journey
- [x] All MoSCoW categories addressed (Must/Should/Could/Won't)
- [x] Every feature has testable acceptance criteria
- [x] Every metric has corresponding tracking events
- [x] No feature redundancy (check for duplicates)
- [x] No contradictions between sections
- [x] No technical implementation details included
- [x] A new team member could understand this PRD

---

## Product Overview

### Vision
Empower team members to manage their work-life balance by easily requesting time off and swapping shifts with coworkers, all with real-time status updates via push notifications.

### Problem Statement
Team members currently have no self-service way to:
1. **Request time off** - They must contact managers directly (text, call, in-person), leading to missed requests, no paper trail, and delayed responses
2. **Swap shifts** - When they can't work a scheduled shift, they have to manually find coverage, often through group texts or in-person asks, which is time-consuming and unreliable
3. **Track request status** - They don't know if their request was seen, is pending, or requires action, leading to anxiety and repeated follow-ups

**Impact:**
- Managers get interrupted constantly with ad-hoc requests
- Team members miss important life events because they couldn't get coverage
- Shift swaps fall through, causing no-shows and understaffing
- No audit trail for time-off or swap history

### Value Proposition
A streamlined, mobile-first request system that:
- Lets team members submit requests in seconds from their phone
- Shows real-time status via push notifications (submitted, approved, denied)
- Enables direct shift swaps between team members with manager approval
- Provides a complete request history for transparency
- Reduces manager interruptions by batching requests for review

## User Personas

### Primary Persona: Team Member (Employee)
- **Demographics:** Ages 16-45, hourly retail/service workers, moderate smartphone proficiency
- **Goals:**
  - Get time off when needed for personal events, appointments, or rest
  - Find coverage when they can't work a scheduled shift
  - Know immediately when requests are approved or denied
- **Pain Points:**
  - Forgetting to request time off until it's too late
  - Not knowing who to ask for shift coverage
  - Uncertainty about whether their request was received or reviewed
  - Having to repeatedly follow up with managers

### Secondary Persona: Shift Lead / Manager
- **Demographics:** Ages 22-55, supervisory role, reviews and approves requests
- **Goals:**
  - Review requests efficiently without constant interruptions
  - Maintain adequate staffing levels
  - Keep team members happy and reduce turnover
- **Pain Points:**
  - Getting texts/calls at all hours about schedule changes
  - Losing track of verbal requests
  - Having to manually update schedules after approvals

## User Journey Maps

### Primary User Journey: Requesting Time Off
1. **Trigger:** Team member realizes they need a specific day(s) off for an appointment, event, or personal reason
2. **Discovery:** Opens the app, navigates to Requests section
3. **Action:** Taps "Request Time Off", selects date(s), adds optional reason, submits
4. **Confirmation:** Sees confirmation that request was submitted, receives push notification
5. **Waiting:** Request appears in "Pending" list with status
6. **Resolution:** Receives push notification when approved/denied, sees updated status in app
7. **Follow-up:** Can view request history anytime

### Secondary User Journey: Swapping a Shift
1. **Trigger:** Team member is scheduled but can't work (conflict, illness, emergency)
2. **Discovery:** Views their schedule, identifies the shift they need to swap
3. **Exploration:** Taps "Find Swap" to see team schedule and available coworkers
4. **Selection:** Selects a coworker's compatible shift to propose a swap
5. **Request:** Submits swap request, coworker receives push notification
6. **Coworker Response:** Coworker accepts or declines the swap request
7. **Manager Approval:** If coworker accepts, manager receives notification to approve
8. **Resolution:** Both team members receive push notification with final decision
9. **Schedule Update:** If approved, both schedules automatically update

### Tertiary User Journey: Viewing Team Schedule for Swap
1. **Trigger:** Team member wants to find potential swap partners
2. **Action:** Opens Team Schedule view
3. **Exploration:** Browses team members' shifts by date
4. **Filtering:** Can filter by position/role compatibility
5. **Selection:** Identifies compatible shifts for potential swap

## Feature Requirements

### Must Have Features

#### Feature 1: Day Off Request Submission
- **User Story:** As a team member, I want to request specific days off so that I can plan personal activities without manually contacting my manager
- **Acceptance Criteria:**
  - [ ] Can select single date or date range for time off
  - [ ] Can add optional reason/notes for the request
  - [ ] Request is submitted to manager for review
  - [ ] Receives confirmation on submit (in-app + push notification)
  - [ ] Request appears in pending requests list immediately

#### Feature 2: Day Off Request Status Tracking
- **User Story:** As a team member, I want to see the status of my time-off requests so that I know if I can make plans
- **Acceptance Criteria:**
  - [ ] Can view list of all submitted requests (pending, approved, denied)
  - [ ] Each request shows: dates, reason, status, submission date
  - [ ] Denied requests show manager's reason (if provided)
  - [ ] Receives push notification when status changes

#### Feature 3: Shift Swap Request
- **User Story:** As a team member, I want to request swapping my shift with a coworker so that I can get coverage when I can't work
- **Acceptance Criteria:**
  - [ ] Can initiate swap from my scheduled shift
  - [ ] Can view team schedule to find compatible shifts
  - [ ] Can select target coworker and their shift for swap proposal
  - [ ] Coworker receives push notification of swap request
  - [ ] Manager receives notification after coworker accepts
  - [ ] Both parties receive push notification of final decision

#### Feature 4: Team Schedule View
- **User Story:** As a team member, I want to view my coworkers' schedules so that I can find shifts to swap with
- **Acceptance Criteria:**
  - [ ] Can view team schedule by week (same navigation as personal schedule)
  - [ ] Shows all scheduled team members with their shifts
  - [ ] Can filter by position/role for compatible swaps
  - [ ] Clearly indicates which shifts are eligible for swap
  - [ ] Respects privacy (shows only work schedule, not personal info)

#### Feature 5: Respond to Swap Requests
- **User Story:** As a team member, I want to respond to swap requests from coworkers so that I can help them get coverage
- **Acceptance Criteria:**
  - [ ] Receives push notification when someone requests swap with me
  - [ ] Can view swap proposal details (their shift, my shift)
  - [ ] Can accept or decline the swap request
  - [ ] Can add optional note when declining
  - [ ] Requestor receives notification of my response

#### Feature 6: Push Notification Integration
- **User Story:** As a team member, I want to receive push notifications about my requests so that I don't have to constantly check the app
- **Acceptance Criteria:**
  - [ ] Notification when my day-off request is submitted (confirmation)
  - [ ] Notification when my day-off request is approved/denied
  - [ ] Notification when someone requests to swap with me
  - [ ] Notification when my swap request is accepted/declined by coworker
  - [ ] Notification when my swap request is approved/denied by manager
  - [ ] Deep links from notifications go to relevant screen
  - [ ] Notification preferences can be managed in Settings

### Should Have Features

#### Feature 7: Request History
- **User Story:** As a team member, I want to view my complete request history so that I can reference past requests
- **Acceptance Criteria:**
  - [ ] Can view all past day-off requests with outcomes
  - [ ] Can view all past swap requests with outcomes
  - [ ] Can filter by date range
  - [ ] Can filter by status (approved, denied)

#### Feature 8: Cancel Pending Request
- **User Story:** As a team member, I want to cancel a pending request if my plans change
- **Acceptance Criteria:**
  - [ ] Can cancel pending day-off request before it's reviewed
  - [ ] Can withdraw pending swap request before coworker responds
  - [ ] Manager receives notification of cancellation (if relevant)
  - [ ] Cancelled requests move to history with "cancelled" status

### Could Have Features

#### Feature 9: Recurring Time Off
- **User Story:** As a team member with regular commitments, I want to request recurring time off (e.g., every Tuesday) so I don't have to submit weekly requests
- **Acceptance Criteria:**
  - [ ] Can set recurring pattern (weekly, bi-weekly)
  - [ ] Can specify end date or number of occurrences
  - [ ] Manager can approve/deny entire series or individual dates

#### Feature 10: Shift Giveaway (No Swap Required)
- **User Story:** As a team member, I want to give away my shift without requiring a swap so that coworkers can just take it
- **Acceptance Criteria:**
  - [ ] Can post shift as "available for pickup"
  - [ ] Coworkers see it in open shifts list
  - [ ] First eligible coworker to claim gets it (manager approval required)

### Won't Have (This Phase)

- **Shift Bidding/Auction:** Competitive bidding for desirable shifts
- **Automatic Swap Matching:** AI-powered suggestions for swap partners
- **Time-Off Accrual/Balance:** Integration with PTO balance systems
- **Blackout Dates:** Manager-defined dates where no time off allowed
- **Partial Shift Swaps:** Swapping only part of a shift
- **Manager-Side UI:** Manager approval UI (handled in web app)
- **Chat Integration:** Discussion about swaps (future feature)

## Detailed Feature Specifications

### Feature: Shift Swap Request (Most Complex)
**Description:** A two-stage workflow where a team member proposes swapping their scheduled shift with a coworker's shift, the coworker responds, and then a manager approves.

**User Flow:**
1. User views their schedule and taps on a shift they want to swap
2. System shows "Find Swap" option
3. User taps "Find Swap" and sees Team Schedule for that week
4. User browses coworkers' shifts, filtering by compatible positions
5. User selects a coworker's shift and taps "Propose Swap"
6. System shows swap preview: "Your shift [details] ↔ Their shift [details]"
7. User confirms and optionally adds a message
8. System submits request and shows confirmation
9. Coworker receives push notification "Swap Request from [Name]"
10. Coworker opens notification, sees proposal, and accepts or declines
11. If accepted, manager receives push notification for approval
12. Manager approves/denies in web interface
13. Both team members receive push notification with final result
14. If approved, both schedules update automatically

**Business Rules:**
- Rule 1: Both shifts must be for the same store (typeNum)
- Rule 2: Swap can only be proposed for future shifts (not past or in-progress)
- Rule 3: User can have only one pending swap request per shift
- Rule 4: Coworker must respond within 24 hours or request auto-expires
- Rule 5: Manager approval must happen at least 4 hours before shift start
- Rule 6: Users can only swap shifts they're qualified for (position/role match)
- Rule 7: Swaps cannot result in overtime without manager approval flag

**Edge Cases:**
- Scenario 1: Coworker doesn't respond in time → Expected: Request expires, requestor notified, shift unchanged
- Scenario 2: Manager denies after coworker accepts → Expected: Both notified, shift unchanged
- Scenario 3: Either shift gets deleted before approval → Expected: Request auto-cancelled, both notified
- Scenario 4: Requestor tries to swap same shift twice → Expected: Error shown, only one active request per shift
- Scenario 5: Coworker already has shift on requested day → Expected: System checks for conflicts, warns but allows (overtime case)

### Feature: Day Off Request
**Description:** Simple submission of time-off requests with date range and optional reason.

**User Flow:**
1. User navigates to Requests tab or taps "Request Time Off" button
2. User selects start date (required)
3. User optionally selects end date (defaults to single day)
4. User optionally enters reason/notes
5. User taps "Submit Request"
6. System shows confirmation with pending status
7. User receives push notification confirming submission
8. When manager reviews, user receives push notification with result

**Business Rules:**
- Rule 1: Cannot request time off for past dates
- Rule 2: Cannot request time off less than 24 hours in advance (configurable by store)
- Rule 3: Date range must be contiguous (no gaps)
- Rule 4: Maximum request length: 14 days (configurable by store)
- Rule 5: User can have multiple pending requests for different date ranges
- Rule 6: Cannot request time off for dates where user has pending swap request

**Edge Cases:**
- Scenario 1: User has scheduled shift on requested date → Expected: Warning shown, user can still submit (manager decides)
- Scenario 2: User requests date they already have off → Expected: Warning shown, cannot submit duplicate
- Scenario 3: Overlapping requests → Expected: Error if same dates already pending, otherwise allowed
- Scenario 4: Network loss during submission → Expected: Request queued locally, auto-retry when online, duplicate prevention via idempotency key
- Scenario 5: Timezone/DST boundary (e.g., request spans DST change) → Expected: All dates processed in store timezone, not device timezone

---

## Request State Machine

### Time-Off Request States

| State | Description | Transitions From | Transitions To | Who Triggers |
|-------|-------------|------------------|----------------|--------------|
| `pending` | Submitted, awaiting manager review | (initial) | `approved`, `denied`, `cancelled` | Submit action |
| `approved` | Manager approved the request | `pending` | (terminal) | Manager action |
| `denied` | Manager denied the request | `pending` | (terminal) | Manager action |
| `cancelled` | Employee cancelled before review | `pending` | (terminal) | Employee action |

**Notifications per Transition:**
- `pending` → Employee receives "Request Submitted" confirmation
- `approved` → Employee receives "Request Approved" with dates
- `denied` → Employee receives "Request Denied" with reason (if provided)
- `cancelled` → Manager notified of cancellation (if already seen)

### Shift Swap Request States

| State | Description | Transitions From | Transitions To | Who Triggers |
|-------|-------------|------------------|----------------|--------------|
| `pending_coworker` | Awaiting coworker response | (initial) | `declined`, `pending_manager`, `expired`, `cancelled` | Submit action |
| `declined` | Coworker declined the swap | `pending_coworker` | (terminal) | Coworker action |
| `pending_manager` | Coworker accepted, awaiting manager | `pending_coworker` | `approved`, `denied`, `expired`, `cancelled` | Coworker accept |
| `approved` | Manager approved, schedules swapped | `pending_manager` | (terminal) | Manager action |
| `denied` | Manager denied the swap | `pending_manager` | (terminal) | Manager action |
| `expired` | Request timed out (24h coworker, 4h before shift for manager) | `pending_coworker`, `pending_manager` | (terminal) | System timer |
| `cancelled` | Requestor withdrew the request | `pending_coworker`, `pending_manager` | (terminal) | Employee action |
| `invalidated` | Shift deleted or employee removed | `pending_coworker`, `pending_manager` | (terminal) | System detection |

**Notifications per Transition:**
- `pending_coworker` → Requestor: "Request Sent"; Coworker: "Swap Request from [Name]"
- `declined` → Requestor: "Swap Declined by [Coworker]"
- `pending_manager` → Requestor: "Coworker Accepted, Pending Manager"; Manager: "Swap Request Needs Approval"
- `approved` → Both employees: "Swap Approved - Schedules Updated"
- `denied` → Both employees: "Swap Denied by Manager" with reason
- `expired` → Requestor: "Swap Request Expired"; Coworker (if pending_coworker): none
- `cancelled` → Coworker (if pending_coworker): "Swap Request Withdrawn"
- `invalidated` → Both employees: "Swap Request Cancelled - Shift No Longer Available"

---

## Swap Eligibility Rules

### Who Can See Team Schedule
| Rule | Description |
|------|-------------|
| **Same Store Only** | Employee can only view schedules for their currently selected store (typeNum) |
| **Active Employees Only** | Only see shifts of active (non-terminated) employees |
| **Future Shifts Only** | Only shifts that haven't started yet appear as swappable |
| **Minimal Info Display** | Shows: Employee first name, shift date/time, position. Does NOT show: last name, phone, email, personal details |

### Which Shifts Are Eligible for Swap
| Rule | Description | Validation |
|------|-------------|------------|
| **Same Store** | Both shifts must be at the same store | Backend validates `typeNum` match |
| **Future Shift** | Shift must start at least 4 hours from now | Backend validates `shift.startTime > now + 4h` |
| **Position Qualified** | Both employees must be qualified for each other's position | Backend checks `employee.qualifiedPositions` includes target shift's position |
| **No Existing Pending** | Employee can't have another pending swap for the same shift | Backend checks no `pending_*` swap exists for `shiftId` |
| **Not Same Shift** | Can't swap a shift with itself (edge case) | Client + backend validation |

### Conflicts (Hard Blocks vs Warnings)
| Scenario | Type | Behavior |
|----------|------|----------|
| Employee already scheduled at same time on target date | **Warning** | Show warning, allow submission (overtime case) |
| Employee on time-off on target shift date | **Hard Block** | Cannot submit swap request |
| Employee terminated from store | **Hard Block** | Cannot view or select their shifts |
| Target shift has <4 hours until start | **Hard Block** | Cannot initiate swap |
| Swap would exceed 40 hrs/week for either party | **Warning** | Show warning with estimated hours, allow submission |

---

## Team Schedule Visibility & Privacy

### What Employees Can See

| Data | Visible | Not Visible |
|------|---------|-------------|
| Coworker first name | ✅ | |
| Coworker last name | | ❌ |
| Shift date/time | ✅ | |
| Shift position/role | ✅ | |
| Shift duration (hours) | ✅ | |
| Coworker phone/email | | ❌ |
| Coworker profile photo | ✅ (if set) | |
| Total weekly hours | | ❌ |
| Time-off requests | | ❌ |
| Other coworker's swap requests | | ❌ |

### Access Control
- **Store Scoping:** Team schedule only shows employees assigned to the selected store
- **Role Filtering:** Can filter by position to find compatible swap partners
- **Self-Exclusion:** Own shifts don't appear in "swappable" list when browsing team schedule
- **Terminated Exclusion:** Terminated employees don't appear in team schedule

---

## Additional User Stories (Codex Review)

#### Feature 11: Approval Status Visibility
- **User Story:** As a team member, I want to see who needs to approve my request next so that I understand what's blocking my request
- **Acceptance Criteria:**
  - [ ] Pending time-off requests show "Awaiting Manager Review"
  - [ ] Swap requests show current step: "Awaiting [Coworker Name]" or "Awaiting Manager"
  - [ ] Approved/denied requests show manager name who made decision

#### Feature 12: Offline/Push Disabled Fallback
- **User Story:** As a team member with push notifications disabled, I want to still see request updates in the app so that I don't miss important decisions
- **Acceptance Criteria:**
  - [ ] App refreshes request list on screen focus (pull-to-refresh and auto-refresh)
  - [ ] Badge count on Requests tab shows pending actions
  - [ ] In-app banner shows recent status changes when app opens

---

## Error States and Messages

| Scenario | Error Message | Recovery Action |
|----------|---------------|-----------------|
| Submit time-off for past date | "Cannot request time off for past dates" | Clear date, re-select |
| Submit time-off <24h in advance | "Requests must be submitted at least 24 hours in advance" | Select later date |
| Duplicate time-off request | "You already have a pending request for these dates" | View existing request |
| Swap shift with <4h until start | "Cannot swap shifts starting in less than 4 hours" | None (blocked) |
| Swap with unqualified position | "You're not qualified for this position" | Select different shift |
| Already have pending swap for shift | "You already have a pending swap request for this shift" | View existing request |
| Network error on submit | "Unable to submit request. Check your connection and try again." | Retry button |
| Swap request expired | "This swap request has expired" | View history, create new |
| Coworker not found (terminated) | "This employee is no longer available" | Return to team schedule |

## Success Metrics

### Key Performance Indicators

**Measurement Period:** 60 days post-launch, compared to 30-day pre-launch baseline

| KPI | Target | Baseline Measurement |
|-----|--------|----------------------|
| **Adoption** | 70% of team members submit at least 1 request in first 30 days | N/A (new feature) |
| **Engagement** | Average 2.5 time-off requests per team member per month | N/A (new feature) |
| **Swap Success Rate** | 60% of swap requests result in approved swaps | N/A (new feature) |
| **Coworker Response Time** | 80% of responses within 4 hours | N/A (new feature) |
| **Quality** | <5% of approved swaps result in no-shows | Pre-launch no-show rate from scheduling data |
| **Manager Interruptions** | 30% reduction | Pre-launch survey: "How many schedule change requests do you handle per week?" |

### Guardrail Metrics

| Metric | Threshold | Action if Exceeded |
|--------|-----------|-------------------|
| **Notification Opt-Out Rate** | <15% disable request notifications | Review notification frequency, add batching |
| **Crash-Free Sessions (Requests)** | >99.5% | Investigate crashes, prioritize fixes |
| **Request Abandonment Rate** | <20% start but don't submit | Simplify form, reduce friction |
| **Expired Swap Requests** | <30% of swap requests expire | Send reminders, adjust 24h window |

### Tracking Requirements

| Event | Properties | Purpose |
|-------|------------|---------|
| `time_off_request_submitted` | `dates_count`, `has_reason`, `advance_days` | Track request patterns |
| `time_off_request_approved` | `request_id`, `response_time_hours` | Track approval rates |
| `time_off_request_denied` | `request_id`, `has_reason`, `response_time_hours` | Track denial patterns |
| `swap_request_initiated` | `days_until_shift`, `same_position` | Track swap behavior |
| `swap_request_coworker_responded` | `response_time_hours`, `accepted` | Track coworker engagement |
| `swap_request_manager_decided` | `approved`, `response_time_hours` | Track manager workflow |
| `team_schedule_viewed` | `filter_used`, `date_range` | Track discovery behavior |
| `notification_opened` | `notification_type`, `time_to_open` | Track notification effectiveness |
| `request_cancelled` | `request_type`, `reason` | Track cancellation patterns |

---

## Constraints and Assumptions

### Constraints
- **Mobile-only:** This phase focuses on team member mobile app; manager approval happens in existing web interface
- **Existing backend:** Must work with existing scheduling API structure from buyerkiosk-web
- **Push notification infrastructure:** Already implemented via FCM; this feature extends existing notification types
- **Single store context:** Requests are scoped to the user's currently selected store

### Assumptions
- Backend APIs for requests will follow existing patterns (REST, similar to open-shifts endpoints)
- Managers will continue to use web interface for approvals (no mobile manager approval this phase)
- Team members have push notifications enabled (graceful degradation to in-app polling if not)
- Store administrators have configured minimum advance notice for time-off requests
- Position/role data is available for filtering compatible swap partners

## Risks and Mitigations

| Risk | Impact | Likelihood | Mitigation |
|------|--------|------------|------------|
| Low adoption if workflow is confusing | High | Medium | User testing, clear onboarding, intuitive UI |
| Swap request spam between coworkers | Medium | Low | Rate limits, 24-hour response window, one request per shift |
| Notification fatigue from too many updates | Medium | Medium | Granular notification preferences, smart batching |
| Coworkers don't respond to swap requests | High | Medium | Expiration reminders, backup notification channels |
| Backend API latency affects UX | Medium | Low | Optimistic updates, loading states, offline queue |
| Schedule conflicts from race conditions | High | Low | Backend validation, atomic operations, conflict detection |

## Open Questions

- [x] ~~What is the minimum advance notice for time-off requests?~~ → Configurable per store, default 24 hours
- [x] ~~How long does a coworker have to respond to a swap request?~~ → 24 hours, then auto-expires
- [x] ~~Can swap requests cross position types?~~ → Only if both users are qualified for both positions
- [x] ~~Should cancelled/denied requests count toward any limits?~~ → No, only pending requests count
- [ ] What is the notification sound/priority for request updates? (Defer to notification preferences)

---

## Supporting Research

### Competitive Analysis
| App | Day Off Requests | Shift Swaps | Notifications | Notes |
|-----|------------------|-------------|---------------|-------|
| WhenIWork | Yes, basic | Yes, with approval | Push + Email | Industry standard |
| Homebase | Yes, with calendar | Yes, limited | Push | Strong mobile UX |
| 7shifts | Yes, advanced | Yes, with chat | Push + SMS | Restaurant-focused |
| Deputy | Yes, PTO tracking | Yes, marketplace | Push | Enterprise features |

**Key Learnings:**
- All competitors support push notifications for request updates (table stakes)
- Two-stage swap approval (coworker → manager) is standard
- Simple, mobile-first submission forms have highest adoption
- Request history and status visibility reduce support burden

### User Research
Based on feedback from existing BuyerKiosk users:
- "I always forget to ask for time off until it's too late" → Need easy mobile access
- "I never know if my manager saw my text" → Need status tracking and notifications
- "Finding someone to cover is the worst part of my job" → Need team schedule visibility
- "I wish I got a notification when my request was approved" → Need push notifications

### Market Data
- 78% of hourly workers prefer mobile apps for scheduling (Shiftboard Survey 2024)
- Schedule flexibility is #2 reason for job changes in retail (McKinsey 2024)
- Self-service scheduling reduces manager time on scheduling by 35% (7shifts case study)
