Guards & people
Shift swap workflow
Guard initiates from their shift detail page; you approve from the inbox.
Guard side: open the shift detail page, tap "Trade" — either offers to a specific guard or leaves it as an open offer.
Dispatcher side: /dashboard/shifts/trades has tabs for PENDING / ACCEPTED / DECLINED / ALL. Each pending row has Approve / Decline (with reason). Approving runs the compliance check on the receiving guard before reassigning the shift in a single $transaction.
Open offers (no toGuardId) appear in /guard/open-shifts for any qualified guard to claim.