Initial Commit: Duty Schedule and Attendance Logbook

This commit is contained in:
2026-03-07 10:16:28 +08:00
parent 73dc735cce
commit c6f536edeb
24 changed files with 3165 additions and 282 deletions
+30 -16
View File
@@ -21,6 +21,9 @@ final geofenceProvider = FutureProvider<GeofenceConfig?>((ref) async {
return GeofenceConfig.fromJson(setting.value);
});
/// Toggle to show/hide past schedules. Defaults to false (hide past).
final showPastSchedulesProvider = StateProvider<bool>((ref) => false);
final dutySchedulesProvider = StreamProvider<List<DutySchedule>>((ref) {
final client = ref.watch(supabaseClientProvider);
final profileAsync = ref.watch(currentProfileProvider);
@@ -29,24 +32,17 @@ final dutySchedulesProvider = StreamProvider<List<DutySchedule>>((ref) {
return Stream.value(const <DutySchedule>[]);
}
final isAdmin = profile.role == 'admin' || profile.role == 'dispatcher';
// All roles now see all schedules (RLS updated in migration)
final wrapper = StreamRecoveryWrapper<DutySchedule>(
stream: isAdmin
? client
.from('duty_schedules')
.stream(primaryKey: ['id'])
.order('start_time')
: client
.from('duty_schedules')
.stream(primaryKey: ['id'])
.eq('user_id', profile.id)
.order('start_time'),
stream: client
.from('duty_schedules')
.stream(primaryKey: ['id'])
.order('start_time'),
onPollData: () async {
final query = client.from('duty_schedules').select();
final data = isAdmin
? await query.order('start_time')
: await query.eq('user_id', profile.id).order('start_time');
final data = await client
.from('duty_schedules')
.select()
.order('start_time');
return data.map(DutySchedule.fromMap).toList();
},
fromMap: DutySchedule.fromMap,
@@ -223,6 +219,24 @@ class WorkforceController {
.eq('id', swapId);
}
Future<void> updateSchedule({
required String scheduleId,
required String userId,
required String shiftType,
required DateTime startTime,
required DateTime endTime,
}) async {
await _client
.from('duty_schedules')
.update({
'user_id': userId,
'shift_type': shiftType,
'start_time': startTime.toUtc().toIso8601String(),
'end_time': endTime.toUtc().toIso8601String(),
})
.eq('id', scheduleId);
}
String _formatDate(DateTime value) {
final date = DateTime(value.year, value.month, value.day);
final month = date.month.toString().padLeft(2, '0');