Swap Accept, Reject and Escalate
This commit is contained in:
@@ -40,6 +40,45 @@ final dutySchedulesProvider = StreamProvider<List<DutySchedule>>((ref) {
|
||||
.map((rows) => rows.map(DutySchedule.fromMap).toList());
|
||||
});
|
||||
|
||||
/// Fetch duty schedules by a list of IDs (used by UI when swap requests reference
|
||||
/// schedules that are not included in the current user's `dutySchedulesProvider`).
|
||||
final dutySchedulesByIdsProvider =
|
||||
FutureProvider.family<List<DutySchedule>, List<String>>((ref, ids) async {
|
||||
if (ids.isEmpty) return const <DutySchedule>[];
|
||||
final client = ref.watch(supabaseClientProvider);
|
||||
final quoted = ids.map((id) => '"$id"').join(',');
|
||||
final inList = '($quoted)';
|
||||
final rows =
|
||||
await client
|
||||
.from('duty_schedules')
|
||||
.select()
|
||||
.filter('id', 'in', inList)
|
||||
as List<dynamic>;
|
||||
return rows
|
||||
.map((r) => DutySchedule.fromMap(r as Map<String, dynamic>))
|
||||
.toList();
|
||||
});
|
||||
|
||||
/// Fetch upcoming duty schedules for a specific user (used by swap UI to
|
||||
/// let the requester pick a concrete target shift owned by the recipient).
|
||||
final dutySchedulesForUserProvider =
|
||||
FutureProvider.family<List<DutySchedule>, String>((ref, userId) async {
|
||||
final client = ref.watch(supabaseClientProvider);
|
||||
final nowIso = DateTime.now().toUtc().toIso8601String();
|
||||
final rows =
|
||||
await client
|
||||
.from('duty_schedules')
|
||||
.select()
|
||||
.eq('user_id', userId)
|
||||
/* exclude past schedules by ensuring the shift has not ended */
|
||||
.gte('end_time', nowIso)
|
||||
.order('start_time')
|
||||
as List<dynamic>;
|
||||
return rows
|
||||
.map((r) => DutySchedule.fromMap(r as Map<String, dynamic>))
|
||||
.toList();
|
||||
});
|
||||
|
||||
final swapRequestsProvider = StreamProvider<List<SwapRequest>>((ref) {
|
||||
final client = ref.watch(supabaseClientProvider);
|
||||
final profileAsync = ref.watch(currentProfileProvider);
|
||||
@@ -110,12 +149,17 @@ class WorkforceController {
|
||||
}
|
||||
|
||||
Future<String?> requestSwap({
|
||||
required String shiftId,
|
||||
required String requesterScheduleId,
|
||||
required String targetScheduleId,
|
||||
required String recipientId,
|
||||
}) async {
|
||||
final data = await _client.rpc(
|
||||
'request_shift_swap',
|
||||
params: {'p_shift_id': shiftId, 'p_recipient_id': recipientId},
|
||||
params: {
|
||||
'p_shift_id': requesterScheduleId,
|
||||
'p_target_shift_id': targetScheduleId,
|
||||
'p_recipient_id': recipientId,
|
||||
},
|
||||
);
|
||||
return data as String?;
|
||||
}
|
||||
@@ -130,6 +174,23 @@ class WorkforceController {
|
||||
);
|
||||
}
|
||||
|
||||
/// Reassign the recipient of a swap request. Only admins/dispatchers are
|
||||
/// expected to call this; the DB RLS and RPCs will additionally enforce rules.
|
||||
Future<void> reassignSwap({
|
||||
required String swapId,
|
||||
required String newRecipientId,
|
||||
}) async {
|
||||
// Prefer using an RPC for server-side validation, but update directly here
|
||||
await _client
|
||||
.from('swap_requests')
|
||||
.update({
|
||||
'recipient_id': newRecipientId,
|
||||
'status': 'pending',
|
||||
'updated_at': DateTime.now().toUtc().toIso8601String(),
|
||||
})
|
||||
.eq('id', swapId);
|
||||
}
|
||||
|
||||
String _formatDate(DateTime value) {
|
||||
final date = DateTime(value.year, value.month, value.day);
|
||||
final month = date.month.toString().padLeft(2, '0');
|
||||
|
||||
Reference in New Issue
Block a user