Workforce rotation settings and location permission handling

This commit is contained in:
2026-03-08 17:31:39 +08:00
parent ce82a88e04
commit 8bf0dc13d7
8 changed files with 1200 additions and 26 deletions
+55 -2
View File
@@ -23,6 +23,7 @@ import '../../providers/whereabouts_provider.dart';
import '../../providers/workforce_provider.dart';
import '../../theme/m3_motion.dart';
import '../../utils/app_time.dart';
import '../../utils/location_permission.dart';
import '../../widgets/face_verification_overlay.dart';
import '../../utils/snackbar.dart';
import '../../widgets/gemini_animated_text_field.dart';
@@ -409,8 +410,21 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
),
Switch(
value: allowTracking,
onChanged: (v) =>
ref.read(whereaboutsControllerProvider).setTracking(v),
onChanged: (v) async {
if (v) {
final granted = await ensureLocationPermission();
if (!granted) {
if (context.mounted) {
showWarningSnackBar(
context,
'Location permission is required.',
);
}
return;
}
}
ref.read(whereaboutsControllerProvider).setTracking(v);
},
),
],
),
@@ -810,6 +824,17 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
Future<void> _handleCheckIn(DutySchedule schedule) async {
setState(() => _loading = true);
try {
// Ensure location permission before check-in
final locGranted = await ensureLocationPermission();
if (!locGranted) {
if (mounted) {
showWarningSnackBar(
context,
'Location permission is required for check-in.',
);
}
return;
}
final geoCfg = await ref.read(geofenceProvider.future);
final position = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
@@ -849,6 +874,8 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
lat: position.latitude,
lng: position.longitude,
);
// Update live position immediately on check-in
ref.read(whereaboutsControllerProvider).updatePositionNow();
if (mounted) {
setState(() {
_justCheckedIn.add(schedule.id);
@@ -869,6 +896,17 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
Future<void> _handleCheckOut(AttendanceLog log, {String? scheduleId}) async {
setState(() => _loading = true);
try {
// Ensure location permission before check-out
final locGranted = await ensureLocationPermission();
if (!locGranted) {
if (mounted) {
showWarningSnackBar(
context,
'Location permission is required for check-out.',
);
}
return;
}
final position = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
@@ -881,6 +919,8 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
lat: position.latitude,
lng: position.longitude,
);
// Update live position immediately on check-out
ref.read(whereaboutsControllerProvider).updatePositionNow();
if (mounted) {
setState(() {
if (scheduleId != null) {
@@ -904,6 +944,17 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
Future<void> _handleCheckOutById(String logId, {String? scheduleId}) async {
setState(() => _loading = true);
try {
// Ensure location permission before check-out
final locGranted = await ensureLocationPermission();
if (!locGranted) {
if (mounted) {
showWarningSnackBar(
context,
'Location permission is required for check-out.',
);
}
return;
}
final position = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
@@ -916,6 +967,8 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
lat: position.latitude,
lng: position.longitude,
);
// Update live position immediately on check-out
ref.read(whereaboutsControllerProvider).updatePositionNow();
if (mounted) {
setState(() {
if (scheduleId != null) {