Fix: Resolve critical linting issues and bugs (concurrency, syntax, dead code)

This commit is contained in:
2026-02-10 19:12:01 +05:30
parent 5e7bf0d5c0
commit 7570ffa3b9
46 changed files with 4057 additions and 1299 deletions

View File

@@ -1,5 +1,6 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:geolocator/geolocator.dart';
import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';
import '../../domain/usecases/get_todays_shift_usecase.dart';
import '../../domain/usecases/get_attendance_status_usecase.dart';
@@ -10,8 +11,8 @@ import '../../domain/arguments/clock_out_arguments.dart';
import 'clock_in_event.dart';
import 'clock_in_state.dart';
class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
class ClockInBloc extends Bloc<ClockInEvent, ClockInState>
with BlocErrorHandler<ClockInState> {
ClockInBloc({
required GetTodaysShiftUseCase getTodaysShift,
required GetAttendanceStatusUseCase getAttendanceStatus,
@@ -47,92 +48,105 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
Emitter<ClockInState> emit,
) async {
emit(state.copyWith(status: ClockInStatus.loading));
try {
final List<Shift> shifts = await _getTodaysShift();
final AttendanceStatus status = await _getAttendanceStatus();
await handleError(
emit: emit,
action: () async {
final List<Shift> shifts = await _getTodaysShift();
final AttendanceStatus status = await _getAttendanceStatus();
// Check permissions silently on load? Maybe better to wait for user interaction or specific event
// However, if shift exists, we might want to check permission state
Shift? selectedShift;
if (shifts.isNotEmpty) {
if (status.activeShiftId != null) {
try {
selectedShift =
shifts.firstWhere((Shift s) => s.id == status.activeShiftId);
} catch (_) {}
Shift? selectedShift;
if (shifts.isNotEmpty) {
if (status.activeShiftId != null) {
try {
selectedShift =
shifts.firstWhere((Shift s) => s.id == status.activeShiftId);
} catch (_) {}
}
selectedShift ??= shifts.last;
}
selectedShift ??= shifts.last;
}
emit(state.copyWith(
status: ClockInStatus.success,
todayShifts: shifts,
selectedShift: selectedShift,
attendance: status,
));
emit(state.copyWith(
status: ClockInStatus.success,
todayShifts: shifts,
selectedShift: selectedShift,
attendance: status,
));
if (selectedShift != null && !status.isCheckedIn) {
add(RequestLocationPermission());
}
} catch (e) {
emit(state.copyWith(
if (selectedShift != null && !status.isCheckedIn) {
add(RequestLocationPermission());
}
},
onError: (String errorKey) => state.copyWith(
status: ClockInStatus.failure,
errorMessage: e.toString(),
));
}
errorMessage: errorKey,
),
);
}
Future<void> _onRequestLocationPermission(
RequestLocationPermission event,
Emitter<ClockInState> emit,
) async {
try {
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
}
final bool hasConsent = permission == LocationPermission.always || permission == LocationPermission.whileInUse;
emit(state.copyWith(hasLocationConsent: hasConsent));
await handleError(
emit: emit,
action: () async {
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
}
if (hasConsent) {
_startLocationUpdates();
}
} catch (e) {
emit(state.copyWith(errorMessage: "Location error: $e"));
}
final bool hasConsent =
permission == LocationPermission.always ||
permission == LocationPermission.whileInUse;
emit(state.copyWith(hasLocationConsent: hasConsent));
if (hasConsent) {
await _startLocationUpdates();
}
},
onError: (String errorKey) => state.copyWith(
errorMessage: errorKey,
),
);
}
Future<void> _startLocationUpdates() async {
// Note: handleErrorWithResult could be used here too if we want centralized logging/conversion
try {
final Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
final Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
);
double distance = 0;
bool isVerified = false; // Require location match by default if shift has location
bool isVerified =
false; // Require location match by default if shift has location
if (state.selectedShift != null &&
state.selectedShift!.latitude != null &&
state.selectedShift!.longitude != null) {
distance = Geolocator.distanceBetween(
position.latitude,
position.longitude,
state.selectedShift!.latitude!,
state.selectedShift!.longitude!,
);
isVerified = distance <= allowedRadiusMeters;
distance = Geolocator.distanceBetween(
position.latitude,
position.longitude,
state.selectedShift!.latitude!,
state.selectedShift!.longitude!,
);
isVerified = distance <= allowedRadiusMeters;
} else {
// If no shift location, assume verified or don't restrict?
// For strict clock-in, maybe false? but let's default to verified to avoid blocking if data missing
isVerified = true;
isVerified = true;
}
if (!isClosed) {
add(LocationUpdated(position: position, distance: distance, isVerified: isVerified));
add(
LocationUpdated(
position: position,
distance: distance,
isVerified: isVerified,
),
);
}
} catch (e) {
// Handle error silently or via state
} catch (_) {
// Geolocator errors usually handled via onRequestLocationPermission
}
}
@@ -144,7 +158,8 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
currentLocation: event.position,
distanceFromVenue: event.distance,
isLocationVerified: event.isVerified,
etaMinutes: (event.distance / 80).round(), // Rough estimate: 80m/min walking speed
etaMinutes:
(event.distance / 80).round(), // Rough estimate: 80m/min walking speed
));
}
@@ -152,10 +167,10 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
CommuteModeToggled event,
Emitter<ClockInState> emit,
) {
emit(state.copyWith(isCommuteModeOn: event.isEnabled));
if (event.isEnabled) {
add(RequestLocationPermission());
}
emit(state.copyWith(isCommuteModeOn: event.isEnabled));
if (event.isEnabled) {
add(RequestLocationPermission());
}
}
void _onShiftSelected(
@@ -186,28 +201,23 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
CheckInRequested event,
Emitter<ClockInState> emit,
) async {
// Only verify location if not using NFC (or depending on requirements) - enforcing for swipe
if (state.checkInMode == 'swipe' && !state.isLocationVerified) {
// Allow for now since coordinates are hardcoded and might not match user location
// emit(state.copyWith(errorMessage: "You must be at the location to clock in."));
// return;
}
emit(state.copyWith(status: ClockInStatus.actionInProgress));
try {
final AttendanceStatus newStatus = await _clockIn(
ClockInArguments(shiftId: event.shiftId, notes: event.notes),
);
emit(state.copyWith(
status: ClockInStatus.success,
attendance: newStatus,
));
} catch (e) {
emit(state.copyWith(
await handleError(
emit: emit,
action: () async {
final AttendanceStatus newStatus = await _clockIn(
ClockInArguments(shiftId: event.shiftId, notes: event.notes),
);
emit(state.copyWith(
status: ClockInStatus.success,
attendance: newStatus,
));
},
onError: (String errorKey) => state.copyWith(
status: ClockInStatus.failure,
errorMessage: e.toString(),
));
}
errorMessage: errorKey,
),
);
}
Future<void> _onCheckOut(
@@ -215,23 +225,25 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
Emitter<ClockInState> emit,
) async {
emit(state.copyWith(status: ClockInStatus.actionInProgress));
try {
final AttendanceStatus newStatus = await _clockOut(
ClockOutArguments(
notes: event.notes,
breakTimeMinutes: 0, // Should be passed from event if supported
applicationId: state.attendance.activeApplicationId,
),
);
emit(state.copyWith(
status: ClockInStatus.success,
attendance: newStatus,
));
} catch (e) {
emit(state.copyWith(
await handleError(
emit: emit,
action: () async {
final AttendanceStatus newStatus = await _clockOut(
ClockOutArguments(
notes: event.notes,
breakTimeMinutes: 0,
applicationId: state.attendance.activeApplicationId,
),
);
emit(state.copyWith(
status: ClockInStatus.success,
attendance: newStatus,
));
},
onError: (String errorKey) => state.copyWith(
status: ClockInStatus.failure,
errorMessage: e.toString(),
));
}
errorMessage: errorKey,
),
);
}
}

View File

@@ -86,7 +86,7 @@ class ClockInCubit extends Cubit<ClockInState> { // 500m radius
return;
}
_getCurrentLocation();
await _getCurrentLocation();
} catch (e) {
emit(state.copyWith(isLoading: false, error: e.toString()));
}