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

View File

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

View File

@@ -8,14 +8,11 @@ import 'package:krow_domain/krow_domain.dart';
import '../blocs/profile_cubit.dart'; import '../blocs/profile_cubit.dart';
import '../blocs/profile_state.dart'; import '../blocs/profile_state.dart';
import '../widgets/language_selector_bottom_sheet.dart';
import '../widgets/logout_button.dart'; import '../widgets/logout_button.dart';
import '../widgets/profile_header.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_score_bar.dart';
import '../widgets/reliability_stats_card.dart'; import '../widgets/reliability_stats_card.dart';
import '../widgets/section_title.dart'; import '../widgets/sections/index.dart';
/// The main Staff Profile page. /// The main Staff Profile page.
/// ///
@@ -49,7 +46,6 @@ class StaffProfilePage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final i18n = Translations.of(context).staff.profile;
final ProfileCubit cubit = Modular.get<ProfileCubit>(); final ProfileCubit cubit = Modular.get<ProfileCubit>();
// Load profile data on first build // Load profile data on first build
@@ -60,7 +56,7 @@ class StaffProfilePage extends StatelessWidget {
return Scaffold( return Scaffold(
body: BlocConsumer<ProfileCubit, ProfileState>( body: BlocConsumer<ProfileCubit, ProfileState>(
bloc: cubit, bloc: cubit,
listener: (context, state) { listener: (BuildContext context, ProfileState state) {
if (state.status == ProfileStatus.signedOut) { if (state.status == ProfileStatus.signedOut) {
Modular.to.toGetStartedPage(); Modular.to.toGetStartedPage();
} else if (state.status == ProfileStatus.error && } 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 // Show loading spinner if status is loading
if (state.status == ProfileStatus.loading) { if (state.status == ProfileStatus.loading) {
return const Center(child: CircularProgressIndicator()); 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) { if (profile == null) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} }
@@ -103,7 +99,7 @@ class StaffProfilePage extends StatelessWidget {
return SingleChildScrollView( return SingleChildScrollView(
padding: const EdgeInsets.only(bottom: UiConstants.space16), padding: const EdgeInsets.only(bottom: UiConstants.space16),
child: Column( child: Column(
children: [ children: <Widget>[
ProfileHeader( ProfileHeader(
fullName: profile.name, fullName: profile.name,
level: _mapStatusToLevel(profile.status), level: _mapStatusToLevel(profile.status),
@@ -117,7 +113,7 @@ class StaffProfilePage extends StatelessWidget {
horizontal: UiConstants.space5, horizontal: UiConstants.space5,
), ),
child: Column( child: Column(
children: [ children: <Widget>[
ReliabilityStatsCard( ReliabilityStatsCard(
totalShifts: profile.totalShifts, totalShifts: profile.totalShifts,
averageRating: profile.averageRating, averageRating: profile.averageRating,
@@ -130,105 +126,15 @@ class StaffProfilePage extends StatelessWidget {
reliabilityScore: profile.reliabilityScore, reliabilityScore: profile.reliabilityScore,
), ),
const SizedBox(height: UiConstants.space6), const SizedBox(height: UiConstants.space6),
SectionTitle(i18n.sections.onboarding), const OnboardingSection(),
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 SizedBox(height: UiConstants.space6), const SizedBox(height: UiConstants.space6),
Column( const ComplianceSection(),
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 SizedBox(height: UiConstants.space6), const SizedBox(height: UiConstants.space6),
SectionTitle(i18n.sections.finance), const FinanceSection(),
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 SizedBox(height: UiConstants.space6), const SizedBox(height: UiConstants.space6),
SectionTitle( const SupportSection(),
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 SizedBox(height: UiConstants.space6), const SizedBox(height: UiConstants.space6),
SectionTitle( const SettingsSection(),
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 SizedBox(height: UiConstants.space6), const SizedBox(height: UiConstants.space6),
LogoutButton( LogoutButton(
onTap: () => _onSignOut(cubit, state), 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(),
),
],
),
],
);
}
}