Add staff reliability stats & shift location
Introduce staff reliability statistics and location fields across domain, data, and UI. Changes include:
- New API endpoint StaffEndpoints.profileStats ('/staff/profile/stats').
- New domain entity StaffReliabilityStats with JSON (de)serialization and export.
- Profile repository: getReliabilityStats implementation and interface addition.
- New GetReliabilityStatsUseCase and DI registration in StaffProfileModule.
- ProfileCubit/state: load and store reliabilityStats; UI wired to display ReliabilityStatsCard and ReliabilityScoreBar using state values.
- Coverage/shift updates: Added AssignedWorker.hasReview to track if a worker was reviewed; added locationName/locationAddress to ShiftWithWorkers and show location in ShiftHeader; hide rate button if worker.hasReview.
- Clock-in handling: treat backend ALREADY_CLOCKED_IN (409) as idempotent by re-fetching attendance and emitting success when appropriate.
These changes wire backend stats through repository/usecase/cubit to the profile UI and add shift location and review-awareness to client views.
This commit is contained in:
@@ -228,12 +228,20 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState>
|
||||
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.
|
||||
} on AppException catch (e) {
|
||||
// The backend returns 409 ALREADY_CLOCKED_IN when the worker has
|
||||
// an active attendance session. This is a normal idempotency
|
||||
// signal — re-fetch the authoritative status and emit success
|
||||
// without surfacing an error snackbar.
|
||||
final bool isAlreadyClockedIn =
|
||||
e is ApiException && e.apiCode == 'ALREADY_CLOCKED_IN';
|
||||
|
||||
// Re-fetch attendance status to reconcile local state with
|
||||
// the backend (handles both ALREADY_CLOCKED_IN and legacy
|
||||
// Postgres constraint 23505 duplicates).
|
||||
final AttendanceStatus currentStatus = await _getAttendanceStatus();
|
||||
if (currentStatus.isClockedIn) {
|
||||
|
||||
if (isAlreadyClockedIn || currentStatus.isClockedIn) {
|
||||
emit(state.copyWith(
|
||||
status: ClockInStatus.success,
|
||||
attendance: currentStatus,
|
||||
|
||||
Reference in New Issue
Block a user