import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../models/app_settings.dart'; import '../models/duty_schedule.dart'; import '../models/swap_request.dart'; import 'profile_provider.dart'; import 'supabase_provider.dart'; final geofenceProvider = FutureProvider((ref) async { final client = ref.watch(supabaseClientProvider); final data = await client .from('app_settings') .select() .eq('key', 'geofence') .maybeSingle(); if (data == null) return null; final setting = AppSetting.fromMap(data); return GeofenceConfig.fromJson(setting.value); }); final dutySchedulesProvider = StreamProvider>((ref) { final client = ref.watch(supabaseClientProvider); final profileAsync = ref.watch(currentProfileProvider); final profile = profileAsync.valueOrNull; if (profile == null) { return Stream.value(const []); } final isAdmin = profile.role == 'admin' || profile.role == 'dispatcher'; final base = client.from('duty_schedules').stream(primaryKey: ['id']); if (isAdmin) { return base .order('start_time') .map((rows) => rows.map(DutySchedule.fromMap).toList()); } return base .eq('user_id', profile.id) .order('start_time') .map((rows) => rows.map(DutySchedule.fromMap).toList()); }); final swapRequestsProvider = StreamProvider>((ref) { final client = ref.watch(supabaseClientProvider); final profileAsync = ref.watch(currentProfileProvider); final profile = profileAsync.valueOrNull; if (profile == null) { return Stream.value(const []); } final isAdmin = profile.role == 'admin' || profile.role == 'dispatcher'; final base = client.from('swap_requests').stream(primaryKey: ['id']); if (isAdmin) { return base .order('created_at', ascending: false) .map((rows) => rows.map(SwapRequest.fromMap).toList()); } return base .order('created_at', ascending: false) .map( (rows) => rows .where( (row) => row['requester_id'] == profile.id || row['recipient_id'] == profile.id, ) .map(SwapRequest.fromMap) .toList(), ); }); final workforceControllerProvider = Provider((ref) { final client = ref.watch(supabaseClientProvider); return WorkforceController(client); }); class WorkforceController { WorkforceController(this._client); final SupabaseClient _client; Future generateSchedule({ required DateTime startDate, required DateTime endDate, }) async { await _client.rpc( 'generate_duty_schedule', params: { 'start_date': _formatDate(startDate), 'end_date': _formatDate(endDate), }, ); } Future insertSchedules(List> schedules) async { if (schedules.isEmpty) return; await _client.from('duty_schedules').insert(schedules); } Future checkIn({ required String dutyScheduleId, required double lat, required double lng, }) async { final data = await _client.rpc( 'duty_check_in', params: {'p_duty_id': dutyScheduleId, 'p_lat': lat, 'p_lng': lng}, ); return data as String?; } Future requestSwap({ required String shiftId, required String recipientId, }) async { final data = await _client.rpc( 'request_shift_swap', params: {'p_shift_id': shiftId, 'p_recipient_id': recipientId}, ); return data as String?; } Future respondSwap({ required String swapId, required String action, }) async { await _client.rpc( 'respond_shift_swap', params: {'p_swap_id': swapId, 'p_action': action}, ); } String _formatDate(DateTime value) { final date = DateTime(value.year, value.month, value.day); final month = date.month.toString().padLeft(2, '0'); final day = date.day.toString().padLeft(2, '0'); return '${date.year}-$month-$day'; } }