import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../models/leave_of_absence.dart'; import 'profile_provider.dart'; import 'supabase_provider.dart'; import 'stream_recovery.dart'; import 'realtime_controller.dart'; /// All visible leaves (own for standard, all for admin/dispatcher/it_staff). final leavesProvider = StreamProvider>((ref) { final client = ref.watch(supabaseClientProvider); final profileAsync = ref.watch(currentProfileProvider); final profile = profileAsync.valueOrNull; if (profile == null) return Stream.value(const []); final hasFullAccess = profile.role == 'admin' || profile.role == 'dispatcher' || profile.role == 'it_staff'; final wrapper = StreamRecoveryWrapper( stream: hasFullAccess ? client .from('leave_of_absence') .stream(primaryKey: ['id']) .order('start_time', ascending: false) : client .from('leave_of_absence') .stream(primaryKey: ['id']) .eq('user_id', profile.id) .order('start_time', ascending: false), onPollData: () async { final query = client.from('leave_of_absence').select(); final data = hasFullAccess ? await query.order('start_time', ascending: false) : await query .eq('user_id', profile.id) .order('start_time', ascending: false); return data.map(LeaveOfAbsence.fromMap).toList(); }, fromMap: LeaveOfAbsence.fromMap, channelName: 'leave_of_absence', onStatusChanged: ref.read(realtimeControllerProvider).handleChannelStatus, ); ref.onDispose(wrapper.dispose); return wrapper.stream.map((result) => result.data); }); final leaveControllerProvider = Provider((ref) { final client = ref.watch(supabaseClientProvider); return LeaveController(client); }); class LeaveController { LeaveController(this._client); final SupabaseClient _client; /// File a leave of absence for the current user. /// Caller controls auto-approval based on role policy. Future fileLeave({ required String leaveType, required String justification, required DateTime startTime, required DateTime endTime, required bool autoApprove, }) async { final uid = _client.auth.currentUser!.id; await _client.from('leave_of_absence').insert({ 'user_id': uid, 'leave_type': leaveType, 'justification': justification, 'start_time': startTime.toIso8601String(), 'end_time': endTime.toIso8601String(), 'status': autoApprove ? 'approved' : 'pending', 'filed_by': uid, }); } /// Approve a leave request. Future approveLeave(String leaveId) async { await _client .from('leave_of_absence') .update({'status': 'approved'}) .eq('id', leaveId); } /// Reject a leave request. Future rejectLeave(String leaveId) async { await _client .from('leave_of_absence') .update({'status': 'rejected'}) .eq('id', leaveId); } /// Cancel an approved leave. Future cancelLeave(String leaveId) async { await _client .from('leave_of_absence') .update({'status': 'cancelled'}) .eq('id', leaveId); } }