Bonne avancée sur le refactoring du menu evenements

This commit is contained in:
DahoudG
2024-08-28 15:23:51 +00:00
parent 6059f64999
commit 7e1cb85160
10 changed files with 682 additions and 149 deletions

View File

@@ -0,0 +1,304 @@
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class AddEventDialog extends StatefulWidget {
const AddEventDialog({super.key});
@override
_AddEventDialogState createState() => _AddEventDialogState();
}
class _AddEventDialogState extends State<AddEventDialog> {
final _formKey = GlobalKey<FormState>();
String _title = '';
String _description = '';
DateTime? _selectedDate;
String? _imagePath;
String _location = '';
String _category = '';
String _link = '';
LatLng? _selectedLatLng;
@override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
backgroundColor: const Color(0xFF2C2C3E),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildTitleField(),
const SizedBox(height: 10),
_buildDescriptionField(),
const SizedBox(height: 10),
_buildDatePicker(),
const SizedBox(height: 10),
_buildLocationField(context),
const SizedBox(height: 10),
_buildCategoryField(),
const SizedBox(height: 10),
_buildImagePicker(),
const SizedBox(height: 10),
_buildLinkField(),
const SizedBox(height: 20),
_buildSubmitButton(),
],
),
),
),
);
}
Widget _buildTitleField() {
return TextFormField(
decoration: InputDecoration(
labelText: 'Titre',
labelStyle: const TextStyle(color: Colors.white70),
filled: true,
fillColor: Colors.white.withOpacity(0.1),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide.none,
),
prefixIcon: const Icon(Icons.title, color: Colors.white70),
),
style: const TextStyle(color: Colors.white),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Veuillez entrer un titre';
}
return null;
},
onSaved: (value) {
_title = value ?? '';
},
);
}
Widget _buildDescriptionField() {
return TextFormField(
decoration: InputDecoration(
labelText: 'Description',
labelStyle: const TextStyle(color: Colors.white70),
filled: true,
fillColor: Colors.white.withOpacity(0.1),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide.none,
),
prefixIcon: const Icon(Icons.description, color: Colors.white70),
),
style: const TextStyle(color: Colors.white),
maxLines: 3,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Veuillez entrer une description';
}
return null;
},
onSaved: (value) {
_description = value ?? '';
},
);
}
Widget _buildDatePicker() {
return GestureDetector(
onTap: () async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime(2101),
);
if (picked != null && picked != _selectedDate) {
setState(() {
_selectedDate = picked;
});
}
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(10.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_selectedDate == null
? 'Sélectionnez une date'
: '${_selectedDate!.day}/${_selectedDate!.month}/${_selectedDate!.year}',
style: const TextStyle(color: Colors.white70),
),
const Icon(Icons.calendar_today, color: Colors.white70),
],
),
),
);
}
Widget _buildLocationField(BuildContext context) {
return GestureDetector(
onTap: () async {
final LatLng? pickedLocation = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LocationPickerScreen(),
),
);
if (pickedLocation != null) {
setState(() {
_selectedLatLng = pickedLocation;
_location = '${pickedLocation.latitude}, ${pickedLocation.longitude}';
});
}
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(10.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_selectedLatLng == null
? 'Sélectionnez une localisation'
: 'Localisation: $_location',
style: const TextStyle(color: Colors.white70),
),
const Icon(Icons.location_on, color: Colors.white70),
],
),
),
);
}
Widget _buildCategoryField() {
return TextFormField(
decoration: InputDecoration(
labelText: 'Catégorie',
labelStyle: const TextStyle(color: Colors.white70),
filled: true,
fillColor: Colors.white.withOpacity(0.1),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide.none,
),
prefixIcon: const Icon(Icons.category, color: Colors.white70),
),
style: const TextStyle(color: Colors.white),
onSaved: (value) {
_category = value ?? '';
},
);
}
Widget _buildImagePicker() {
return GestureDetector(
onTap: () {
// Logique pour sélectionner une image
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(10.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_imagePath == null ? 'Sélectionnez une image' : 'Image sélectionnée',
style: const TextStyle(color: Colors.white70),
),
const Icon(Icons.image, color: Colors.white70),
],
),
),
);
}
Widget _buildLinkField() {
return TextFormField(
decoration: InputDecoration(
labelText: 'Lien (optionnel)',
labelStyle: const TextStyle(color: Colors.white70),
filled: true,
fillColor: Colors.white.withOpacity(0.1),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide.none,
),
prefixIcon: const Icon(Icons.link, color: Colors.white70),
),
style: const TextStyle(color: Colors.white),
onSaved: (value) {
_link = value ?? '';
},
);
}
Widget _buildSubmitButton() {
return ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// Logique pour soumettre les données
Navigator.of(context).pop();
}
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF1DBF73),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
padding: const EdgeInsets.symmetric(vertical: 12.0),
minimumSize: const Size(double.infinity, 40),
),
child: const Text('Ajouter l\'événement', style: TextStyle(color: Colors.white)),
);
}
}
class LocationPickerScreen extends StatelessWidget {
const LocationPickerScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sélectionnez une localisation'),
backgroundColor: const Color(0xFF1E1E2C),
),
body: GoogleMap(
initialCameraPosition: const CameraPosition(
target: LatLng(48.8566, 2.3522), // Paris par défaut
zoom: 12.0,
),
markers: Set<Marker>.of(<Marker>[
Marker(
markerId: const MarkerId('selectedLocation'),
position: LatLng(48.8566, 2.3522), // Position par défaut
draggable: true,
onDragEnd: (newPosition) {
Navigator.of(context).pop(newPosition);
},
)
]),
onTap: (position) {
Navigator.of(context).pop(position);
},
),
);
}
}

View File

@@ -0,0 +1,209 @@
import 'package:flutter/material.dart';
class EventCard extends StatelessWidget {
final String profileImage;
final String name;
final String datePosted;
final String eventTitle;
final String eventDescription;
final String eventImageUrl;
final int reactionsCount;
final int commentsCount;
final int sharesCount;
final VoidCallback onReact;
final VoidCallback onComment;
final VoidCallback onShare;
final VoidCallback onParticipate;
final VoidCallback onCloseEvent;
final VoidCallback onMoreOptions;
const EventCard({
Key? key,
required this.profileImage,
required this.name,
required this.datePosted,
required this.eventTitle,
required this.eventDescription,
required this.eventImageUrl,
required this.reactionsCount,
required this.commentsCount,
required this.sharesCount,
required this.onReact,
required this.onComment,
required this.onShare,
required this.onParticipate,
required this.onCloseEvent,
required this.onMoreOptions, required String assetImage,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
color: const Color(0xFF2C2C3E),
margin: const EdgeInsets.symmetric(vertical: 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(),
const SizedBox(height: 10),
_buildEventDetails(),
const SizedBox(height: 10),
_buildEventImage(),
const SizedBox(height: 10),
Divider(color: Colors.white.withOpacity(0.2)),
_buildInteractionRow(),
const SizedBox(height: 10),
_buildParticipateButton(),
],
),
),
);
}
Widget _buildHeader() {
return Row(
children: [
CircleAvatar(
backgroundImage: AssetImage(profileImage),
radius: 25,
),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
datePosted,
style: const TextStyle(color: Colors.white70, fontSize: 14),
),
],
),
),
IconButton(
icon: const Icon(Icons.more_vert, color: Colors.white),
onPressed: onMoreOptions,
),
IconButton(
icon: const Icon(Icons.close, color: Colors.white),
onPressed: onCloseEvent,
),
],
);
}
Widget _buildEventDetails() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
eventTitle,
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 5),
Text(
eventDescription,
style: const TextStyle(color: Colors.white70, fontSize: 14),
),
],
);
}
Widget _buildEventImage() {
return ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.network(
eventImageUrl,
height: 180,
width: double.infinity,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Image.asset(
'lib/assets/images/placeholder.png',
height: 180,
width: double.infinity,
fit: BoxFit.cover,
);
},
),
);
}
Widget _buildInteractionRow() {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildIconButton(
icon: Icons.thumb_up_alt_outlined,
label: 'Réagir',
count: reactionsCount,
onPressed: onReact,
),
_buildIconButton(
icon: Icons.comment_outlined,
label: 'Commenter',
count: commentsCount,
onPressed: onComment,
),
_buildIconButton(
icon: Icons.share_outlined,
label: 'Partager',
count: sharesCount,
onPressed: onShare,
),
],
),
);
}
Widget _buildIconButton({
required IconData icon,
required String label,
required int count,
required VoidCallback onPressed,
}) {
return Expanded(
child: TextButton.icon(
onPressed: onPressed,
icon: Icon(icon, color: const Color(0xFF1DBF73), size: 20),
label: Text(
'$label ($count)',
style: const TextStyle(color: Colors.white70, fontSize: 12),
),
),
);
}
Widget _buildParticipateButton() {
return ElevatedButton(
onPressed: onParticipate,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF1DBF73),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
padding: const EdgeInsets.symmetric(vertical: 12.0),
minimumSize: const Size(double.infinity, 40),
),
child: const Text('Participer', style: TextStyle(color: Colors.white)),
);
}
}

View File

@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import '../dialogs/add_event_dialog.dart';
import 'event_card.dart';
class EventScreen extends StatelessWidget {
const EventScreen({super.key});
@@ -13,130 +15,44 @@ class EventScreen extends StatelessWidget {
IconButton(
icon: const Icon(Icons.add_circle_outline, size: 28, color: Color(0xFF1DBF73)),
onPressed: () {
// Logique pour ajouter un nouvel événement
_showAddEventDialog(context);
},
),
],
),
body: ListView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: 10, // Remplacez par le nombre réel d'événements
itemCount: 10,
itemBuilder: (context, index) {
return Card(
color: const Color(0xFF2C2C3E),
margin: const EdgeInsets.symmetric(vertical: 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
children: [
CircleAvatar(
backgroundImage: NetworkImage(
'https://example.com/profile_picture.png', // Remplacez par l'URL réelle de l'image de profil
),
radius: 25,
),
SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Nom Prénom', // Remplacez par le nom réel
style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
),
Text(
'Posté le 24/08/2024', // Remplacez par la date réelle
style: TextStyle(color: Colors.white70, fontSize: 14),
),
],
),
],
),
const SizedBox(height: 10),
const Text(
'Titre de l\'événement', // Remplacez par le titre réel
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 5),
const Text(
'Description détaillée de l\'événement...', // Remplacez par la description réelle
style: TextStyle(color: Colors.white70, fontSize: 14),
),
const SizedBox(height: 10),
ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.network(
'https://example.com/event_image.png', // Remplacez par l'URL réelle de l'image de l'événement
height: 180,
width: double.infinity,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Image.asset(
'lib/assets/images/placeholder.png', // Chemin vers une image de remplacement locale
height: 180,
width: double.infinity,
fit: BoxFit.cover,
);
},
),
),
const SizedBox(height: 10),
Divider(color: Colors.white.withOpacity(0.2)), // Ligne de séparation discrète
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildIconButton(
icon: Icons.thumb_up_alt_outlined,
label: 'Réagir',
count: 120, // Remplacez par le nombre réel de j'aimes
onPressed: () {
// Logique pour réagir à l'événement
},
),
_buildIconButton(
icon: Icons.comment_outlined,
label: 'Commenter',
count: 45, // Remplacez par le nombre réel de commentaires
onPressed: () {
// Logique pour commenter l'événement
},
),
_buildIconButton(
icon: Icons.share_outlined,
label: 'Partager',
count: 30, // Remplacez par le nombre réel de partages
onPressed: () {
// Logique pour partager l'événement
},
),
],
),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () {
// Logique pour participer à l'événement
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF1DBF73),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
padding: const EdgeInsets.symmetric(vertical: 12.0),
minimumSize: const Size(double.infinity, 40),
),
child: const Text('Participer', style: TextStyle(color: Colors.white)),
),
],
),
),
return EventCard(
profileImage: 'lib/assets/images/profile_picture.png',
name: 'Nom Prénom',
datePosted: 'Posté le 24/08/2024',
eventTitle: 'Titre de l\'événement',
eventDescription: 'Description détaillée de l\'événement...',
eventImageUrl: 'lib/assets/images/profile_picture.png',
reactionsCount: 120,
commentsCount: 45,
sharesCount: 30,
onReact: () {
// Logique pour réagir à l'événement
},
onComment: () {
// Logique pour commenter l'événement
},
onShare: () {
// Logique pour partager l'événement
},
onParticipate: () {
// Logique pour participer à l'événement
},
onCloseEvent: () {
// Logique pour fermer l'événement
},
onMoreOptions: () {
// Logique pour afficher plus d'options
},
assetImage: 'lib/assets/images/placeholder.png', // Ajoutez ce paramètre requis
);
},
),
@@ -144,26 +60,12 @@ class EventScreen extends StatelessWidget {
);
}
Widget _buildIconButton({
required IconData icon,
required String label,
required int count,
required VoidCallback onPressed,
}) {
return Container(
margin: const EdgeInsets.only(right: 8.0), // Espacement entre les boutons
child: Column(
children: [
IconButton(
icon: Icon(icon, color: const Color(0xFF1DBF73), size: 20),
onPressed: onPressed,
),
Text(
'$label ($count)',
style: const TextStyle(color: Colors.white70, fontSize: 12),
),
],
),
void _showAddEventDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return const AddEventDialog();
},
);
}
}

View File

@@ -50,25 +50,25 @@ class ProfileScreen extends StatelessWidget {
}
Widget _buildUserInfoSection(BuildContext context) {
return Column(
return const Column(
children: [
const CircleAvatar(
CircleAvatar(
radius: 50,
backgroundImage: AssetImage('lib/assets/images/profile_picture.png'), // Remplacer par la photo de profil
backgroundImage: AssetImage('lib/assets/images/profile_picture.png'), //Photo de profil
),
const SizedBox(height: 10),
const Text(
'Nom Prénom',
SizedBox(height: 10),
Text(
'GBANE Dahoud',
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.white),
),
const SizedBox(height: 5),
const Text(
SizedBox(height: 5),
Text(
'pseudo',
style: TextStyle(fontSize: 16, color: Colors.grey),
),
const SizedBox(height: 5),
const Text(
'email@example.com',
SizedBox(height: 5),
Text(
'gbanedahoud@lions.dev',
style: TextStyle(fontSize: 14, color: Colors.grey),
),
],