412 lines
12 KiB
Dart
412 lines
12 KiB
Dart
/// Page de détails d'un événement
|
|
library event_detail_page;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import '../../bloc/evenements_bloc.dart';
|
|
import '../../bloc/evenements_state.dart';
|
|
import '../../data/models/evenement_model.dart';
|
|
import '../widgets/inscription_event_dialog.dart';
|
|
import '../widgets/edit_event_dialog.dart';
|
|
|
|
class EventDetailPage extends StatelessWidget {
|
|
final EvenementModel evenement;
|
|
|
|
const EventDetailPage({
|
|
super.key,
|
|
required this.evenement,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Détails de l\'événement'),
|
|
backgroundColor: const Color(0xFF3B82F6),
|
|
foregroundColor: Colors.white,
|
|
actions: [
|
|
IconButton(
|
|
icon: const Icon(Icons.edit),
|
|
onPressed: () => _showEditDialog(context),
|
|
),
|
|
],
|
|
),
|
|
body: BlocBuilder<EvenementsBloc, EvenementsState>(
|
|
builder: (context, state) {
|
|
return SingleChildScrollView(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
_buildHeader(),
|
|
_buildInfoSection(),
|
|
_buildDescriptionSection(),
|
|
if (evenement.lieu != null) _buildLocationSection(),
|
|
_buildParticipantsSection(),
|
|
const SizedBox(height: 80), // Espace pour le bouton flottant
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
floatingActionButton: _buildInscriptionButton(context),
|
|
);
|
|
}
|
|
|
|
Widget _buildHeader() {
|
|
return Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(24),
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
const Color(0xFF3B82F6),
|
|
const Color(0xFF3B82F6).withOpacity(0.8),
|
|
],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white.withOpacity(0.2),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: Text(
|
|
_getTypeLabel(evenement.type),
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 12),
|
|
Text(
|
|
evenement.titre,
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 24,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: _getStatutColor(evenement.statut),
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
child: Text(
|
|
_getStatutLabel(evenement.statut),
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildInfoSection() {
|
|
return Container(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
children: [
|
|
_buildInfoRow(
|
|
Icons.calendar_today,
|
|
'Date de début',
|
|
_formatDate(evenement.dateDebut),
|
|
),
|
|
const Divider(),
|
|
_buildInfoRow(
|
|
Icons.event,
|
|
'Date de fin',
|
|
_formatDate(evenement.dateFin),
|
|
),
|
|
if (evenement.maxParticipants != null) ...[
|
|
const Divider(),
|
|
_buildInfoRow(
|
|
Icons.people,
|
|
'Places',
|
|
'${evenement.participantsActuels} / ${evenement.maxParticipants}',
|
|
),
|
|
],
|
|
if (evenement.organisateurNom != null) ...[
|
|
const Divider(),
|
|
_buildInfoRow(
|
|
Icons.person,
|
|
'Organisateur',
|
|
evenement.organisateurNom!,
|
|
),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildInfoRow(IconData icon, String label, String value) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
child: Row(
|
|
children: [
|
|
Icon(icon, color: const Color(0xFF3B82F6), size: 20),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
label,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey[600],
|
|
),
|
|
),
|
|
const SizedBox(height: 2),
|
|
Text(
|
|
value,
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildDescriptionSection() {
|
|
if (evenement.description == null) return const SizedBox.shrink();
|
|
|
|
return Container(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
'Description',
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
evenement.description!,
|
|
style: const TextStyle(fontSize: 14, height: 1.5),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildLocationSection() {
|
|
return Container(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
'Lieu',
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.location_on, color: Color(0xFF3B82F6)),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
evenement.lieu!,
|
|
style: const TextStyle(fontSize: 14),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildParticipantsSection() {
|
|
return Container(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
const Text(
|
|
'Participants',
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
Text(
|
|
'${evenement.participantsActuels} inscrits',
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color: Colors.grey[600],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 12),
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[100],
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: const Row(
|
|
children: [
|
|
Icon(Icons.info_outline, size: 20),
|
|
SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
'La liste des participants est visible uniquement pour les organisateurs',
|
|
style: TextStyle(fontSize: 12),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildInscriptionButton(BuildContext context) {
|
|
const isInscrit = false; // TODO: Vérifier si l'utilisateur est inscrit
|
|
final placesRestantes = (evenement.maxParticipants ?? 0) -
|
|
evenement.participantsActuels;
|
|
final isComplet = placesRestantes <= 0 && evenement.maxParticipants != null;
|
|
|
|
if (!isComplet) {
|
|
return FloatingActionButton.extended(
|
|
onPressed: () => _showInscriptionDialog(context, isInscrit),
|
|
backgroundColor: const Color(0xFF3B82F6),
|
|
icon: const Icon(Icons.check),
|
|
label: const Text('S\'inscrire'),
|
|
);
|
|
} else {
|
|
return const FloatingActionButton.extended(
|
|
onPressed: null,
|
|
backgroundColor: Colors.grey,
|
|
icon: Icon(Icons.block),
|
|
label: Text('Complet'),
|
|
);
|
|
}
|
|
}
|
|
|
|
void _showInscriptionDialog(BuildContext context, bool isInscrit) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => BlocProvider.value(
|
|
value: context.read<EvenementsBloc>(),
|
|
child: InscriptionEventDialog(
|
|
evenement: evenement,
|
|
isInscrit: isInscrit,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showEditDialog(BuildContext context) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => BlocProvider.value(
|
|
value: context.read<EvenementsBloc>(),
|
|
child: EditEventDialog(evenement: evenement),
|
|
),
|
|
);
|
|
}
|
|
|
|
String _formatDate(DateTime date) {
|
|
final months = [
|
|
'janvier', 'février', 'mars', 'avril', 'mai', 'juin',
|
|
'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'
|
|
];
|
|
return '${date.day} ${months[date.month - 1]} ${date.year} à ${date.hour}:${date.minute.toString().padLeft(2, '0')}';
|
|
}
|
|
|
|
String _getTypeLabel(TypeEvenement type) {
|
|
switch (type) {
|
|
case TypeEvenement.assembleeGenerale:
|
|
return 'Assemblée Générale';
|
|
case TypeEvenement.reunion:
|
|
return 'Réunion';
|
|
case TypeEvenement.formation:
|
|
return 'Formation';
|
|
case TypeEvenement.conference:
|
|
return 'Conférence';
|
|
case TypeEvenement.atelier:
|
|
return 'Atelier';
|
|
case TypeEvenement.seminaire:
|
|
return 'Séminaire';
|
|
case TypeEvenement.evenementSocial:
|
|
return 'Événement Social';
|
|
case TypeEvenement.manifestation:
|
|
return 'Manifestation';
|
|
case TypeEvenement.celebration:
|
|
return 'Célébration';
|
|
case TypeEvenement.autre:
|
|
return 'Autre';
|
|
}
|
|
}
|
|
|
|
String _getStatutLabel(StatutEvenement statut) {
|
|
switch (statut) {
|
|
case StatutEvenement.planifie:
|
|
return 'Planifié';
|
|
case StatutEvenement.confirme:
|
|
return 'Confirmé';
|
|
case StatutEvenement.enCours:
|
|
return 'En cours';
|
|
case StatutEvenement.termine:
|
|
return 'Terminé';
|
|
case StatutEvenement.annule:
|
|
return 'Annulé';
|
|
case StatutEvenement.reporte:
|
|
return 'Reporté';
|
|
}
|
|
}
|
|
|
|
Color _getStatutColor(StatutEvenement statut) {
|
|
switch (statut) {
|
|
case StatutEvenement.planifie:
|
|
return Colors.blue;
|
|
case StatutEvenement.confirme:
|
|
return Colors.green;
|
|
case StatutEvenement.enCours:
|
|
return Colors.orange;
|
|
case StatutEvenement.termine:
|
|
return Colors.grey;
|
|
case StatutEvenement.annule:
|
|
return Colors.red;
|
|
case StatutEvenement.reporte:
|
|
return Colors.purple;
|
|
}
|
|
}
|
|
}
|
|
|