feat: Refactor onboarding experience and personal info pages
- Updated ExperiencePage to include subtitles in ExperienceSectionTitle. - Modified ExperienceSectionTitle widget to accept an optional subtitle parameter. - Refactored PersonalInfoPage to improve imports and structure. - Removed unused PersonalInfoContent and PersonalInfoForm widgets. - Introduced new widgets: EditableField, FieldLabel, ReadOnlyField, TappableRow, and LanguageSelector for better modularity. - Added AccountCard and SecurityNotice widgets for bank account section. - Enhanced SaveButton to utilize UiButton for consistency.
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
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:design_system/design_system.dart';
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
import '../blocs/bank_account_cubit.dart';
|
||||
import '../blocs/bank_account_state.dart';
|
||||
import '../widgets/account_card.dart';
|
||||
import '../widgets/add_account_form.dart';
|
||||
import '../widgets/security_notice.dart';
|
||||
|
||||
class BankAccountPage extends StatelessWidget {
|
||||
const BankAccountPage({super.key});
|
||||
@@ -26,19 +28,9 @@ class BankAccountPage extends StatelessWidget {
|
||||
final dynamic strings = t.staff.profile.bank_account_page;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: UiColors.background,
|
||||
appBar: AppBar(
|
||||
backgroundColor: UiColors.background, // Was surface
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(UiIcons.arrowLeft, color: UiColors.textSecondary),
|
||||
onPressed: () => Modular.to.popSafe(),
|
||||
),
|
||||
title: Text(strings.title, style: UiTypography.headline3m.textPrimary),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(1.0),
|
||||
child: Container(color: UiColors.border, height: 1.0),
|
||||
),
|
||||
appBar: UiAppBar(
|
||||
title: strings.title,
|
||||
showBackButton: true,
|
||||
),
|
||||
body: BlocConsumer<BankAccountCubit, BankAccountState>(
|
||||
bloc: cubit,
|
||||
@@ -88,18 +80,51 @@ class BankAccountPage extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_buildSecurityNotice(strings),
|
||||
SecurityNotice(strings: strings),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Text(
|
||||
strings.linked_accounts,
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
if (state.accounts.isEmpty)
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space10,
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
UiIcons.building,
|
||||
size: 48,
|
||||
color: UiColors.iconSecondary,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
Text(
|
||||
'No accounts yet',
|
||||
style: UiTypography.headline4m,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Text(
|
||||
'Add your first bank account to get started',
|
||||
style: UiTypography.body2m.textSecondary,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
else ...<Widget>[
|
||||
Text(
|
||||
strings.linked_accounts,
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
...state.accounts.map(
|
||||
(StaffBankAccount a) => _buildAccountCard(a, strings),
|
||||
), // Added type
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
...state.accounts.map<Widget>(
|
||||
(StaffBankAccount account) => AccountCard(
|
||||
account: account,
|
||||
strings: strings,
|
||||
),
|
||||
),
|
||||
],
|
||||
// Add extra padding at bottom
|
||||
const SizedBox(height: UiConstants.space20),
|
||||
],
|
||||
@@ -157,119 +182,4 @@ class BankAccountPage extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSecurityNotice(dynamic strings) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const Icon(UiIcons.shield, color: UiColors.primary, size: 20),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
strings.secure_title,
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space1 - 2), // 2px
|
||||
Text(
|
||||
strings.secure_subtitle,
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAccountCard(StaffBankAccount account, dynamic strings) {
|
||||
final bool isPrimary = account.isPrimary;
|
||||
const Color primaryColor = UiColors.primary;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: UiConstants.space3),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup, // Was surface, using bgPopup (white) for card
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
border: Border.all(
|
||||
color: isPrimary ? primaryColor : UiColors.border,
|
||||
width: isPrimary ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
),
|
||||
child: const Center(
|
||||
child: Icon(
|
||||
UiIcons.building,
|
||||
color: primaryColor,
|
||||
size: UiConstants.iconLg,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
account.bankName,
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
Text(
|
||||
strings.account_ending(
|
||||
last4: account.last4?.isNotEmpty == true
|
||||
? account.last4!
|
||||
: '----',
|
||||
),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
if (isPrimary)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space2,
|
||||
vertical: UiConstants.space1,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor.withValues(alpha: 0.15),
|
||||
borderRadius: UiConstants.radiusFull,
|
||||
),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
UiIcons.check,
|
||||
size: UiConstants.iconXs,
|
||||
color: primaryColor,
|
||||
),
|
||||
const SizedBox(width: UiConstants.space1),
|
||||
Text(strings.primary, style: UiTypography.body3m.primary),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
class AccountCard extends StatelessWidget {
|
||||
final StaffBankAccount account;
|
||||
final dynamic strings;
|
||||
|
||||
const AccountCard({
|
||||
super.key,
|
||||
required this.account,
|
||||
required this.strings,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool isPrimary = account.isPrimary;
|
||||
const Color primaryColor = UiColors.primary;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: UiConstants.space3),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
border: Border.all(
|
||||
color: isPrimary ? primaryColor : UiColors.border,
|
||||
width: isPrimary ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
),
|
||||
child: const Center(
|
||||
child: Icon(
|
||||
UiIcons.building,
|
||||
color: primaryColor,
|
||||
size: UiConstants.iconLg,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
account.bankName,
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
Text(
|
||||
strings.account_ending(
|
||||
last4: account.last4?.isNotEmpty == true
|
||||
? account.last4!
|
||||
: '----',
|
||||
),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
if (isPrimary)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space2,
|
||||
vertical: UiConstants.space1,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor.withValues(alpha: 0.15),
|
||||
borderRadius: UiConstants.radiusFull,
|
||||
),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
UiIcons.check,
|
||||
size: UiConstants.iconXs,
|
||||
color: primaryColor,
|
||||
),
|
||||
const SizedBox(width: UiConstants.space1),
|
||||
Text(strings.primary, style: UiTypography.body3m.primary),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SecurityNotice extends StatelessWidget {
|
||||
final dynamic strings;
|
||||
|
||||
const SecurityNotice({
|
||||
super.key,
|
||||
required this.strings,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return UiNoticeBanner(
|
||||
icon: UiIcons.shield,
|
||||
title: strings.secure_title,
|
||||
description: strings.secure_subtitle,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user