feat(geofence): enhance geofence handling with improved messaging and justification for clock-out
This commit is contained in:
@@ -978,12 +978,15 @@
|
||||
"retry": "Retry",
|
||||
"clock_in_anyway": "Clock In Anyway",
|
||||
"override_title": "Justification Required",
|
||||
"override_desc": "Your location could not be verified. Please explain why you are clocking in without location verification.",
|
||||
"override_desc": "Your location could not be verified. Please explain why you are proceeding without location verification.",
|
||||
"override_hint": "Enter your justification...",
|
||||
"override_submit": "Clock In",
|
||||
"override_submit": "Submit",
|
||||
"overridden_title": "Location Not Verified",
|
||||
"overridden_desc": "You are clocking in without location verification. Your justification has been recorded.",
|
||||
"outside_work_area_warning": "You've moved away from the work area"
|
||||
"overridden_desc": "You are proceeding without location verification. Your justification has been recorded.",
|
||||
"outside_work_area_warning": "You've moved away from the work area",
|
||||
"outside_work_area_title": "You've moved away from the work area",
|
||||
"outside_work_area_desc": "You are $distance away from your shift location. To clock out, provide a reason below.",
|
||||
"clock_out_anyway": "Clock out anyway"
|
||||
}
|
||||
},
|
||||
"availability": {
|
||||
|
||||
@@ -973,12 +973,15 @@
|
||||
"retry": "Reintentar",
|
||||
"clock_in_anyway": "Registrar Entrada",
|
||||
"override_title": "Justificación Requerida",
|
||||
"override_desc": "No se pudo verificar su ubicación. Explique por qué registra entrada sin verificación de ubicación.",
|
||||
"override_desc": "No se pudo verificar su ubicación. Explique por qué continúa sin verificación de ubicación.",
|
||||
"override_hint": "Ingrese su justificación...",
|
||||
"override_submit": "Registrar Entrada",
|
||||
"override_submit": "Enviar",
|
||||
"overridden_title": "Ubicación No Verificada",
|
||||
"overridden_desc": "Está registrando entrada sin verificación de ubicación. Su justificación ha sido registrada.",
|
||||
"outside_work_area_warning": "Te has alejado del área de trabajo"
|
||||
"overridden_desc": "Está continuando sin verificación de ubicación. Su justificación ha sido registrada.",
|
||||
"outside_work_area_warning": "Te has alejado del área de trabajo",
|
||||
"outside_work_area_title": "Te has alejado del área de trabajo",
|
||||
"outside_work_area_desc": "Estás a $distance de la ubicación de tu turno. Para registrar tu salida, proporciona una razón a continuación.",
|
||||
"clock_out_anyway": "Registrar salida de todos modos"
|
||||
}
|
||||
},
|
||||
"availability": {
|
||||
|
||||
@@ -291,6 +291,9 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState>
|
||||
longitude: location?.longitude,
|
||||
accuracyMeters: location?.accuracy,
|
||||
capturedAt: location?.timestamp,
|
||||
overrideReason: currentGeofence.isGeofenceOverridden
|
||||
? currentGeofence.overrideNotes
|
||||
: null,
|
||||
),
|
||||
);
|
||||
emit(state.copyWith(
|
||||
|
||||
@@ -134,8 +134,9 @@ class ClockInActionSection extends StatelessWidget {
|
||||
final bool hasCoordinates =
|
||||
selectedShift?.latitude != null && selectedShift?.longitude != null;
|
||||
|
||||
// Geofence only gates clock-in, never clock-out. When already
|
||||
// checked in the swipe must always be enabled for checkout.
|
||||
// Geofence gates both clock-in and clock-out. When outside the
|
||||
// geofence, the slider is locked until the worker provides a
|
||||
// justification via the override modal.
|
||||
final bool isGeofenceBlocking =
|
||||
hasCoordinates &&
|
||||
!geofenceState.isLocationVerified &&
|
||||
|
||||
@@ -91,7 +91,9 @@ class GeofenceStatusBanner extends StatelessWidget {
|
||||
// instead of the "Clock in anyway" override flow so the clock-out
|
||||
// slider remains accessible.
|
||||
if (isClockedIn) {
|
||||
return const OutsideWorkAreaBanner();
|
||||
return OutsideWorkAreaBanner(
|
||||
distanceMeters: state.distanceFromTarget!,
|
||||
);
|
||||
}
|
||||
return TooFarBanner(distanceMeters: state.distanceFromTarget!);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
|
||||
/// Non-blocking warning banner shown when the worker is already clocked in
|
||||
/// but has moved outside the geofence radius.
|
||||
import 'banner_action_button.dart';
|
||||
import 'geofence_override_modal.dart';
|
||||
|
||||
/// Warning banner shown when the worker is clocked in but has moved outside
|
||||
/// the geofence radius.
|
||||
///
|
||||
/// Unlike [TooFarBanner], this banner does not include a "Clock in anyway"
|
||||
/// action button and does not block the clock-out slider.
|
||||
/// Mirrors [TooFarBanner] with a "Clock out anyway" action that opens the
|
||||
/// [GeofenceOverrideModal] so the worker can provide justification before
|
||||
/// the clock-out slider unlocks.
|
||||
class OutsideWorkAreaBanner extends StatelessWidget {
|
||||
/// Creates an [OutsideWorkAreaBanner].
|
||||
const OutsideWorkAreaBanner({super.key});
|
||||
const OutsideWorkAreaBanner({required this.distanceMeters, super.key});
|
||||
|
||||
/// Distance from the target location in meters.
|
||||
final double distanceMeters;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -21,8 +29,17 @@ class OutsideWorkAreaBanner extends StatelessWidget {
|
||||
backgroundColor: UiColors.tagPending,
|
||||
icon: UiIcons.warning,
|
||||
iconColor: UiColors.textWarning,
|
||||
title: i18n.outside_work_area_warning,
|
||||
title: i18n.outside_work_area_title,
|
||||
titleColor: UiColors.textWarning,
|
||||
description: i18n.outside_work_area_desc(
|
||||
distance: formatDistance(distanceMeters),
|
||||
),
|
||||
descriptionColor: UiColors.textWarning,
|
||||
action: BannerActionButton(
|
||||
label: i18n.clock_out_anyway,
|
||||
color: UiColors.textWarning,
|
||||
onPressed: () => GeofenceOverrideModal.show(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user