refactor: enhance navigation robustness by introducing popSafe and safePushNamedAndRemoveUntil methods and updating their usage.
This commit is contained in:
@@ -135,7 +135,7 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
|
||||
leading: const Icon(Icons.photo_library),
|
||||
title: Text(t.common.gallery),
|
||||
onTap: () {
|
||||
Modular.to.pop();
|
||||
Modular.to.popSafe();
|
||||
_onGallery(context);
|
||||
},
|
||||
),
|
||||
@@ -143,7 +143,7 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
|
||||
leading: const Icon(Icons.camera_alt),
|
||||
title: Text(t.common.camera),
|
||||
onTap: () {
|
||||
Modular.to.pop();
|
||||
Modular.to.popSafe();
|
||||
_onCamera(context);
|
||||
},
|
||||
),
|
||||
@@ -215,10 +215,16 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
|
||||
|
||||
String _getStatusText(bool hasUploadedPhoto) {
|
||||
return switch (widget.item.verificationStatus) {
|
||||
AttireVerificationStatus.approved => t.staff_profile_attire.capture.approved,
|
||||
AttireVerificationStatus.rejected => t.staff_profile_attire.capture.rejected,
|
||||
AttireVerificationStatus.pending => t.staff_profile_attire.capture.pending_verification,
|
||||
_ => hasUploadedPhoto ? t.staff_profile_attire.capture.pending_verification : t.staff_profile_attire.capture.not_uploaded,
|
||||
AttireVerificationStatus.approved =>
|
||||
t.staff_profile_attire.capture.approved,
|
||||
AttireVerificationStatus.rejected =>
|
||||
t.staff_profile_attire.capture.rejected,
|
||||
AttireVerificationStatus.pending =>
|
||||
t.staff_profile_attire.capture.pending_verification,
|
||||
_ =>
|
||||
hasUploadedPhoto
|
||||
? t.staff_profile_attire.capture.pending_verification
|
||||
: t.staff_profile_attire.capture.not_uploaded,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -281,7 +287,9 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
_FileTypesBanner(
|
||||
message: t.staff_profile_attire.upload_file_types_banner,
|
||||
message: t
|
||||
.staff_profile_attire
|
||||
.upload_file_types_banner,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
ImagePreviewSection(
|
||||
@@ -350,17 +358,10 @@ class _FileTypesBanner extends StatelessWidget {
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
UiIcons.info,
|
||||
size: 20,
|
||||
color: UiColors.primary,
|
||||
),
|
||||
Icon(UiIcons.info, size: 20, color: UiColors.primary),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Text(
|
||||
message,
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
child: Text(message, style: UiTypography.body2r.textSecondary),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
|
||||
import 'attire_upload_buttons.dart';
|
||||
|
||||
@@ -98,7 +99,7 @@ class FooterSection extends StatelessWidget {
|
||||
text: 'Submit Image',
|
||||
onPressed: () {
|
||||
if (updatedItem != null) {
|
||||
Modular.to.pop(updatedItem);
|
||||
Modular.to.popSafe(updatedItem);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import '../blocs/emergency_contact_bloc.dart';
|
||||
import '../widgets/emergency_contact_add_button.dart';
|
||||
import '../widgets/emergency_contact_form_item.dart';
|
||||
@@ -25,7 +26,7 @@ class EmergencyContactScreen extends StatelessWidget {
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(UiIcons.chevronLeft, color: UiColors.textSecondary),
|
||||
onPressed: () => Modular.to.pop(),
|
||||
onPressed: () => Modular.to.popSafe(),
|
||||
),
|
||||
title: Text(
|
||||
'Emergency Contact',
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
|
||||
/// Language selection page for staff profile.
|
||||
///
|
||||
@@ -30,7 +31,7 @@ class LanguageSelectionPage extends StatelessWidget {
|
||||
);
|
||||
|
||||
Modular.to
|
||||
.pop(); // Close the language selection page after showing the snackbar
|
||||
.popSafe(); // Close the language selection page after showing the snackbar
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -3,12 +3,12 @@ import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
|
||||
import '../blocs/personal_info_bloc.dart';
|
||||
import '../blocs/personal_info_state.dart';
|
||||
import '../widgets/personal_info_content.dart';
|
||||
|
||||
|
||||
/// The Personal Info page for staff onboarding.
|
||||
///
|
||||
/// This page allows staff members to view and edit their personal information
|
||||
@@ -22,7 +22,9 @@ class PersonalInfoPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final TranslationsStaffOnboardingPersonalInfoEn i18n = Translations.of(context).staff.onboarding.personal_info;
|
||||
final TranslationsStaffOnboardingPersonalInfoEn i18n = Translations.of(
|
||||
context,
|
||||
).staff.onboarding.personal_info;
|
||||
return BlocProvider<PersonalInfoBloc>(
|
||||
create: (BuildContext context) => Modular.get<PersonalInfoBloc>(),
|
||||
child: BlocListener<PersonalInfoBloc, PersonalInfoState>(
|
||||
@@ -33,7 +35,7 @@ class PersonalInfoPage extends StatelessWidget {
|
||||
message: i18n.save_success,
|
||||
type: UiSnackbarType.success,
|
||||
);
|
||||
Modular.to.pop();
|
||||
Modular.to.popSafe();
|
||||
} else if (state.status == PersonalInfoStatus.error) {
|
||||
UiSnackbar.show(
|
||||
context,
|
||||
@@ -54,19 +56,13 @@ class PersonalInfoPage extends StatelessWidget {
|
||||
UiIcons.chevronLeft,
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
onPressed: () => Modular.to.pop(),
|
||||
onPressed: () => Modular.to.popSafe(),
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
),
|
||||
title: Text(
|
||||
i18n.title,
|
||||
style: UiTypography.title1m.textPrimary,
|
||||
),
|
||||
title: Text(i18n.title, style: UiTypography.title1m.textPrimary),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(1.0),
|
||||
child: Container(
|
||||
color: UiColors.border,
|
||||
height: 1.0,
|
||||
),
|
||||
child: Container(color: UiColors.border, height: 1.0),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
@@ -74,9 +70,7 @@ class PersonalInfoPage extends StatelessWidget {
|
||||
builder: (BuildContext context, PersonalInfoState state) {
|
||||
if (state.status == PersonalInfoStatus.loading ||
|
||||
state.status == PersonalInfoStatus.initial) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (state.staff == null) {
|
||||
|
||||
@@ -11,7 +11,6 @@ import 'package:krow_core/core.dart';
|
||||
/// The Preferred Locations row navigates to a dedicated Uber-style page.
|
||||
/// Uses only design system tokens for colors, typography, and spacing.
|
||||
class PersonalInfoForm extends StatelessWidget {
|
||||
|
||||
/// Creates a [PersonalInfoForm].
|
||||
const PersonalInfoForm({
|
||||
super.key,
|
||||
@@ -22,6 +21,7 @@ class PersonalInfoForm extends StatelessWidget {
|
||||
required this.currentLocations,
|
||||
this.enabled = true,
|
||||
});
|
||||
|
||||
/// The staff member's full name (read-only).
|
||||
final String fullName;
|
||||
|
||||
@@ -42,7 +42,8 @@ class PersonalInfoForm extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final TranslationsStaffOnboardingPersonalInfoEn i18n = t.staff.onboarding.personal_info;
|
||||
final TranslationsStaffOnboardingPersonalInfoEn i18n =
|
||||
t.staff.onboarding.personal_info;
|
||||
final String locationSummary = currentLocations.isEmpty
|
||||
? i18n.locations_summary_none
|
||||
: currentLocations.join(', ');
|
||||
@@ -84,17 +85,13 @@ class PersonalInfoForm extends StatelessWidget {
|
||||
hint: i18n.locations_hint,
|
||||
icon: UiIcons.mapPin,
|
||||
enabled: enabled,
|
||||
onTap: enabled
|
||||
? () => Modular.to.pushNamed(StaffPaths.preferredLocations)
|
||||
: null,
|
||||
onTap: enabled ? () => Modular.to.toPreferredLocations() : null,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
|
||||
const _FieldLabel(text: 'Language'),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
_LanguageSelector(
|
||||
enabled: enabled,
|
||||
),
|
||||
_LanguageSelector(enabled: enabled),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -132,7 +129,9 @@ class _TappableRow extends StatelessWidget {
|
||||
color: enabled ? UiColors.bgPopup : UiColors.bgSecondary,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusMdValue),
|
||||
border: Border.all(
|
||||
color: enabled ? UiColors.border : UiColors.border.withValues(alpha: 0.5),
|
||||
color: enabled
|
||||
? UiColors.border
|
||||
: UiColors.border.withValues(alpha: 0.5),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
@@ -164,9 +163,7 @@ class _TappableRow extends StatelessWidget {
|
||||
|
||||
/// A language selector widget that displays the current language and navigates to language selection page.
|
||||
class _LanguageSelector extends StatelessWidget {
|
||||
const _LanguageSelector({
|
||||
this.enabled = true,
|
||||
});
|
||||
const _LanguageSelector({this.enabled = true});
|
||||
|
||||
final bool enabled;
|
||||
|
||||
@@ -176,9 +173,7 @@ class _LanguageSelector extends StatelessWidget {
|
||||
final String languageName = currentLocale == 'es' ? 'Español' : 'English';
|
||||
|
||||
return GestureDetector(
|
||||
onTap: enabled
|
||||
? () => Modular.to.pushNamed(StaffPaths.languageSelection)
|
||||
: null,
|
||||
onTap: enabled ? () => Modular.to.toLanguageSelection() : null,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space3,
|
||||
@@ -188,18 +183,21 @@ class _LanguageSelector extends StatelessWidget {
|
||||
color: enabled ? UiColors.bgPopup : UiColors.bgSecondary,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusMdValue),
|
||||
border: Border.all(
|
||||
color: enabled ? UiColors.border : UiColors.border.withValues(alpha: 0.5),
|
||||
color: enabled
|
||||
? UiColors.border
|
||||
: UiColors.border.withValues(alpha: 0.5),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
const Icon(UiIcons.settings, size: 18, color: UiColors.iconSecondary),
|
||||
const Icon(
|
||||
UiIcons.settings,
|
||||
size: 18,
|
||||
color: UiColors.iconSecondary,
|
||||
),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Text(
|
||||
languageName,
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
),
|
||||
child: Text(languageName, style: UiTypography.body2r.textPrimary),
|
||||
),
|
||||
if (enabled)
|
||||
const Icon(
|
||||
@@ -220,10 +218,7 @@ class _FieldLabel extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
text,
|
||||
style: UiTypography.titleUppercase3m.textSecondary,
|
||||
);
|
||||
return Text(text, style: UiTypography.titleUppercase3m.textSecondary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,10 +239,7 @@ class _ReadOnlyField extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusMdValue),
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Text(
|
||||
value,
|
||||
style: UiTypography.body2r.textInactive,
|
||||
),
|
||||
child: Text(value, style: UiTypography.body2r.textInactive),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user