feat(ui): RefreshIndicator + AlwaysScrollable + dark mode sur 14 pages
RefreshIndicator ajouté (dispatche les events BLoC appropriés) : - adhesion_detail, adhesions_page, demande_aide_detail, demandes_aide_page - event_detail, organization_detail, org_selector, org_types - user_management_detail, reports (TabBarView), logs (Dashboard tab) - profile (onglet Perso), backup (3 onglets), notifications Fixes associés : - AlwaysScrollableScrollPhysics sur tous les scroll widgets (permet pull-to-refresh même si contenu < écran) - Empty states des listes : wrappés dans SingleChildScrollView pour refresh - Dark mode adaptatif sur textes/surfaces/borders hardcodés - backup_page : bouton retour ajouté dans le header gradient - org_types : chevron/star/border adaptatifs - reports : couleurs placeholders graphique + chevrons
This commit is contained in:
@@ -2,7 +2,10 @@
|
||||
library event_detail_page;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../../shared/design_system/tokens/module_colors.dart';
|
||||
import '../../../../shared/design_system/tokens/color_tokens.dart';
|
||||
import '../../../../shared/design_system/tokens/app_colors.dart';
|
||||
import '../../../../shared/design_system/components/uf_app_bar.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../../../core/di/injection.dart';
|
||||
import '../../bloc/evenements_bloc.dart';
|
||||
@@ -51,10 +54,9 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Détails de l\'événement'),
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
foregroundColor: Colors.white,
|
||||
appBar: UFAppBar(
|
||||
title: "Détails de l'événement",
|
||||
moduleGradient: ModuleColors.evenementsGradient,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.edit),
|
||||
@@ -62,10 +64,16 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: BlocBuilder<EvenementsBloc, EvenementsState>(
|
||||
builder: (context, state) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: BlocBuilder<EvenementsBloc, EvenementsState>(
|
||||
builder: (context, state) {
|
||||
return RefreshIndicator(
|
||||
color: ModuleColors.evenements,
|
||||
onRefresh: _loadInscriptionStatus,
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildHeader(),
|
||||
@@ -76,8 +84,10 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
const SizedBox(height: 80), // Espace pour le bouton flottant
|
||||
],
|
||||
),
|
||||
);
|
||||
), // SingleChildScrollView
|
||||
); // RefreshIndicator
|
||||
},
|
||||
),
|
||||
),
|
||||
floatingActionButton: _buildInscriptionButton(context),
|
||||
);
|
||||
@@ -87,12 +97,9 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.primaryGreen,
|
||||
AppColors.primaryGreen.withOpacity(0.8),
|
||||
],
|
||||
colors: ModuleColors.evenementsGradient,
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
@@ -191,7 +198,7 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, color: AppColors.primaryGreen, size: 20),
|
||||
Icon(icon, color: ModuleColors.evenements, size: 20),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
@@ -201,7 +208,7 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
@@ -261,7 +268,7 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.location_on, color: AppColors.primaryGreen),
|
||||
const Icon(Icons.location_on, color: ModuleColors.evenements),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
@@ -296,7 +303,7 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
'${widget.evenement.participantsActuels} inscrits',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[600],
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -305,7 +312,7 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[100],
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: const Row(
|
||||
@@ -335,14 +342,14 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
if (!isComplet) {
|
||||
return FloatingActionButton.extended(
|
||||
onPressed: () => _showInscriptionDialog(context, isInscrit),
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
backgroundColor: ModuleColors.evenements,
|
||||
icon: const Icon(Icons.check),
|
||||
label: const Text('S\'inscrire'),
|
||||
);
|
||||
} else {
|
||||
return const FloatingActionButton.extended(
|
||||
onPressed: null,
|
||||
backgroundColor: Colors.grey,
|
||||
backgroundColor: AppColors.textTertiary,
|
||||
icon: Icon(Icons.block),
|
||||
label: Text('Complet'),
|
||||
);
|
||||
@@ -425,17 +432,17 @@ class _EventDetailPageState extends State<EventDetailPage> {
|
||||
Color _getStatutColor(StatutEvenement statut) {
|
||||
switch (statut) {
|
||||
case StatutEvenement.planifie:
|
||||
return AppColors.info;
|
||||
return ColorTokens.info;
|
||||
case StatutEvenement.confirme:
|
||||
return AppColors.success;
|
||||
return ColorTokens.success;
|
||||
case StatutEvenement.enCours:
|
||||
return AppColors.warning;
|
||||
return ColorTokens.warningLight;
|
||||
case StatutEvenement.termine:
|
||||
return AppColors.textSecondaryLight;
|
||||
return ColorTokens.textSecondary;
|
||||
case StatutEvenement.annule:
|
||||
return AppColors.error;
|
||||
return ColorTokens.error;
|
||||
case StatutEvenement.reporte:
|
||||
return AppColors.brandGreen;
|
||||
return ColorTokens.warning;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user