simulacion de estados y flujo de notificacion, modificacion de estilos en todas las vistas
This commit is contained in:
@@ -48,7 +48,6 @@ class _EditProfileScreenState extends ConsumerState<EditProfileScreen> {
|
||||
_prefilled = true;
|
||||
}
|
||||
|
||||
// Normaliza un teléfono almacenado (con o sin lada/guiones) al formato 000-000-0000
|
||||
String _formatPhoneInitial(String? raw) {
|
||||
if (raw == null || raw.isEmpty) return '';
|
||||
final digits = raw.replaceAll(RegExp(r'\D'), '');
|
||||
@@ -132,7 +131,6 @@ class _EditProfileScreenState extends ConsumerState<EditProfileScreen> {
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppTheme.background,
|
||||
appBar: AppBar(title: const Text('Editar perfil')),
|
||||
body: userAsync.when(
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (e, _) => Center(
|
||||
@@ -154,114 +152,225 @@ class _EditProfileScreenState extends ConsumerState<EditProfileScreen> {
|
||||
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
const AppSectionTitle(title: 'Datos personales'),
|
||||
AppCard(
|
||||
child: Column(
|
||||
children: [
|
||||
AppFormField(
|
||||
label: 'Nombre',
|
||||
controller: _nameCtrl,
|
||||
validator: (v) => (v == null || v.trim().isEmpty)
|
||||
? 'Ingresa tu nombre'
|
||||
: null,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
AppFormField(
|
||||
label: 'Correo electrónico',
|
||||
controller: _emailCtrl,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (v) {
|
||||
if (v == null || v.trim().isEmpty) return null;
|
||||
if (!v.contains('@')) return 'Correo inválido';
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_PhoneField(controller: _phoneCtrl),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const AppSectionTitle(title: 'Cambiar contraseña'),
|
||||
AppCard(
|
||||
child: Column(
|
||||
children: [
|
||||
AppFormField(
|
||||
label: 'Contraseña actual',
|
||||
controller: _currentPasswordCtrl,
|
||||
obscureText: true,
|
||||
validator: (v) {
|
||||
if (!_wantsPasswordChange) return null;
|
||||
if (v == null || v.length < 6) {
|
||||
return 'Mínimo 6 caracteres';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
AppFormField(
|
||||
label: 'Nueva contraseña',
|
||||
controller: _newPasswordCtrl,
|
||||
obscureText: true,
|
||||
validator: (v) {
|
||||
if (!_wantsPasswordChange) return null;
|
||||
if (v == null || v.length < 6) {
|
||||
return 'Mínimo 6 caracteres';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
AppFormField(
|
||||
label: 'Confirmar nueva contraseña',
|
||||
controller: _confirmPasswordCtrl,
|
||||
obscureText: true,
|
||||
validator: (v) {
|
||||
if (!_wantsPasswordChange) return null;
|
||||
if (v == null || v.isEmpty) {
|
||||
return 'Confirma la contraseña';
|
||||
}
|
||||
if (v != _newPasswordCtrl.text) return 'No coincide';
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
'Déjalo en blanco si no deseas cambiarla.',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppTheme.textSecondary,
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverToBoxAdapter(child: _buildPageHeader(context)),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 0),
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
const AppSectionTitle(title: 'Datos personales'),
|
||||
AppFormCard(
|
||||
icon: Icons.person_outline,
|
||||
title: 'Información personal',
|
||||
child: Column(
|
||||
children: [
|
||||
AppFormField(
|
||||
label: 'Nombre',
|
||||
controller: _nameCtrl,
|
||||
validator: (v) =>
|
||||
(v == null || v.trim().isEmpty)
|
||||
? 'Ingresa tu nombre'
|
||||
: null,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
AppFormField(
|
||||
label: 'Correo electrónico',
|
||||
controller: _emailCtrl,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (v) {
|
||||
if (v == null || v.trim().isEmpty) return null;
|
||||
if (!v.contains('@')) return 'Correo inválido';
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_PhoneField(controller: _phoneCtrl),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 20),
|
||||
const AppSectionTitle(title: 'Cambiar contraseña'),
|
||||
AppFormCard(
|
||||
icon: Icons.lock_outline,
|
||||
title: 'Seguridad',
|
||||
child: Column(
|
||||
children: [
|
||||
AppFormField(
|
||||
label: 'Contraseña actual',
|
||||
controller: _currentPasswordCtrl,
|
||||
obscureText: true,
|
||||
validator: (v) {
|
||||
if (!_wantsPasswordChange) return null;
|
||||
if (v == null || v.length < 6) {
|
||||
return 'Mínimo 6 caracteres';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
AppFormField(
|
||||
label: 'Nueva contraseña',
|
||||
controller: _newPasswordCtrl,
|
||||
obscureText: true,
|
||||
validator: (v) {
|
||||
if (!_wantsPasswordChange) return null;
|
||||
if (v == null || v.length < 6) {
|
||||
return 'Mínimo 6 caracteres';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
AppFormField(
|
||||
label: 'Confirmar nueva contraseña',
|
||||
controller: _confirmPasswordCtrl,
|
||||
obscureText: true,
|
||||
validator: (v) {
|
||||
if (!_wantsPasswordChange) return null;
|
||||
if (v == null || v.isEmpty) {
|
||||
return 'Confirma la contraseña';
|
||||
}
|
||||
if (v != _newPasswordCtrl.text) {
|
||||
return 'No coincide';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
'Déjalo en blanco si no deseas cambiarla.',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppTheme.textSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
]),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: _saving ? null : _save,
|
||||
child: _saving
|
||||
? const SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: const Text('Guardar cambios'),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
bottomNavigationBar: _buildSaveButton(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPageHeader(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
20,
|
||||
MediaQuery.of(context).padding.top + 12,
|
||||
20,
|
||||
24,
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0xFF4A0E26), Color(0xFF9B1B4A)],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(28),
|
||||
bottomRight: Radius.circular(28),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: Container(
|
||||
width: 36,
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
const Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Editar perfil',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
'Actualiza tu información personal',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.white70,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: _saving ? null : _save,
|
||||
child: Container(
|
||||
width: 36,
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: _saving
|
||||
? const Padding(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: Colors.white,
|
||||
),
|
||||
)
|
||||
: const Icon(Icons.save_outlined, color: Colors.white, size: 20),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSaveButton() {
|
||||
return SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 12, 24, 16),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: _saving ? null : _save,
|
||||
child: _saving
|
||||
? const SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: Colors.white,
|
||||
),
|
||||
)
|
||||
: const Text('Guardar cambios'),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -369,7 +478,7 @@ class _PhoneField extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
validator: (v) {
|
||||
if (v == null || v.isEmpty) return null; // opcional
|
||||
if (v == null || v.isEmpty) return null;
|
||||
final digits = v.replaceAll('-', '');
|
||||
if (digits.length != 10) {
|
||||
return 'Ingresa exactamente 10 dígitos';
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:go_router/go_router.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/app_widgets.dart';
|
||||
import '../../core/services/auth_controller.dart';
|
||||
import '../separation_guide/ai_pet_chat_screen.dart';
|
||||
import 'models/profile_user.dart';
|
||||
import 'providers/profile_providers.dart';
|
||||
|
||||
@@ -20,91 +19,95 @@ class ProfileScreen extends ConsumerWidget {
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppTheme.background,
|
||||
appBar: AppBar(title: const Text('Mi perfil')),
|
||||
body: RefreshIndicator(
|
||||
color: AppTheme.primary,
|
||||
onRefresh: () async {
|
||||
ref.invalidate(currentUserProvider);
|
||||
await ref.read(currentUserProvider.future);
|
||||
},
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
_ProfileHeader(
|
||||
user: userAsync.asData?.value,
|
||||
fallbackRole: authRole,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
const AppSectionTitle(title: 'Mi cuenta'),
|
||||
AppMenuTile(
|
||||
icon: Icons.person_outline,
|
||||
title: 'Editar perfil',
|
||||
subtitle: 'Nombre, correo, teléfono y contraseña',
|
||||
onTap: () => context.push('/edit-profile'),
|
||||
),
|
||||
if ((userAsync.asData?.value.isAdmin ?? false) ||
|
||||
authRole == 'admin')
|
||||
AppMenuTile(
|
||||
icon: Icons.admin_panel_settings_outlined,
|
||||
title: 'Panel de administración',
|
||||
subtitle: 'Gestiona usuarios, rutas y camiones',
|
||||
onTap: () => context.go('/admin'),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
const AppSectionTitle(title: 'Soporte'),
|
||||
AppMenuTile(
|
||||
icon: Icons.pets,
|
||||
title: 'Hablar con Eco (Asistente IA)',
|
||||
subtitle: 'Guía de separación de residuos',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => const AiPetChatScreen()),
|
||||
);
|
||||
},
|
||||
),
|
||||
AppMenuTile(
|
||||
icon: Icons.help_outline,
|
||||
title: 'Ayuda y preguntas frecuentes',
|
||||
subtitle: 'Chatea con nuestro asistente',
|
||||
onTap: () => context.push('/help'),
|
||||
),
|
||||
AppMenuTile(
|
||||
icon: Icons.bug_report_outlined,
|
||||
title: 'Reportar un problema',
|
||||
subtitle: 'Reporta una unidad o incidente',
|
||||
onTap: () => context.push('/report-issue'),
|
||||
),
|
||||
AppMenuTile(
|
||||
icon: Icons.info_outline,
|
||||
title: 'Acerca de la app',
|
||||
onTap: () => context.push('/about'),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
AppMenuTile(
|
||||
icon: Icons.logout_rounded,
|
||||
title: 'Cerrar sesión',
|
||||
iconColor: AppTheme.danger,
|
||||
titleColor: AppTheme.danger,
|
||||
trailing: const SizedBox.shrink(),
|
||||
onTap: () => _confirmarCerrarSesion(context, ref),
|
||||
),
|
||||
|
||||
const SizedBox(height: 32),
|
||||
const Center(
|
||||
child: Text(
|
||||
'Recolecta v1.0.0\nServicio de Limpia · Celaya, Gto.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppTheme.textHint,
|
||||
height: 1.6,
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: _ProfileHeroHeader(
|
||||
user: userAsync.asData?.value,
|
||||
fallbackRole: authRole,
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 0),
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
const AppSectionTitle(title: 'Cuenta'),
|
||||
AppMenuTile(
|
||||
icon: Icons.person_outline,
|
||||
title: 'Editar perfil',
|
||||
subtitle: 'Nombre, correo, teléfono y contraseña',
|
||||
onTap: () => context.push('/edit-profile'),
|
||||
),
|
||||
if ((userAsync.asData?.value.isAdmin ?? false) ||
|
||||
authRole == 'admin')
|
||||
AppMenuTile(
|
||||
icon: Icons.admin_panel_settings_outlined,
|
||||
title: 'Panel de administración',
|
||||
subtitle: 'Gestiona usuarios, rutas y camiones',
|
||||
onTap: () => context.go('/admin'),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
const AppSectionTitle(title: 'Herramientas'),
|
||||
AppMenuTile(
|
||||
icon: Icons.feedback_outlined,
|
||||
title: 'Buzón de retroalimentación',
|
||||
subtitle: 'Califica el servicio de recolección',
|
||||
onTap: () => context.push('/feedback'),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
const AppSectionTitle(title: 'Soporte'),
|
||||
AppMenuTile(
|
||||
icon: Icons.help_outline,
|
||||
title: 'Ayuda y preguntas frecuentes',
|
||||
subtitle: 'Chatea con nuestro asistente',
|
||||
onTap: () => context.push('/help'),
|
||||
),
|
||||
AppMenuTile(
|
||||
icon: Icons.bug_report_outlined,
|
||||
title: 'Reportar un problema',
|
||||
subtitle: 'Reporta una unidad o incidente',
|
||||
onTap: () => context.push('/report-issue'),
|
||||
),
|
||||
AppMenuTile(
|
||||
icon: Icons.info_outline,
|
||||
title: 'Acerca de la app',
|
||||
onTap: () => context.push('/about'),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
AppMenuTile(
|
||||
icon: Icons.logout_rounded,
|
||||
title: 'Cerrar sesión',
|
||||
iconColor: AppTheme.danger,
|
||||
titleColor: AppTheme.danger,
|
||||
trailing: const SizedBox.shrink(),
|
||||
onTap: () => _confirmarCerrarSesion(context, ref),
|
||||
),
|
||||
|
||||
const SizedBox(height: 32),
|
||||
const Center(
|
||||
child: Text(
|
||||
'Recolecta v1.0.0\nServicio de Limpia · Celaya, Gto.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppTheme.textHint,
|
||||
height: 1.6,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
]),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -157,11 +160,11 @@ class ProfileScreen extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Encabezado ────────────────────────────────────────────────────────────────
|
||||
class _ProfileHeader extends StatelessWidget {
|
||||
// ── Hero header con gradiente ─────────────────────────────────────────────────
|
||||
class _ProfileHeroHeader extends StatelessWidget {
|
||||
final ProfileUser? user;
|
||||
final String fallbackRole;
|
||||
const _ProfileHeader({required this.user, required this.fallbackRole});
|
||||
const _ProfileHeroHeader({required this.user, required this.fallbackRole});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -171,66 +174,89 @@ class _ProfileHeader extends StatelessWidget {
|
||||
final initials = user?.initials ?? 'U';
|
||||
final displayName = user?.displayName ?? 'Usuario';
|
||||
final email = user?.email ?? '…';
|
||||
final roleLabel = isAdmin
|
||||
? 'Administrador'
|
||||
: isDriver
|
||||
? 'Chofer'
|
||||
: 'Ciudadano';
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.surface,
|
||||
borderRadius: BorderRadius.circular(AppTheme.radiusLg),
|
||||
border: Border.all(color: AppTheme.border, width: 0.5),
|
||||
boxShadow: AppTheme.softShadow,
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
24,
|
||||
MediaQuery.of(context).padding.top + 20,
|
||||
24,
|
||||
32,
|
||||
),
|
||||
child: Row(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [Color(0xFF4A0E26), Color(0xFF9B1B4A)],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(28),
|
||||
bottomRight: Radius.circular(28),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Avatar con iniciales
|
||||
Container(
|
||||
width: 56,
|
||||
height: 56,
|
||||
width: 80,
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.primaryLight,
|
||||
color: Colors.white.withValues(alpha: 0.15),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: AppTheme.primaryMid, width: 1.5),
|
||||
border: Border.all(
|
||||
color: Colors.white.withValues(alpha: 0.4),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
initials,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: AppTheme.primaryDark,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
displayName,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: AppTheme.textPrimary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
email,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
color: AppTheme.textSecondary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
AppStatusBadge.green(
|
||||
isAdmin
|
||||
? 'Administrador'
|
||||
: isDriver
|
||||
? 'Chofer'
|
||||
: 'Ciudadano',
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 14),
|
||||
Text(
|
||||
displayName,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
email,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.white.withValues(alpha: 0.8),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.18),
|
||||
borderRadius: BorderRadius.circular(AppTheme.radiusFull),
|
||||
border: Border.all(
|
||||
color: Colors.white.withValues(alpha: 0.3),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
roleLabel,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -238,4 +264,3 @@ class _ProfileHeader extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user