feat: Implement sections for compliance, finance, onboarding, settings, and support in staff profile

This commit is contained in:
Achintha Isuru
2026-02-18 23:32:47 -05:00
parent 8578723fb3
commit 3bda0cc0c3
9 changed files with 253 additions and 109 deletions

View File

@@ -521,7 +521,8 @@
"compliance": "COMPLIANCE",
"level_up": "LEVEL UP",
"finance": "FINANCE",
"support": "SUPPORT"
"support": "SUPPORT",
"settings": "SETTINGS"
},
"menu_items": {
"personal_info": "Personal Info",
@@ -543,7 +544,8 @@
"timecard": "Timecard",
"faqs": "FAQs",
"privacy_security": "Privacy & Security",
"messages": "Messages"
"messages": "Messages",
"language": "Language"
},
"bank_account_page": {
"title": "Bank Account",

View File

@@ -521,7 +521,8 @@
"compliance": "CUMPLIMIENTO",
"level_up": "MEJORAR NIVEL",
"finance": "FINANZAS",
"support": "SOPORTE"
"support": "SOPORTE",
"settings": "AJUSTES"
},
"menu_items": {
"personal_info": "Información Personal",
@@ -543,7 +544,8 @@
"timecard": "Tarjeta de Tiempo",
"faqs": "Preguntas Frecuentes",
"privacy_security": "Privacidad y Seguridad",
"messages": "Mensajes"
"messages": "Mensajes",
"language": "Idioma"
},
"bank_account_page": {
"title": "Cuenta Bancaria",

View File

@@ -8,14 +8,11 @@ import 'package:krow_domain/krow_domain.dart';
import '../blocs/profile_cubit.dart';
import '../blocs/profile_state.dart';
import '../widgets/language_selector_bottom_sheet.dart';
import '../widgets/logout_button.dart';
import '../widgets/profile_header.dart';
import '../widgets/profile_menu_grid.dart';
import '../widgets/profile_menu_item.dart';
import '../widgets/reliability_score_bar.dart';
import '../widgets/reliability_stats_card.dart';
import '../widgets/section_title.dart';
import '../widgets/sections/index.dart';
/// The main Staff Profile page.
///
@@ -49,7 +46,6 @@ class StaffProfilePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = Translations.of(context).staff.profile;
final ProfileCubit cubit = Modular.get<ProfileCubit>();
// Load profile data on first build
@@ -60,7 +56,7 @@ class StaffProfilePage extends StatelessWidget {
return Scaffold(
body: BlocConsumer<ProfileCubit, ProfileState>(
bloc: cubit,
listener: (context, state) {
listener: (BuildContext context, ProfileState state) {
if (state.status == ProfileStatus.signedOut) {
Modular.to.toGetStartedPage();
} else if (state.status == ProfileStatus.error &&
@@ -72,7 +68,7 @@ class StaffProfilePage extends StatelessWidget {
);
}
},
builder: (context, state) {
builder: (BuildContext context, ProfileState state) {
// Show loading spinner if status is loading
if (state.status == ProfileStatus.loading) {
return const Center(child: CircularProgressIndicator());
@@ -95,7 +91,7 @@ class StaffProfilePage extends StatelessWidget {
);
}
final profile = state.profile;
final Staff? profile = state.profile;
if (profile == null) {
return const Center(child: CircularProgressIndicator());
}
@@ -103,7 +99,7 @@ class StaffProfilePage extends StatelessWidget {
return SingleChildScrollView(
padding: const EdgeInsets.only(bottom: UiConstants.space16),
child: Column(
children: [
children: <Widget>[
ProfileHeader(
fullName: profile.name,
level: _mapStatusToLevel(profile.status),
@@ -117,7 +113,7 @@ class StaffProfilePage extends StatelessWidget {
horizontal: UiConstants.space5,
),
child: Column(
children: [
children: <Widget>[
ReliabilityStatsCard(
totalShifts: profile.totalShifts,
averageRating: profile.averageRating,
@@ -130,105 +126,15 @@ class StaffProfilePage extends StatelessWidget {
reliabilityScore: profile.reliabilityScore,
),
const SizedBox(height: UiConstants.space6),
SectionTitle(i18n.sections.onboarding),
ProfileMenuGrid(
crossAxisCount: 3,
children: [
ProfileMenuItem(
icon: UiIcons.user,
label: i18n.menu_items.personal_info,
onTap: () => Modular.to.toPersonalInfo(),
),
ProfileMenuItem(
icon: UiIcons.phone,
label: i18n.menu_items.emergency_contact,
onTap: () => Modular.to.toEmergencyContact(),
),
ProfileMenuItem(
icon: UiIcons.briefcase,
label: i18n.menu_items.experience,
onTap: () => Modular.to.toExperience(),
),
],
),
const OnboardingSection(),
const SizedBox(height: UiConstants.space6),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SectionTitle(i18n.sections.compliance),
ProfileMenuGrid(
crossAxisCount: 3,
children: [
ProfileMenuItem(
icon: UiIcons.file,
label: i18n.menu_items.tax_forms,
onTap: () => Modular.to.toTaxForms(),
),
],
),
],
),
const ComplianceSection(),
const SizedBox(height: UiConstants.space6),
SectionTitle(i18n.sections.finance),
ProfileMenuGrid(
crossAxisCount: 3,
children: [
ProfileMenuItem(
icon: UiIcons.building,
label: i18n.menu_items.bank_account,
onTap: () => Modular.to.toBankAccount(),
),
ProfileMenuItem(
icon: UiIcons.creditCard,
label: i18n.menu_items.payments,
onTap: () => Modular.to.toPayments(),
),
ProfileMenuItem(
icon: UiIcons.clock,
label: i18n.menu_items.timecard,
onTap: () => Modular.to.toTimeCard(),
),
],
),
const FinanceSection(),
const SizedBox(height: UiConstants.space6),
SectionTitle(
i18n.header.title.contains("Perfil") ? "Soporte" : "Support",
),
ProfileMenuGrid(
crossAxisCount: 3,
children: [
ProfileMenuItem(
icon: UiIcons.helpCircle,
label: i18n.header.title.contains("Perfil") ? "Preguntas Frecuentes" : "FAQs",
onTap: () => Modular.to.toFaqs(),
),
ProfileMenuItem(
icon: UiIcons.shield,
label: i18n.header.title.contains("Perfil") ? "Privacidad" : "Privacy & Security",
onTap: () => Modular.to.toPrivacySecurity(),
),
],
),
const SupportSection(),
const SizedBox(height: UiConstants.space6),
SectionTitle(
i18n.header.title.contains("Perfil") ? "Ajustes" : "Settings",
),
ProfileMenuGrid(
crossAxisCount: 3,
children: [
ProfileMenuItem(
icon: UiIcons.globe,
label: i18n.header.title.contains("Perfil") ? "Idioma" : "Language",
onTap: () {
showModalBottomSheet(
context: context,
builder: (context) => const LanguageSelectorBottomSheet(),
);
},
),
],
),
const SettingsSection(),
const SizedBox(height: UiConstants.space6),
LogoutButton(
onTap: () => _onSignOut(cubit, state),

View File

@@ -0,0 +1,39 @@
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:krow_core/core.dart';
import '../profile_menu_grid.dart';
import '../profile_menu_item.dart';
import '../section_title.dart';
/// Widget displaying the compliance section of the staff profile.
///
/// This section contains menu items for tax forms and other compliance-related documents.
class ComplianceSection extends StatelessWidget {
/// Creates a [ComplianceSection].
const ComplianceSection({super.key});
@override
Widget build(BuildContext context) {
final TranslationsStaffProfileEn i18n = Translations.of(context).staff.profile;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SectionTitle(i18n.sections.compliance),
ProfileMenuGrid(
crossAxisCount: 3,
children: <Widget>[
ProfileMenuItem(
icon: UiIcons.file,
label: i18n.menu_items.tax_forms,
onTap: () => Modular.to.toTaxForms(),
),
],
),
],
);
}
}

View File

@@ -0,0 +1,48 @@
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:krow_core/core.dart';
import '../profile_menu_grid.dart';
import '../profile_menu_item.dart';
import '../section_title.dart';
/// Widget displaying the finance section of the staff profile.
///
/// This section contains menu items for bank account, payments, and timecard information.
class FinanceSection extends StatelessWidget {
/// Creates a [FinanceSection].
const FinanceSection({super.key});
@override
Widget build(BuildContext context) {
final TranslationsStaffProfileEn i18n = Translations.of(context).staff.profile;
return Column(
children: <Widget>[
SectionTitle(i18n.sections.finance),
ProfileMenuGrid(
crossAxisCount: 3,
children: <Widget>[
ProfileMenuItem(
icon: UiIcons.building,
label: i18n.menu_items.bank_account,
onTap: () => Modular.to.toBankAccount(),
),
ProfileMenuItem(
icon: UiIcons.creditCard,
label: i18n.menu_items.payments,
onTap: () => Modular.to.toPayments(),
),
ProfileMenuItem(
icon: UiIcons.clock,
label: i18n.menu_items.timecard,
onTap: () => Modular.to.toTimeCard(),
),
],
),
],
);
}
}

View File

@@ -0,0 +1,5 @@
export 'compliance_section.dart';
export 'finance_section.dart';
export 'onboarding_section.dart';
export 'settings_section.dart';
export 'support_section.dart';

View File

@@ -0,0 +1,49 @@
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:krow_core/core.dart';
import '../profile_menu_grid.dart';
import '../profile_menu_item.dart';
import '../section_title.dart';
/// Widget displaying the onboarding section of the staff profile.
///
/// This section contains menu items for personal information, emergency contact,
/// and work experience setup.
class OnboardingSection extends StatelessWidget {
/// Creates an [OnboardingSection].
const OnboardingSection({super.key});
@override
Widget build(BuildContext context) {
final TranslationsStaffProfileEn i18n = Translations.of(context).staff.profile;
return Column(
children: <Widget>[
SectionTitle(i18n.sections.onboarding),
ProfileMenuGrid(
crossAxisCount: 3,
children: <Widget>[
ProfileMenuItem(
icon: UiIcons.user,
label: i18n.menu_items.personal_info,
onTap: () => Modular.to.toPersonalInfo(),
),
ProfileMenuItem(
icon: UiIcons.phone,
label: i18n.menu_items.emergency_contact,
onTap: () => Modular.to.toEmergencyContact(),
),
ProfileMenuItem(
icon: UiIcons.briefcase,
label: i18n.menu_items.experience,
onTap: () => Modular.to.toExperience(),
),
],
),
],
);
}
}

View File

@@ -0,0 +1,47 @@
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import '../language_selector_bottom_sheet.dart';
import '../profile_menu_grid.dart';
import '../profile_menu_item.dart';
import '../section_title.dart';
/// Widget displaying the settings section of the staff profile.
///
/// This section contains menu items for language selection.
class SettingsSection extends StatelessWidget {
/// Creates a [SettingsSection].
const SettingsSection({super.key});
@override
Widget build(BuildContext context) {
final TranslationsStaffProfileEn i18n = Translations.of(
context,
).staff.profile;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SectionTitle(i18n.sections.settings),
ProfileMenuGrid(
crossAxisCount: 3,
children: <Widget>[
ProfileMenuItem(
icon: UiIcons.globe,
label: i18n.menu_items.language,
onTap: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) =>
const LanguageSelectorBottomSheet(),
);
},
),
],
),
],
);
}
}

View File

@@ -0,0 +1,46 @@
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:krow_core/core.dart';
import '../profile_menu_grid.dart';
import '../profile_menu_item.dart';
import '../section_title.dart';
/// Widget displaying the support section of the staff profile.
///
/// This section contains menu items for FAQs and privacy & security settings.
class SupportSection extends StatelessWidget {
/// Creates a [SupportSection].
const SupportSection({super.key});
@override
Widget build(BuildContext context) {
final TranslationsStaffProfileEn i18n = Translations.of(
context,
).staff.profile;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SectionTitle(i18n.sections.support),
ProfileMenuGrid(
crossAxisCount: 3,
children: <Widget>[
ProfileMenuItem(
icon: UiIcons.helpCircle,
label: i18n.menu_items.faqs,
onTap: () => Modular.to.toFaqs(),
),
ProfileMenuItem(
icon: UiIcons.shield,
label: i18n.menu_items.privacy_security,
onTap: () => Modular.to.toPrivacySecurity(),
),
],
),
],
);
}
}