feat: Refactor ClockInPage for improved readability and consistency in code formatting
This commit is contained in:
@@ -33,7 +33,9 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final TranslationsStaffClockInEn i18n = Translations.of(context).staff.clock_in;
|
final TranslationsStaffClockInEn i18n = Translations.of(
|
||||||
|
context,
|
||||||
|
).staff.clock_in;
|
||||||
return BlocProvider<ClockInBloc>.value(
|
return BlocProvider<ClockInBloc>.value(
|
||||||
value: _bloc,
|
value: _bloc,
|
||||||
child: BlocConsumer<ClockInBloc, ClockInState>(
|
child: BlocConsumer<ClockInBloc, ClockInState>(
|
||||||
@@ -60,22 +62,17 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
final String? activeShiftId = state.attendance.activeShiftId;
|
final String? activeShiftId = state.attendance.activeShiftId;
|
||||||
final bool isActiveSelected =
|
final bool isActiveSelected =
|
||||||
selectedShift != null && selectedShift.id == activeShiftId;
|
selectedShift != null && selectedShift.id == activeShiftId;
|
||||||
final DateTime? checkInTime =
|
final DateTime? checkInTime = isActiveSelected
|
||||||
isActiveSelected ? state.attendance.checkInTime : null;
|
? state.attendance.checkInTime
|
||||||
final DateTime? checkOutTime =
|
: null;
|
||||||
isActiveSelected ? state.attendance.checkOutTime : null;
|
final DateTime? checkOutTime = isActiveSelected
|
||||||
|
? state.attendance.checkOutTime
|
||||||
|
: null;
|
||||||
final bool isCheckedIn =
|
final bool isCheckedIn =
|
||||||
state.attendance.isCheckedIn && isActiveSelected;
|
state.attendance.isCheckedIn && isActiveSelected;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: UiAppBar(
|
appBar: UiAppBar(title: i18n.title, showBackButton: false),
|
||||||
titleWidget: Text(
|
|
||||||
i18n.title,
|
|
||||||
style: UiTypography.title1m.textPrimary,
|
|
||||||
),
|
|
||||||
showBackButton: false,
|
|
||||||
centerTitle: false,
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
@@ -141,15 +138,12 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: UiColors.white,
|
color: UiColors.white,
|
||||||
borderRadius:
|
borderRadius: UiConstants.radiusLg,
|
||||||
UiConstants.radiusLg,
|
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: shift.id ==
|
color: shift.id == selectedShift?.id
|
||||||
selectedShift?.id
|
|
||||||
? UiColors.primary
|
? UiColors.primary
|
||||||
: UiColors.border,
|
: UiColors.border,
|
||||||
width:
|
width: shift.id == selectedShift?.id
|
||||||
shift.id == selectedShift?.id
|
|
||||||
? 2
|
? 2
|
||||||
: 1,
|
: 1,
|
||||||
),
|
),
|
||||||
@@ -166,15 +160,15 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
Text(
|
Text(
|
||||||
shift.id ==
|
shift.id ==
|
||||||
selectedShift?.id
|
selectedShift?.id
|
||||||
? i18n
|
? i18n.selected_shift_badge
|
||||||
.selected_shift_badge
|
: i18n.today_shift_badge,
|
||||||
: i18n
|
|
||||||
.today_shift_badge,
|
|
||||||
style: UiTypography
|
style: UiTypography
|
||||||
.titleUppercase4b
|
.titleUppercase4b
|
||||||
.copyWith(
|
.copyWith(
|
||||||
color: shift.id ==
|
color:
|
||||||
selectedShift?.id
|
shift.id ==
|
||||||
|
selectedShift
|
||||||
|
?.id
|
||||||
? UiColors.primary
|
? UiColors.primary
|
||||||
: UiColors
|
: UiColors
|
||||||
.textSecondary,
|
.textSecondary,
|
||||||
@@ -187,7 +181,8 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"${shift.clientName} • ${shift.location}",
|
"${shift.clientName} • ${shift.location}",
|
||||||
style: UiTypography.body3r
|
style: UiTypography
|
||||||
|
.body3r
|
||||||
.textSecondary,
|
.textSecondary,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -199,7 +194,8 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
"${_formatTime(shift.startTime)} - ${_formatTime(shift.endTime)}",
|
"${_formatTime(shift.startTime)} - ${_formatTime(shift.endTime)}",
|
||||||
style: UiTypography.body3m
|
style: UiTypography
|
||||||
|
.body3m
|
||||||
.textSecondary,
|
.textSecondary,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
@@ -226,8 +222,9 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
!_isCheckInAllowed(selectedShift))
|
!_isCheckInAllowed(selectedShift))
|
||||||
Container(
|
Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding:
|
padding: const EdgeInsets.all(
|
||||||
const EdgeInsets.all(UiConstants.space6),
|
UiConstants.space6,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: UiColors.bgSecondary,
|
color: UiColors.bgSecondary,
|
||||||
borderRadius: UiConstants.radiusLg,
|
borderRadius: UiConstants.radiusLg,
|
||||||
@@ -261,8 +258,12 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
// Attire Photo Section
|
// Attire Photo Section
|
||||||
if (!isCheckedIn) ...<Widget>[
|
if (!isCheckedIn) ...<Widget>[
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(UiConstants.space4),
|
padding: const EdgeInsets.all(
|
||||||
margin: const EdgeInsets.only(bottom: UiConstants.space4),
|
UiConstants.space4,
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
bottom: UiConstants.space4,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: UiColors.white,
|
color: UiColors.white,
|
||||||
borderRadius: UiConstants.radiusLg,
|
borderRadius: UiConstants.radiusLg,
|
||||||
@@ -277,15 +278,27 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
color: UiColors.bgSecondary,
|
color: UiColors.bgSecondary,
|
||||||
borderRadius: UiConstants.radiusMd,
|
borderRadius: UiConstants.radiusMd,
|
||||||
),
|
),
|
||||||
child: const Icon(UiIcons.camera, color: UiColors.primary),
|
child: const Icon(
|
||||||
|
UiIcons.camera,
|
||||||
|
color: UiColors.primary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: UiConstants.space3),
|
const SizedBox(width: UiConstants.space3),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(i18n.attire_photo_label, style: UiTypography.body2b),
|
Text(
|
||||||
Text(i18n.attire_photo_desc, style: UiTypography.body3r.textSecondary),
|
i18n.attire_photo_label,
|
||||||
|
style: UiTypography.body2b,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
i18n.attire_photo_desc,
|
||||||
|
style: UiTypography
|
||||||
|
.body3r
|
||||||
|
.textSecondary,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -304,24 +317,37 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
||||||
if (!isCheckedIn && (!state.isLocationVerified || state.currentLocation == null)) ...<Widget>[
|
if (!isCheckedIn &&
|
||||||
|
(!state.isLocationVerified ||
|
||||||
|
state.currentLocation ==
|
||||||
|
null)) ...<Widget>[
|
||||||
Container(
|
Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.all(UiConstants.space4),
|
padding: const EdgeInsets.all(
|
||||||
margin: const EdgeInsets.only(bottom: UiConstants.space4),
|
UiConstants.space4,
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
bottom: UiConstants.space4,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: UiColors.tagError,
|
color: UiColors.tagError,
|
||||||
borderRadius: UiConstants.radiusLg,
|
borderRadius: UiConstants.radiusLg,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(UiIcons.error, color: UiColors.textError, size: 20),
|
const Icon(
|
||||||
|
UiIcons.error,
|
||||||
|
color: UiColors.textError,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
const SizedBox(width: UiConstants.space3),
|
const SizedBox(width: UiConstants.space3),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
state.currentLocation == null
|
state.currentLocation == null
|
||||||
? i18n.location_verifying
|
? i18n.location_verifying
|
||||||
: i18n.not_in_range(distance: '500'),
|
: i18n.not_in_range(
|
||||||
|
distance: '500',
|
||||||
|
),
|
||||||
style: UiTypography.body3m.textError,
|
style: UiTypography.body3m.textError,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -333,7 +359,8 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
SwipeToCheckIn(
|
SwipeToCheckIn(
|
||||||
isCheckedIn: isCheckedIn,
|
isCheckedIn: isCheckedIn,
|
||||||
mode: state.checkInMode,
|
mode: state.checkInMode,
|
||||||
isDisabled: !isCheckedIn && !state.isLocationVerified,
|
isDisabled:
|
||||||
|
!isCheckedIn && !state.isLocationVerified,
|
||||||
isLoading:
|
isLoading:
|
||||||
state.status ==
|
state.status ==
|
||||||
ClockInStatus.actionInProgress,
|
ClockInStatus.actionInProgress,
|
||||||
@@ -554,7 +581,9 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _showNFCDialog(BuildContext context) async {
|
Future<void> _showNFCDialog(BuildContext context) async {
|
||||||
final TranslationsStaffClockInEn i18n = Translations.of(context).staff.clock_in;
|
final TranslationsStaffClockInEn i18n = Translations.of(
|
||||||
|
context,
|
||||||
|
).staff.clock_in;
|
||||||
bool scanned = false;
|
bool scanned = false;
|
||||||
|
|
||||||
// Using a local navigator context since we are in a dialog
|
// Using a local navigator context since we are in a dialog
|
||||||
@@ -668,7 +697,13 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
try {
|
try {
|
||||||
final List<String> parts = timeStr.split(':');
|
final List<String> parts = timeStr.split(':');
|
||||||
if (parts.length >= 2) {
|
if (parts.length >= 2) {
|
||||||
final DateTime dt = DateTime(2022, 1, 1, int.parse(parts[0]), int.parse(parts[1]));
|
final DateTime 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);
|
||||||
}
|
}
|
||||||
return timeStr;
|
return timeStr;
|
||||||
@@ -683,7 +718,9 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
// 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 DateTime shiftStart = DateTime.parse(shift.startTime);
|
final DateTime shiftStart = DateTime.parse(shift.startTime);
|
||||||
final DateTime windowStart = shiftStart.subtract(const Duration(minutes: 15));
|
final DateTime windowStart = shiftStart.subtract(
|
||||||
|
const Duration(minutes: 15),
|
||||||
|
);
|
||||||
return DateTime.now().isAfter(windowStart);
|
return DateTime.now().isAfter(windowStart);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Fallback: If parsing fails, allow check in to avoid blocking.
|
// Fallback: If parsing fails, allow check in to avoid blocking.
|
||||||
@@ -694,13 +731,15 @@ class _ClockInPageState extends State<ClockInPage> {
|
|||||||
String _getCheckInAvailabilityTime(Shift shift) {
|
String _getCheckInAvailabilityTime(Shift shift) {
|
||||||
try {
|
try {
|
||||||
final DateTime shiftStart = DateTime.parse(shift.startTime.trim());
|
final DateTime shiftStart = DateTime.parse(shift.startTime.trim());
|
||||||
final DateTime windowStart = shiftStart.subtract(const Duration(minutes: 15));
|
final DateTime 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) {
|
||||||
final TranslationsStaffClockInEn i18n = Translations.of(context).staff.clock_in;
|
final TranslationsStaffClockInEn i18n = Translations.of(
|
||||||
|
context,
|
||||||
|
).staff.clock_in;
|
||||||
return i18n.soon;
|
return i18n.soon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user