feat(clock_in): add messages for already clocked in/out states and handle API call failures
This commit is contained in:
@@ -204,29 +204,49 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState>
|
||||
action: () async {
|
||||
final DeviceLocation? location = geofenceState.currentLocation;
|
||||
|
||||
final AttendanceStatus newStatus = await _clockIn(
|
||||
ClockInArguments(
|
||||
shiftId: event.shiftId,
|
||||
notes: event.notes,
|
||||
latitude: location?.latitude,
|
||||
longitude: location?.longitude,
|
||||
accuracyMeters: location?.accuracy,
|
||||
capturedAt: location?.timestamp,
|
||||
overrideReason: geofenceState.isGeofenceOverridden
|
||||
? geofenceState.overrideNotes
|
||||
: null,
|
||||
),
|
||||
);
|
||||
emit(state.copyWith(
|
||||
status: ClockInStatus.success,
|
||||
attendance: newStatus,
|
||||
));
|
||||
try {
|
||||
final AttendanceStatus newStatus = await _clockIn(
|
||||
ClockInArguments(
|
||||
shiftId: event.shiftId,
|
||||
notes: event.notes,
|
||||
latitude: location?.latitude,
|
||||
longitude: location?.longitude,
|
||||
accuracyMeters: location?.accuracy,
|
||||
capturedAt: location?.timestamp,
|
||||
overrideReason: geofenceState.isGeofenceOverridden
|
||||
? geofenceState.overrideNotes
|
||||
: null,
|
||||
),
|
||||
);
|
||||
emit(state.copyWith(
|
||||
status: ClockInStatus.success,
|
||||
attendance: newStatus,
|
||||
));
|
||||
|
||||
// Start background tracking after successful clock-in.
|
||||
_dispatchBackgroundTrackingStarted(
|
||||
event: event,
|
||||
activeShiftId: newStatus.activeShiftId,
|
||||
);
|
||||
// Start background tracking after successful clock-in.
|
||||
_dispatchBackgroundTrackingStarted(
|
||||
event: event,
|
||||
activeShiftId: newStatus.activeShiftId,
|
||||
);
|
||||
} on AppException catch (_) {
|
||||
// The clock-in API call failed. Re-fetch attendance status to
|
||||
// reconcile: if the worker is already clocked in (e.g. duplicate
|
||||
// session from Postgres constraint 23505), treat it as success.
|
||||
final AttendanceStatus currentStatus = await _getAttendanceStatus();
|
||||
if (currentStatus.isClockedIn) {
|
||||
emit(state.copyWith(
|
||||
status: ClockInStatus.success,
|
||||
attendance: currentStatus,
|
||||
));
|
||||
_dispatchBackgroundTrackingStarted(
|
||||
event: event,
|
||||
activeShiftId: currentStatus.activeShiftId,
|
||||
);
|
||||
} else {
|
||||
// Worker is genuinely not clocked in — surface the error.
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: (String errorKey) => state.copyWith(
|
||||
status: ClockInStatus.failure,
|
||||
@@ -261,29 +281,51 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState>
|
||||
final GeofenceState currentGeofence = _geofenceBloc.state;
|
||||
final DeviceLocation? location = currentGeofence.currentLocation;
|
||||
|
||||
final AttendanceStatus newStatus = await _clockOut(
|
||||
ClockOutArguments(
|
||||
notes: event.notes,
|
||||
breakTimeMinutes: event.breakTimeMinutes,
|
||||
shiftId: activeShiftId,
|
||||
latitude: location?.latitude,
|
||||
longitude: location?.longitude,
|
||||
accuracyMeters: location?.accuracy,
|
||||
capturedAt: location?.timestamp,
|
||||
),
|
||||
);
|
||||
emit(state.copyWith(
|
||||
status: ClockInStatus.success,
|
||||
attendance: newStatus,
|
||||
));
|
||||
try {
|
||||
final AttendanceStatus newStatus = await _clockOut(
|
||||
ClockOutArguments(
|
||||
notes: event.notes,
|
||||
breakTimeMinutes: event.breakTimeMinutes,
|
||||
shiftId: activeShiftId,
|
||||
latitude: location?.latitude,
|
||||
longitude: location?.longitude,
|
||||
accuracyMeters: location?.accuracy,
|
||||
capturedAt: location?.timestamp,
|
||||
),
|
||||
);
|
||||
emit(state.copyWith(
|
||||
status: ClockInStatus.success,
|
||||
attendance: newStatus,
|
||||
));
|
||||
|
||||
// Stop background tracking after successful clock-out.
|
||||
_geofenceBloc.add(
|
||||
BackgroundTrackingStopped(
|
||||
clockOutTitle: event.clockOutTitle,
|
||||
clockOutBody: event.clockOutBody,
|
||||
),
|
||||
);
|
||||
// Stop background tracking after successful clock-out.
|
||||
_geofenceBloc.add(
|
||||
BackgroundTrackingStopped(
|
||||
clockOutTitle: event.clockOutTitle,
|
||||
clockOutBody: event.clockOutBody,
|
||||
),
|
||||
);
|
||||
} on AppException catch (_) {
|
||||
// The clock-out API call failed. Re-fetch attendance status to
|
||||
// reconcile: if the worker is already clocked out (e.g. duplicate
|
||||
// end-session), treat it as success.
|
||||
final AttendanceStatus currentStatus = await _getAttendanceStatus();
|
||||
if (!currentStatus.isClockedIn) {
|
||||
emit(state.copyWith(
|
||||
status: ClockInStatus.success,
|
||||
attendance: currentStatus,
|
||||
));
|
||||
_geofenceBloc.add(
|
||||
BackgroundTrackingStopped(
|
||||
clockOutTitle: event.clockOutTitle,
|
||||
clockOutBody: event.clockOutBody,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Worker is still clocked in — surface the error.
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: (String errorKey) => state.copyWith(
|
||||
status: ClockInStatus.failure,
|
||||
|
||||
Reference in New Issue
Block a user