feat(ui): dark mode adaptatif sur 15 pages/widgets restants
Pattern AppColors pair (isDark ternaries) appliqué sur : - login_page : SnackBar error color Color(0xFFDC2626) → AppColors.error (gradient brand intentionnel non modifié) - help_support : barre de recherche + ExpansionTile + chevrons → scheme adaptatif - system_settings : état 'Accès réservé' + unselectedLabelColor TabBar - epargne : date/description/boutons OutlinedButton foregroundColor adaptatifs - conversation_tile, connected_recent_activities, connected_upcoming_events - dashboard_notifications_widget - budgets_list_page, pending_approvals_page, approve/reject_dialog - create_organization_page, edit_organization_page, about_page Les couleurs sémantiques (error, success, warning, primary) restent inchangées. Les blancs/gradients intentionnels (AppBars brand, logos payment) préservés.
This commit is contained in:
@@ -10,6 +10,8 @@ import '../../bloc/organizations_state.dart';
|
||||
import '../../bloc/org_types_bloc.dart';
|
||||
import '../../domain/entities/type_reference_entity.dart';
|
||||
import '../../../../shared/design_system/tokens/app_colors.dart';
|
||||
import '../../../../shared/design_system/tokens/module_colors.dart';
|
||||
import '../../../../shared/design_system/components/uf_app_bar.dart';
|
||||
import '../../../../core/di/injection_container.dart';
|
||||
|
||||
const List<String> _devises = ['XOF', 'XAF', 'EUR', 'USD', 'GBP', 'CAD', 'CHF', 'MAD', 'GHS', 'NGN', 'CDF', 'KES'];
|
||||
@@ -106,12 +108,10 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.lightBackground,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
foregroundColor: Colors.white,
|
||||
title: const Text('Nouvelle Organisation'),
|
||||
elevation: 0,
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
appBar: UFAppBar(
|
||||
title: 'Nouvelle Organisation',
|
||||
moduleGradient: ModuleColors.organisationsGradient,
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: _isFormValid() ? _saveOrganisation : null,
|
||||
@@ -119,7 +119,9 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: BlocListener<OrganizationsBloc, OrganizationsState>(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: BlocListener<OrganizationsBloc, OrganizationsState>(
|
||||
listener: (context, state) {
|
||||
if (state is OrganizationCreated) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@@ -128,7 +130,7 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
Navigator.of(context).pop(true);
|
||||
} else if (state is OrganizationsError) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(state.message), backgroundColor: Colors.red),
|
||||
SnackBar(content: Text(state.message), backgroundColor: AppColors.error),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -161,20 +163,21 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSection(String title, IconData icon, List<Widget> children) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
decoration: BoxDecoration(color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(children: [
|
||||
Icon(icon, size: 16, color: AppColors.primaryGreen),
|
||||
Icon(icon, size: 16, color: AppColors.primary),
|
||||
const SizedBox(width: 6),
|
||||
Text(title, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold, color: AppColors.primaryGreen)),
|
||||
Text(title, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold, color: AppColors.primary)),
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
...children,
|
||||
@@ -237,9 +240,18 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
onTap: () => _pickDateFondation(context),
|
||||
child: InputDecorator(
|
||||
decoration: const InputDecoration(labelText: 'Date de fondation', border: OutlineInputBorder(), prefixIcon: Icon(Icons.cake)),
|
||||
child: Text(
|
||||
_dateFondation != null ? _formatDate(_dateFondation) : 'Sélectionner une date',
|
||||
style: TextStyle(color: _dateFondation != null ? AppColors.textPrimaryLight : AppColors.textSecondaryLight),
|
||||
child: Builder(
|
||||
builder: (ctx) {
|
||||
final isDark = Theme.of(ctx).brightness == Brightness.dark;
|
||||
return Text(
|
||||
_dateFondation != null ? _formatDate(_dateFondation) : 'Sélectionner une date',
|
||||
style: TextStyle(
|
||||
color: _dateFondation != null
|
||||
? (isDark ? AppColors.textPrimaryDark : AppColors.textPrimary)
|
||||
: (isDark ? AppColors.textSecondaryDark : AppColors.textSecondary),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -355,7 +367,7 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
subtitle: const Text('Visible par tous les utilisateurs', style: TextStyle(fontSize: 12)),
|
||||
value: _organisationPublique,
|
||||
onChanged: (v) => setState(() => _organisationPublique = v),
|
||||
activeColor: AppColors.primaryGreen,
|
||||
activeColor: AppColors.primary,
|
||||
),
|
||||
SwitchListTile(
|
||||
dense: true,
|
||||
@@ -364,7 +376,7 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
subtitle: const Text('Les demandes d\'adhésion sont ouvertes', style: TextStyle(fontSize: 12)),
|
||||
value: _accepteNouveauxMembres,
|
||||
onChanged: (v) => setState(() => _accepteNouveauxMembres = v),
|
||||
activeColor: AppColors.primaryGreen,
|
||||
activeColor: AppColors.primary,
|
||||
),
|
||||
];
|
||||
|
||||
@@ -392,7 +404,7 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
title: const Text('Cotisation obligatoire', style: TextStyle(fontSize: 14)),
|
||||
value: _cotisationObligatoire,
|
||||
onChanged: (v) => setState(() => _cotisationObligatoire = v),
|
||||
activeColor: AppColors.primaryGreen,
|
||||
activeColor: AppColors.primary,
|
||||
),
|
||||
if (_cotisationObligatoire) ...[
|
||||
const SizedBox(height: 8),
|
||||
@@ -451,8 +463,8 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
icon: const Icon(Icons.save),
|
||||
label: const Text('Créer l\'organisation'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: AppColors.primary,
|
||||
foregroundColor: AppColors.onPrimary,
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
|
||||
),
|
||||
@@ -466,7 +478,7 @@ class _CreateOrganizationPageState extends State<CreateOrganizationPage> {
|
||||
icon: const Icon(Icons.cancel),
|
||||
label: const Text('Annuler'),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: AppColors.textSecondaryLight,
|
||||
foregroundColor: Theme.of(context).brightness == Brightness.dark ? AppColors.textSecondaryDark : AppColors.textSecondary,
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -10,6 +10,8 @@ import '../../bloc/organizations_state.dart';
|
||||
import '../../bloc/org_types_bloc.dart';
|
||||
import '../../domain/entities/type_reference_entity.dart';
|
||||
import '../../../../shared/design_system/tokens/app_colors.dart';
|
||||
import '../../../../shared/design_system/tokens/module_colors.dart';
|
||||
import '../../../../shared/design_system/components/uf_app_bar.dart';
|
||||
import '../../../../core/di/injection_container.dart';
|
||||
|
||||
const List<String> _devisesEdit = ['XOF', 'XAF', 'EUR', 'USD', 'GBP', 'CAD', 'CHF', 'MAD', 'GHS', 'NGN', 'CDF', 'KES'];
|
||||
@@ -185,12 +187,10 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.lightBackground,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
foregroundColor: Colors.white,
|
||||
title: const Text('Modifier Organisation'),
|
||||
elevation: 0,
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
appBar: UFAppBar(
|
||||
title: 'Modifier Organisation',
|
||||
moduleGradient: ModuleColors.organisationsGradient,
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: _hasChanges() ? _saveChanges : null,
|
||||
@@ -212,7 +212,7 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
Navigator.of(context).pop(true);
|
||||
} else if (state is OrganizationsError) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(state.message), backgroundColor: Colors.red),
|
||||
SnackBar(content: Text(state.message), backgroundColor: AppColors.error),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -254,14 +254,14 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
Widget _buildSection(String title, IconData icon, List<Widget> children) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
decoration: BoxDecoration(color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(children: [
|
||||
Icon(icon, size: 16, color: AppColors.primaryGreen),
|
||||
Icon(icon, size: 16, color: AppColors.primary),
|
||||
const SizedBox(width: 6),
|
||||
Text(title, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold, color: AppColors.primaryGreen)),
|
||||
Text(title, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold, color: AppColors.primary)),
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
...children,
|
||||
@@ -326,9 +326,18 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
onTap: () => _pickDateFondation(context),
|
||||
child: InputDecorator(
|
||||
decoration: const InputDecoration(labelText: 'Date de fondation', border: OutlineInputBorder(), prefixIcon: Icon(Icons.cake)),
|
||||
child: Text(
|
||||
_dateFondation != null ? _formatDate(_dateFondation) : 'Sélectionner une date',
|
||||
style: TextStyle(color: _dateFondation != null ? AppColors.textPrimaryLight : AppColors.textSecondaryLight),
|
||||
child: Builder(
|
||||
builder: (ctx) {
|
||||
final isDark = Theme.of(ctx).brightness == Brightness.dark;
|
||||
return Text(
|
||||
_dateFondation != null ? _formatDate(_dateFondation) : 'Sélectionner une date',
|
||||
style: TextStyle(
|
||||
color: _dateFondation != null
|
||||
? (isDark ? AppColors.textPrimaryDark : AppColors.textPrimary)
|
||||
: (isDark ? AppColors.textSecondaryDark : AppColors.textSecondary),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -452,7 +461,7 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
subtitle: const Text('Visible par tous les utilisateurs', style: TextStyle(fontSize: 12)),
|
||||
value: _organisationPublique,
|
||||
onChanged: (v) => setState(() => _organisationPublique = v),
|
||||
activeColor: AppColors.primaryGreen,
|
||||
activeColor: AppColors.primary,
|
||||
),
|
||||
SwitchListTile(
|
||||
dense: true,
|
||||
@@ -461,7 +470,7 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
subtitle: const Text('Les demandes d\'adhésion sont ouvertes', style: TextStyle(fontSize: 12)),
|
||||
value: _accepteNouveauxMembres,
|
||||
onChanged: (v) => setState(() => _accepteNouveauxMembres = v),
|
||||
activeColor: AppColors.primaryGreen,
|
||||
activeColor: AppColors.primary,
|
||||
),
|
||||
];
|
||||
|
||||
@@ -490,7 +499,7 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
title: const Text('Cotisation obligatoire', style: TextStyle(fontSize: 14)),
|
||||
value: _cotisationObligatoire,
|
||||
onChanged: (v) => setState(() => _cotisationObligatoire = v),
|
||||
activeColor: AppColors.primaryGreen,
|
||||
activeColor: AppColors.primary,
|
||||
),
|
||||
if (_cotisationObligatoire) ...[
|
||||
const SizedBox(height: 8),
|
||||
@@ -559,12 +568,15 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
];
|
||||
|
||||
Widget _buildReadOnlyRow(IconData icon, String label, String value) {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final textSecondary = isDark ? AppColors.textSecondaryDark : AppColors.textSecondary;
|
||||
final textPrimary = isDark ? AppColors.textPrimaryDark : AppColors.textPrimary;
|
||||
return Row(children: [
|
||||
Icon(icon, size: 18, color: AppColors.textSecondaryLight),
|
||||
Icon(icon, size: 18, color: textSecondary),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Text(label, style: const TextStyle(fontSize: 11, color: AppColors.textSecondaryLight)),
|
||||
Text(value, style: const TextStyle(fontSize: 13, color: AppColors.textPrimaryLight, fontWeight: FontWeight.w600)),
|
||||
Text(label, style: TextStyle(fontSize: 11, color: textSecondary)),
|
||||
Text(value, style: TextStyle(fontSize: 13, color: textPrimary, fontWeight: FontWeight.w600)),
|
||||
])),
|
||||
]);
|
||||
}
|
||||
@@ -578,8 +590,8 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
icon: const Icon(Icons.save),
|
||||
label: const Text('Enregistrer les modifications'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: AppColors.primary,
|
||||
foregroundColor: AppColors.onPrimary,
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
|
||||
),
|
||||
@@ -592,7 +604,7 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
onPressed: _showDiscardDialog,
|
||||
icon: const Icon(Icons.cancel),
|
||||
label: const Text('Annuler'),
|
||||
style: OutlinedButton.styleFrom(foregroundColor: AppColors.textSecondaryLight, padding: const EdgeInsets.symmetric(vertical: 10)),
|
||||
style: OutlinedButton.styleFrom(foregroundColor: Theme.of(context).brightness == Brightness.dark ? AppColors.textSecondaryDark : AppColors.textSecondary, padding: const EdgeInsets.symmetric(vertical: 10)),
|
||||
),
|
||||
),
|
||||
]);
|
||||
@@ -681,8 +693,8 @@ class _EditOrganizationPageState extends State<EditOrganizationPage> {
|
||||
TextButton(onPressed: () => Navigator.of(ctx).pop(), child: const Text('Continuer l\'édition')),
|
||||
ElevatedButton(
|
||||
onPressed: () { Navigator.of(ctx).pop(); Navigator.of(context).pop(); },
|
||||
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
|
||||
child: const Text('Abandonner', style: TextStyle(color: Colors.white)),
|
||||
style: ElevatedButton.styleFrom(backgroundColor: AppColors.error),
|
||||
child: const Text('Abandonner', style: TextStyle(color: AppColors.onPrimary)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user