Skip to content

Commit f673e33

Browse files
committed
refactor(account): revamp user header UI and improve code structure
- Redesign the user header widget with a more modern layout - Separate sign-in and sign-out buttons into their own methods - Enhance readability and maintainability of the code - Improve type safety and reduce complexity
1 parent 8706a6d commit f673e33

File tree

1 file changed

+90
-68
lines changed

1 file changed

+90
-68
lines changed

lib/account/view/account_page.dart

Lines changed: 90 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -62,82 +62,104 @@ class AccountPage extends StatelessWidget {
6262
Widget _buildUserHeader(BuildContext context, User? user, bool isAnonymous) {
6363
final l10n = AppLocalizationsX(context).l10n;
6464
final theme = Theme.of(context);
65-
final textTheme = theme.textTheme;
6665
final colorScheme = theme.colorScheme;
6766

68-
final avatarIcon = Icon(
69-
Icons.person_outline,
70-
size: AppSpacing.xxl,
71-
color: colorScheme.onPrimaryContainer,
72-
);
73-
74-
final String displayName;
75-
final Widget statusWidget;
67+
final String statusText;
68+
final String accountTypeText;
69+
final Widget actionButton;
7670

7771
if (isAnonymous) {
78-
displayName = l10n.accountAnonymousUser;
79-
statusWidget = Padding(
80-
padding: const EdgeInsets.only(top: AppSpacing.md),
81-
child: ElevatedButton.icon(
82-
icon: const Icon(Icons.link_outlined),
83-
label: Text(l10n.accountSignInPromptButton),
84-
style: ElevatedButton.styleFrom(
85-
padding: const EdgeInsets.symmetric(
86-
horizontal: AppSpacing.lg,
87-
vertical: AppSpacing.sm,
88-
),
89-
textStyle: textTheme.labelLarge,
90-
),
91-
onPressed: () {
92-
// Navigate directly to the linking flow.
93-
context.goNamed(Routes.accountLinkingName);
94-
},
95-
),
96-
);
72+
statusText = l10n.accountAnonymousUser;
73+
accountTypeText = l10n.accountGuestAccount;
74+
actionButton = _buildSignInButton(context);
9775
} else {
98-
displayName = user?.email ?? l10n.accountNoNameUser;
99-
statusWidget = Column(
100-
mainAxisSize: MainAxisSize.min,
101-
children: [
102-
const SizedBox(height: AppSpacing.md),
103-
OutlinedButton.icon(
104-
icon: Icon(Icons.logout, color: colorScheme.error),
105-
label: Text(l10n.accountSignOutTile),
106-
style: OutlinedButton.styleFrom(
107-
foregroundColor: colorScheme.error,
108-
side: BorderSide(color: colorScheme.error.withOpacity(0.5)),
109-
padding: const EdgeInsets.symmetric(
110-
horizontal: AppSpacing.lg,
111-
vertical: AppSpacing.sm,
112-
),
113-
textStyle: textTheme.labelLarge,
114-
),
115-
onPressed: () {
116-
// Dispatch sign-out event.
117-
context.read<AuthenticationBloc>().add(
118-
const AuthenticationSignOutRequested(),
119-
);
120-
},
121-
),
122-
],
123-
);
76+
statusText = user?.email ?? l10n.accountNoNameUser;
77+
78+
final String roleDisplayName;
79+
switch (user?.appRole) {
80+
case AppUserRole.standardUser:
81+
roleDisplayName = l10n.accountRoleStandard;
82+
case AppUserRole.premiumUser:
83+
roleDisplayName = l10n.accountRolePremium;
84+
case AppUserRole.guestUser:
85+
roleDisplayName = l10n.accountGuestAccount;
86+
case null:
87+
roleDisplayName = '';
88+
}
89+
accountTypeText = roleDisplayName;
90+
actionButton = _buildSignOutButton(context);
12491
}
12592

126-
return Column(
127-
children: [
128-
CircleAvatar(
129-
radius: AppSpacing.xxl - AppSpacing.sm,
130-
backgroundColor: colorScheme.primaryContainer,
131-
child: avatarIcon,
132-
),
133-
const SizedBox(height: AppSpacing.md),
134-
Text(
135-
displayName,
136-
style: textTheme.headlineSmall,
137-
textAlign: TextAlign.center,
93+
return Card(
94+
child: Padding(
95+
padding: const EdgeInsets.all(AppSpacing.md),
96+
child: Row(
97+
crossAxisAlignment: CrossAxisAlignment.center,
98+
children: [
99+
ClipRRect(
100+
borderRadius: BorderRadius.circular(AppSpacing.sm),
101+
child: Container(
102+
width: AppSpacing.xxl + AppSpacing.sm,
103+
height: AppSpacing.xxl + AppSpacing.sm,
104+
color: colorScheme.primaryContainer,
105+
child: Icon(
106+
Icons.person_outline,
107+
size: AppSpacing.xl,
108+
color: colorScheme.onPrimaryContainer,
109+
),
110+
),
111+
),
112+
const SizedBox(width: AppSpacing.md),
113+
Expanded(
114+
child: Column(
115+
crossAxisAlignment: CrossAxisAlignment.start,
116+
children: [
117+
Text(
118+
statusText,
119+
style: theme.textTheme.titleMedium?.copyWith(
120+
fontWeight: FontWeight.bold,
121+
),
122+
maxLines: 1,
123+
overflow: TextOverflow.ellipsis,
124+
),
125+
const SizedBox(height: AppSpacing.xs),
126+
if (accountTypeText.isNotEmpty)
127+
Text(
128+
accountTypeText,
129+
style: theme.textTheme.bodySmall?.copyWith(
130+
color: colorScheme.onSurfaceVariant,
131+
),
132+
maxLines: 1,
133+
overflow: TextOverflow.ellipsis,
134+
),
135+
],
136+
),
137+
),
138+
const SizedBox(width: AppSpacing.md),
139+
actionButton,
140+
],
138141
),
139-
statusWidget,
140-
],
142+
),
143+
);
144+
}
145+
146+
/// Builds the sign-in button for anonymous users.
147+
Widget _buildSignInButton(BuildContext context) {
148+
final l10n = AppLocalizationsX(context).l10n;
149+
return ElevatedButton(
150+
onPressed: () => context.goNamed(Routes.accountLinkingName),
151+
child: Text(l10n.accountSignInPromptButton),
152+
);
153+
}
154+
155+
/// Builds the sign-out button for authenticated users.
156+
Widget _buildSignOutButton(BuildContext context) {
157+
final l10n = AppLocalizationsX(context).l10n;
158+
return OutlinedButton(
159+
onPressed: () => context.read<AuthenticationBloc>().add(
160+
const AuthenticationSignOutRequested(),
161+
),
162+
child: Text(l10n.accountSignOutTile),
141163
);
142164
}
143165

0 commit comments

Comments
 (0)