feat: integrate Google Maps Places autocomplete for hub address validation and remove activity log functionality
This commit is contained in:
@@ -129,6 +129,8 @@ class ClockInRepositoryImpl implements ClockInRepositoryInterface {
|
|||||||
createdDate: _toDateTime(fullShift.createdAt)?.toIso8601String() ?? '',
|
createdDate: _toDateTime(fullShift.createdAt)?.toIso8601String() ?? '',
|
||||||
status: fullShift.status?.stringValue,
|
status: fullShift.status?.stringValue,
|
||||||
description: fullShift.description,
|
description: fullShift.description,
|
||||||
|
latitude: fullShift.latitude,
|
||||||
|
longitude: fullShift.longitude,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,10 +188,4 @@ class ClockInRepositoryImpl implements ClockInRepositoryInterface {
|
|||||||
|
|
||||||
return getAttendanceStatus();
|
return getAttendanceStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<Map<String, dynamic>>> getActivityLog() async {
|
|
||||||
// Placeholder as this wasn't main focus and returns raw maps
|
|
||||||
return <Map<String, dynamic>>[];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,4 @@ abstract class ClockInRepositoryInterface {
|
|||||||
/// Checks the user out for the currently active shift.
|
/// Checks the user out for the currently active shift.
|
||||||
/// Optionally accepts [breakTimeMinutes] if tracked.
|
/// Optionally accepts [breakTimeMinutes] if tracked.
|
||||||
Future<AttendanceStatus> clockOut({String? notes, int? breakTimeMinutes});
|
Future<AttendanceStatus> clockOut({String? notes, int? breakTimeMinutes});
|
||||||
|
|
||||||
/// Retrieves a list of recent clock-in/out activities.
|
|
||||||
Future<List<Map<String, dynamic>>> getActivityLog();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
import 'package:krow_core/core.dart';
|
|
||||||
import '../repositories/clock_in_repository_interface.dart';
|
|
||||||
|
|
||||||
/// Use case for retrieving the activity log.
|
|
||||||
class GetActivityLogUseCase implements NoInputUseCase<List<Map<String, dynamic>>> {
|
|
||||||
final ClockInRepositoryInterface _repository;
|
|
||||||
|
|
||||||
GetActivityLogUseCase(this._repository);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<Map<String, dynamic>>> call() {
|
|
||||||
return _repository.getActivityLog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,6 @@ import '../../domain/usecases/get_todays_shift_usecase.dart';
|
|||||||
import '../../domain/usecases/get_attendance_status_usecase.dart';
|
import '../../domain/usecases/get_attendance_status_usecase.dart';
|
||||||
import '../../domain/usecases/clock_in_usecase.dart';
|
import '../../domain/usecases/clock_in_usecase.dart';
|
||||||
import '../../domain/usecases/clock_out_usecase.dart';
|
import '../../domain/usecases/clock_out_usecase.dart';
|
||||||
import '../../domain/usecases/get_activity_log_usecase.dart';
|
|
||||||
import '../../domain/arguments/clock_in_arguments.dart';
|
import '../../domain/arguments/clock_in_arguments.dart';
|
||||||
import '../../domain/arguments/clock_out_arguments.dart';
|
import '../../domain/arguments/clock_out_arguments.dart';
|
||||||
import 'clock_in_event.dart';
|
import 'clock_in_event.dart';
|
||||||
@@ -15,11 +14,8 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
|
|||||||
final GetAttendanceStatusUseCase _getAttendanceStatus;
|
final GetAttendanceStatusUseCase _getAttendanceStatus;
|
||||||
final ClockInUseCase _clockIn;
|
final ClockInUseCase _clockIn;
|
||||||
final ClockOutUseCase _clockOut;
|
final ClockOutUseCase _clockOut;
|
||||||
final GetActivityLogUseCase _getActivityLog;
|
|
||||||
|
|
||||||
// Mock Venue Location (e.g., Grand Hotel, NYC)
|
// Mock Venue Location (e.g., Grand Hotel, NYC)
|
||||||
static const double venueLat = 40.7128;
|
|
||||||
static const double venueLng = -74.0060;
|
|
||||||
static const double allowedRadiusMeters = 500;
|
static const double allowedRadiusMeters = 500;
|
||||||
|
|
||||||
ClockInBloc({
|
ClockInBloc({
|
||||||
@@ -27,12 +23,10 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
|
|||||||
required GetAttendanceStatusUseCase getAttendanceStatus,
|
required GetAttendanceStatusUseCase getAttendanceStatus,
|
||||||
required ClockInUseCase clockIn,
|
required ClockInUseCase clockIn,
|
||||||
required ClockOutUseCase clockOut,
|
required ClockOutUseCase clockOut,
|
||||||
required GetActivityLogUseCase getActivityLog,
|
|
||||||
}) : _getTodaysShift = getTodaysShift,
|
}) : _getTodaysShift = getTodaysShift,
|
||||||
_getAttendanceStatus = getAttendanceStatus,
|
_getAttendanceStatus = getAttendanceStatus,
|
||||||
_clockIn = clockIn,
|
_clockIn = clockIn,
|
||||||
_clockOut = clockOut,
|
_clockOut = clockOut,
|
||||||
_getActivityLog = getActivityLog,
|
|
||||||
super(ClockInState(selectedDate: DateTime.now())) {
|
super(ClockInState(selectedDate: DateTime.now())) {
|
||||||
on<ClockInPageLoaded>(_onLoaded);
|
on<ClockInPageLoaded>(_onLoaded);
|
||||||
on<DateSelected>(_onDateSelected);
|
on<DateSelected>(_onDateSelected);
|
||||||
@@ -54,7 +48,6 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
|
|||||||
try {
|
try {
|
||||||
final shift = await _getTodaysShift();
|
final shift = await _getTodaysShift();
|
||||||
final status = await _getAttendanceStatus();
|
final status = await _getAttendanceStatus();
|
||||||
final activity = await _getActivityLog();
|
|
||||||
|
|
||||||
// Check permissions silently on load? Maybe better to wait for user interaction or specific event
|
// 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
|
// However, if shift exists, we might want to check permission state
|
||||||
@@ -63,7 +56,6 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
|
|||||||
status: ClockInStatus.success,
|
status: ClockInStatus.success,
|
||||||
todayShift: shift,
|
todayShift: shift,
|
||||||
attendance: status,
|
attendance: status,
|
||||||
activityLog: activity,
|
|
||||||
));
|
));
|
||||||
|
|
||||||
if (shift != null && !status.isCheckedIn) {
|
if (shift != null && !status.isCheckedIn) {
|
||||||
@@ -103,13 +95,23 @@ class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
|
|||||||
void _startLocationUpdates() async {
|
void _startLocationUpdates() async {
|
||||||
try {
|
try {
|
||||||
final position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
|
final position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
|
||||||
final distance = Geolocator.distanceBetween(
|
|
||||||
position.latitude,
|
double distance = 0;
|
||||||
position.longitude,
|
bool isVerified = false; // Require location match by default if shift has location
|
||||||
venueLat,
|
|
||||||
venueLng,
|
if (state.todayShift != null && state.todayShift!.latitude != null && state.todayShift!.longitude != null) {
|
||||||
);
|
distance = Geolocator.distanceBetween(
|
||||||
final isVerified = distance <= allowedRadiusMeters;
|
position.latitude,
|
||||||
|
position.longitude,
|
||||||
|
state.todayShift!.latitude!,
|
||||||
|
state.todayShift!.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;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
add(LocationUpdated(position: position, distance: distance, isVerified: isVerified));
|
add(LocationUpdated(position: position, distance: distance, isVerified: isVerified));
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ class ClockInState extends Equatable {
|
|||||||
final ClockInStatus status;
|
final ClockInStatus status;
|
||||||
final Shift? todayShift;
|
final Shift? todayShift;
|
||||||
final AttendanceStatus attendance;
|
final AttendanceStatus attendance;
|
||||||
final List<Map<String, dynamic>> activityLog;
|
|
||||||
final DateTime selectedDate;
|
final DateTime selectedDate;
|
||||||
final String checkInMode;
|
final String checkInMode;
|
||||||
final String? errorMessage;
|
final String? errorMessage;
|
||||||
@@ -25,7 +24,6 @@ class ClockInState extends Equatable {
|
|||||||
this.status = ClockInStatus.initial,
|
this.status = ClockInStatus.initial,
|
||||||
this.todayShift,
|
this.todayShift,
|
||||||
this.attendance = const AttendanceStatus(),
|
this.attendance = const AttendanceStatus(),
|
||||||
this.activityLog = const [],
|
|
||||||
required this.selectedDate,
|
required this.selectedDate,
|
||||||
this.checkInMode = 'swipe',
|
this.checkInMode = 'swipe',
|
||||||
this.errorMessage,
|
this.errorMessage,
|
||||||
@@ -41,7 +39,6 @@ class ClockInState extends Equatable {
|
|||||||
ClockInStatus? status,
|
ClockInStatus? status,
|
||||||
Shift? todayShift,
|
Shift? todayShift,
|
||||||
AttendanceStatus? attendance,
|
AttendanceStatus? attendance,
|
||||||
List<Map<String, dynamic>>? activityLog,
|
|
||||||
DateTime? selectedDate,
|
DateTime? selectedDate,
|
||||||
String? checkInMode,
|
String? checkInMode,
|
||||||
String? errorMessage,
|
String? errorMessage,
|
||||||
@@ -56,7 +53,6 @@ class ClockInState extends Equatable {
|
|||||||
status: status ?? this.status,
|
status: status ?? this.status,
|
||||||
todayShift: todayShift ?? this.todayShift,
|
todayShift: todayShift ?? this.todayShift,
|
||||||
attendance: attendance ?? this.attendance,
|
attendance: attendance ?? this.attendance,
|
||||||
activityLog: activityLog ?? this.activityLog,
|
|
||||||
selectedDate: selectedDate ?? this.selectedDate,
|
selectedDate: selectedDate ?? this.selectedDate,
|
||||||
checkInMode: checkInMode ?? this.checkInMode,
|
checkInMode: checkInMode ?? this.checkInMode,
|
||||||
errorMessage: errorMessage,
|
errorMessage: errorMessage,
|
||||||
@@ -74,7 +70,6 @@ class ClockInState extends Equatable {
|
|||||||
status,
|
status,
|
||||||
todayShift,
|
todayShift,
|
||||||
attendance,
|
attendance,
|
||||||
activityLog,
|
|
||||||
selectedDate,
|
selectedDate,
|
||||||
checkInMode,
|
checkInMode,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_modular/flutter_modular.dart';
|
import 'package:flutter_modular/flutter_modular.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
import 'package:lucide_icons/lucide_icons.dart';
|
import 'package:lucide_icons/lucide_icons.dart';
|
||||||
|
|
||||||
import '../bloc/clock_in_bloc.dart';
|
import '../bloc/clock_in_bloc.dart';
|
||||||
import '../bloc/clock_in_event.dart';
|
import '../bloc/clock_in_event.dart';
|
||||||
import '../bloc/clock_in_state.dart';
|
import '../bloc/clock_in_state.dart';
|
||||||
import '../theme/app_colors.dart';
|
import '../theme/app_colors.dart';
|
||||||
import '../widgets/attendance_card.dart';
|
|
||||||
import '../widgets/commute_tracker.dart';
|
import '../widgets/commute_tracker.dart';
|
||||||
import '../widgets/date_selector.dart';
|
import '../widgets/date_selector.dart';
|
||||||
import '../widgets/lunch_break_modal.dart';
|
import '../widgets/lunch_break_modal.dart';
|
||||||
@@ -135,13 +135,6 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: const Color(0xFFE2E8F0),
|
color: const Color(0xFFE2E8F0),
|
||||||
), // slate-200
|
), // slate-200
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.05),
|
|
||||||
blurRadius: 2,
|
|
||||||
offset: const Offset(0, 1),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -417,78 +410,7 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// Recent Activity List
|
// Recent Activity List (Temporarily removed)
|
||||||
if (state.activityLog.isNotEmpty)
|
|
||||||
...state.activityLog.map(
|
|
||||||
(activity) => Container(
|
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFFF8F9FA),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(
|
|
||||||
color: const Color(0xFFF1F5F9),
|
|
||||||
), // slate-100
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: AppColors.krowBlue.withOpacity(
|
|
||||||
0.1,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
LucideIcons.mapPin,
|
|
||||||
color: AppColors.krowBlue,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
DateFormat('MMM d').format(
|
|
||||||
activity['date'] as DateTime,
|
|
||||||
),
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Color(
|
|
||||||
0xFF0F172A,
|
|
||||||
), // slate-900
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"${activity['start']} - ${activity['end']}",
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Color(
|
|
||||||
0xFF64748B,
|
|
||||||
), // slate-500
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
activity['hours'] as String,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: AppColors.krowBlue,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -552,87 +474,6 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHeader() {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(20, 24, 20, 16),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
border: Border.all(
|
|
||||||
color: AppColors.krowBlue.withOpacity(0.2),
|
|
||||||
width: 2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: CircleAvatar(
|
|
||||||
backgroundColor: AppColors.krowBlue.withOpacity(0.1),
|
|
||||||
child: const Text(
|
|
||||||
'K',
|
|
||||||
style: TextStyle(
|
|
||||||
color: AppColors.krowBlue,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
const Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Good Morning',
|
|
||||||
style: TextStyle(color: AppColors.krowMuted, fontSize: 12),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'Krower',
|
|
||||||
style: TextStyle(
|
|
||||||
color: AppColors.krowCharcoal,
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'Warehouse Assistant',
|
|
||||||
style: TextStyle(color: AppColors.krowMuted, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
20,
|
|
||||||
), // Rounded full for this page per design
|
|
||||||
border: Border.all(color: Colors.grey.shade100),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.05),
|
|
||||||
blurRadius: 2,
|
|
||||||
offset: const Offset(0, 1),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
LucideIcons.bell,
|
|
||||||
color: AppColors.krowMuted,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _showNFCDialog(BuildContext context) async {
|
Future<void> _showNFCDialog(BuildContext context) async {
|
||||||
bool scanned = false;
|
bool scanned = false;
|
||||||
|
|
||||||
@@ -739,23 +580,32 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
// --- Helper Methods ---
|
// --- Helper Methods ---
|
||||||
|
|
||||||
String _formatTime(String timeStr) {
|
String _formatTime(String timeStr) {
|
||||||
// Expecting HH:mm or HH:mm:ss
|
if (timeStr.isEmpty) return '';
|
||||||
try {
|
try {
|
||||||
if (timeStr.isEmpty) return '';
|
// Try parsing as ISO string first (which contains date)
|
||||||
final parts = timeStr.split(':');
|
final dt = DateTime.parse(timeStr);
|
||||||
final dt = DateTime(2022, 1, 1, int.parse(parts[0]), int.parse(parts[1]));
|
|
||||||
return DateFormat('h:mm a').format(dt);
|
return DateFormat('h:mm a').format(dt);
|
||||||
} catch (e) {
|
} catch (_) {
|
||||||
return timeStr;
|
// Fallback for strict "HH:mm" or "HH:mm:ss" strings
|
||||||
|
try {
|
||||||
|
final parts = timeStr.split(':');
|
||||||
|
if (parts.length >= 2) {
|
||||||
|
final dt = DateTime(2022, 1, 1, int.parse(parts[0]), int.parse(parts[1]));
|
||||||
|
return DateFormat('h:mm a').format(dt);
|
||||||
|
}
|
||||||
|
return timeStr;
|
||||||
|
} catch (e) {
|
||||||
|
return timeStr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isCheckInAllowed(dynamic shift) {
|
bool _isCheckInAllowed(Shift shift) {
|
||||||
if (shift == null) return false;
|
if (shift == null) return false;
|
||||||
try {
|
try {
|
||||||
// Parse shift date (e.g. 2024-01-31T09:00:00)
|
// Parse shift date (e.g. 2024-01-31T09:00:00)
|
||||||
// The Shift entity has 'date' which is the start DateTime string
|
// The Shift entity has 'date' which is the start DateTime string
|
||||||
final shiftStart = DateTime.parse(shift.date);
|
final shiftStart = DateTime.parse(shift.startTime);
|
||||||
final windowStart = shiftStart.subtract(const Duration(minutes: 15));
|
final windowStart = shiftStart.subtract(const Duration(minutes: 15));
|
||||||
return DateTime.now().isAfter(windowStart);
|
return DateTime.now().isAfter(windowStart);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -764,10 +614,10 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getCheckInAvailabilityTime(dynamic shift) {
|
String _getCheckInAvailabilityTime(Shift shift) {
|
||||||
if (shift == null) return '';
|
if (shift == null) return '';
|
||||||
try {
|
try {
|
||||||
final shiftStart = DateTime.parse(shift.date);
|
final shiftStart = DateTime.parse(shift.endTime);
|
||||||
final windowStart = shiftStart.subtract(const Duration(minutes: 15));
|
final windowStart = shiftStart.subtract(const Duration(minutes: 15));
|
||||||
return DateFormat('h:mm a').format(windowStart);
|
return DateFormat('h:mm a').format(windowStart);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -66,9 +66,14 @@ class _CommuteTrackerState extends State<CommuteTracker> {
|
|||||||
|
|
||||||
// For demo purposes, check if we're within 24 hours of shift
|
// For demo purposes, check if we're within 24 hours of shift
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final shiftStart = DateTime.parse(
|
DateTime shiftStart;
|
||||||
'${widget.shift!.date} ${widget.shift!.startTime}',
|
try {
|
||||||
);
|
shiftStart = DateTime.parse(widget.shift!.startTime);
|
||||||
|
} catch (_) {
|
||||||
|
shiftStart = DateTime.parse(
|
||||||
|
'${widget.shift!.date} ${widget.shift!.startTime}',
|
||||||
|
);
|
||||||
|
}
|
||||||
final hoursUntilShift = shiftStart.difference(now).inHours;
|
final hoursUntilShift = shiftStart.difference(now).inHours;
|
||||||
final inCommuteWindow = hoursUntilShift <= 24 && hoursUntilShift >= 0;
|
final inCommuteWindow = hoursUntilShift <= 24 && hoursUntilShift >= 0;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import 'data/repositories_impl/clock_in_repository_impl.dart';
|
|||||||
import 'domain/repositories/clock_in_repository_interface.dart';
|
import 'domain/repositories/clock_in_repository_interface.dart';
|
||||||
import 'domain/usecases/clock_in_usecase.dart';
|
import 'domain/usecases/clock_in_usecase.dart';
|
||||||
import 'domain/usecases/clock_out_usecase.dart';
|
import 'domain/usecases/clock_out_usecase.dart';
|
||||||
import 'domain/usecases/get_activity_log_usecase.dart';
|
|
||||||
import 'domain/usecases/get_attendance_status_usecase.dart';
|
import 'domain/usecases/get_attendance_status_usecase.dart';
|
||||||
import 'domain/usecases/get_todays_shift_usecase.dart';
|
import 'domain/usecases/get_todays_shift_usecase.dart';
|
||||||
import 'presentation/bloc/clock_in_bloc.dart';
|
import 'presentation/bloc/clock_in_bloc.dart';
|
||||||
@@ -28,7 +27,6 @@ class StaffClockInModule extends Module {
|
|||||||
i.add<GetAttendanceStatusUseCase>(GetAttendanceStatusUseCase.new);
|
i.add<GetAttendanceStatusUseCase>(GetAttendanceStatusUseCase.new);
|
||||||
i.add<ClockInUseCase>(ClockInUseCase.new);
|
i.add<ClockInUseCase>(ClockInUseCase.new);
|
||||||
i.add<ClockOutUseCase>(ClockOutUseCase.new);
|
i.add<ClockOutUseCase>(ClockOutUseCase.new);
|
||||||
i.add<GetActivityLogUseCase>(GetActivityLogUseCase.new);
|
|
||||||
|
|
||||||
// BLoC
|
// BLoC
|
||||||
i.add<ClockInBloc>(ClockInBloc.new);
|
i.add<ClockInBloc>(ClockInBloc.new);
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import 'package:flutter_modular/flutter_modular.dart';
|
|||||||
import 'package:krow_domain/krow_domain.dart';
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
|
|
||||||
extension ShiftsNavigator on IModularNavigator {
|
extension ShiftsNavigator on IModularNavigator {
|
||||||
|
void navigateToShiftsHome() {
|
||||||
|
navigate('/worker-main/shifts/');
|
||||||
|
}
|
||||||
|
|
||||||
void pushShiftDetails(Shift shift) {
|
void pushShiftDetails(Shift shift) {
|
||||||
pushNamed('/worker-main/shift-details/${shift.id}', arguments: shift);
|
navigate('/worker-main/shift-details/${shift.id}', arguments: shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user