refactoring
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:afterwork/core/utils/date_formatter.dart';
|
||||
import 'event_status_badge.dart';
|
||||
import 'event_menu.dart';
|
||||
|
||||
class EventHeader extends StatelessWidget {
|
||||
@@ -8,9 +7,10 @@ class EventHeader extends StatelessWidget {
|
||||
final String userLastName;
|
||||
final String? eventDate;
|
||||
final String? imageUrl;
|
||||
final String location; // Ajout du paramètre "location" pour le lieu de l'événement
|
||||
final String location;
|
||||
final GlobalKey menuKey;
|
||||
final BuildContext menuContext;
|
||||
final VoidCallback onClose; // Ajout d'un callback pour l'action de fermeture
|
||||
|
||||
const EventHeader({
|
||||
Key? key,
|
||||
@@ -18,9 +18,10 @@ class EventHeader extends StatelessWidget {
|
||||
required this.userLastName,
|
||||
this.eventDate,
|
||||
this.imageUrl,
|
||||
required this.location, // Initialisation de "location"
|
||||
required this.location,
|
||||
required this.menuKey,
|
||||
required this.menuContext,
|
||||
required this.onClose, // Initialisation du callback de fermeture
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -33,68 +34,85 @@ class EventHeader extends StatelessWidget {
|
||||
}
|
||||
String formattedDate = date != null ? DateFormatter.formatDate(date) : 'Date inconnue';
|
||||
|
||||
return Row(
|
||||
return Stack(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundColor: Colors.grey.shade800,
|
||||
backgroundImage: imageUrl != null && imageUrl!.isNotEmpty
|
||||
? NetworkImage(imageUrl!)
|
||||
: const AssetImage('lib/assets/images/placeholder.png') as ImageProvider,
|
||||
radius: 22,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'$userName $userLastName',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
formattedDate,
|
||||
style: const TextStyle(
|
||||
color: Colors.white54,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
// Utilisation de Row pour afficher le lieu sur la même ligne
|
||||
Row(
|
||||
Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundColor: Colors.grey.shade800,
|
||||
backgroundImage: imageUrl != null && imageUrl!.isNotEmpty
|
||||
? NetworkImage(imageUrl!)
|
||||
: const AssetImage('lib/assets/images/placeholder.png') as ImageProvider,
|
||||
radius: 22,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
location.isNotEmpty ? location : 'Lieu non spécifié',
|
||||
style: const TextStyle(
|
||||
color: Colors.white60,
|
||||
fontSize: 12,
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
Text(
|
||||
'$userName $userLastName',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
formattedDate,
|
||||
style: const TextStyle(
|
||||
color: Colors.white54,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
location.isNotEmpty ? location : 'Lieu non spécifié',
|
||||
style: const TextStyle(
|
||||
color: Colors.white60,
|
||||
fontSize: 12,
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Ajout des boutons dans le coin supérieur droit
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
key: menuKey,
|
||||
icon: const Icon(Icons.more_vert, color: Colors.white54, size: 20),
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
showEventOptions(menuContext, menuKey);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, color: Colors.white54, size: 20),
|
||||
splashRadius: 20,
|
||||
onPressed: onClose, // Appel du callback de fermeture
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
key: menuKey,
|
||||
icon: const Icon(Icons.more_vert, color: Colors.white54, size: 20),
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
showEventOptions(menuContext, menuKey);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
66
lib/presentation/widgets/friend_card.dart
Normal file
66
lib/presentation/widgets/friend_card.dart
Normal file
@@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// [FriendCard] est un widget représentant une carte d'ami.
|
||||
/// Cette carte inclut l'image de l'ami, son nom, et un bouton qui permet
|
||||
/// d'interagir avec cette carte (via le `onTap`).
|
||||
///
|
||||
/// Ce widget est conçu pour être utilisé dans des listes d'amis, comme
|
||||
/// dans la section "Mes Amis" de l'application.
|
||||
class FriendCard extends StatelessWidget {
|
||||
final String name; // Le nom de l'ami
|
||||
final String imageUrl; // URL de l'image de profil de l'ami
|
||||
final VoidCallback onTap; // Fonction callback exécutée lors d'un clic sur la carte
|
||||
|
||||
/// Constructeur de [FriendCard] avec des paramètres obligatoires.
|
||||
const FriendCard({
|
||||
Key? key,
|
||||
required this.name,
|
||||
required this.imageUrl,
|
||||
required this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
// Lorsque l'utilisateur clique sur la carte, on déclenche la fonction onTap.
|
||||
debugPrint("[LOG] Carte de l'ami $name cliquée.");
|
||||
onTap(); // Exécuter le callback fourni
|
||||
},
|
||||
child: Card(
|
||||
elevation: 4, // Élévation de la carte pour donner un effet d'ombre
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.0)), // Bordure arrondie
|
||||
color: Colors.grey.shade800, // Couleur de fond de la carte
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0), // Padding interne pour espacer le contenu
|
||||
child: Row(
|
||||
children: [
|
||||
// Image de profil de l'ami affichée sous forme de cercle
|
||||
Hero(
|
||||
tag: name, // Le tag Hero permet de créer une transition animée vers un autre écran.
|
||||
child: CircleAvatar(
|
||||
backgroundImage: NetworkImage(imageUrl), // Charger l'image depuis l'URL
|
||||
radius: 30, // Taille de l'avatar
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16), // Espacement entre l'image et le nom
|
||||
// Le nom de l'ami avec un texte en gras et blanc
|
||||
Expanded(
|
||||
child: Text(
|
||||
name,
|
||||
style: const TextStyle(
|
||||
fontSize: 18, // Taille de la police
|
||||
color: Colors.white, // Couleur du texte
|
||||
fontWeight: FontWeight.bold, // Style en gras
|
||||
),
|
||||
),
|
||||
),
|
||||
// Icône de flèche indiquant que la carte est cliquable
|
||||
Icon(Icons.chevron_right, color: Colors.white70),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
105
lib/presentation/widgets/friend_detail_screen.dart
Normal file
105
lib/presentation/widgets/friend_detail_screen.dart
Normal file
@@ -0,0 +1,105 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
|
||||
/// [FriendDetailScreen] affiche les détails d'un ami, incluant son nom, son image de profil,
|
||||
/// et une option pour envoyer un message.
|
||||
///
|
||||
/// Utilisé lorsque l'utilisateur clique sur un ami pour voir plus de détails.
|
||||
class FriendDetailScreen extends StatelessWidget {
|
||||
final String name; // Nom de l'ami
|
||||
final String imageUrl; // URL de l'image de profil de l'ami
|
||||
final String friendId; // ID de l'ami pour des actions futures
|
||||
final Logger _logger = Logger(); // Logger pour suivre les actions dans le terminal
|
||||
|
||||
/// Constructeur de la classe [FriendDetailScreen].
|
||||
/// [name], [imageUrl], et [friendId] doivent être fournis.
|
||||
FriendDetailScreen({
|
||||
Key? key,
|
||||
required this.name,
|
||||
required this.imageUrl,
|
||||
required this.friendId,
|
||||
}) : super(key: key);
|
||||
|
||||
/// Méthode statique pour lancer l'écran des détails d'un ami.
|
||||
static void open(BuildContext context, String friendId, String name, String imageUrl) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => FriendDetailScreen(
|
||||
friendId: friendId,
|
||||
name: name,
|
||||
imageUrl: imageUrl,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.i('[LOG] Affichage des détails de l\'ami : $name (ID: $friendId)');
|
||||
|
||||
// Utilise `AssetImage` si `imageUrl` est vide ou ne contient pas d'URL valide.
|
||||
final imageProvider = imageUrl.isNotEmpty && Uri.tryParse(imageUrl)?.hasAbsolutePath == true
|
||||
? NetworkImage(imageUrl)
|
||||
: const AssetImage('lib/assets/images/default_avatar.png') as ImageProvider;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(name), // Titre de l'écran affichant le nom de l'ami
|
||||
backgroundColor: Colors.grey.shade800,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0), // Espacement autour du contenu
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Affichage de l'image de l'ami avec animation `Hero`
|
||||
Hero(
|
||||
tag: friendId, // Tag unique pour l'animation Hero basée sur l'ID de l'ami
|
||||
child: CircleAvatar(
|
||||
radius: 50,
|
||||
backgroundImage: imageProvider,
|
||||
backgroundColor: Colors.grey.shade800,
|
||||
onBackgroundImageError: (error, stackTrace) {
|
||||
_logger.e('[ERROR] Erreur lors du chargement de l\'image pour $name (ID: $friendId): $error');
|
||||
},
|
||||
child: imageUrl.isEmpty
|
||||
? const Icon(Icons.person, size: 50, color: Colors.white) // Icône par défaut si aucune image n'est disponible
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16), // Espacement entre l'image et le texte
|
||||
|
||||
// Affichage du nom de l'ami
|
||||
Text(
|
||||
name,
|
||||
style: const TextStyle(
|
||||
fontSize: 24, // Taille de la police pour le nom
|
||||
fontWeight: FontWeight.bold, // Texte en gras
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20), // Espacement avant le bouton
|
||||
|
||||
// Bouton pour envoyer un message à l'ami
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
_logger.i('[LOG] Envoi d\'un message à $name (ID: $friendId)');
|
||||
// Logique future pour envoyer un message à l'ami
|
||||
},
|
||||
icon: const Icon(Icons.message),
|
||||
label: const Text('Envoyer un message'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.teal, // Couleur de fond du bouton
|
||||
foregroundColor: Colors.white, // Couleur du texte et de l'icône
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
48
lib/presentation/widgets/friends_appbar.dart
Normal file
48
lib/presentation/widgets/friends_appbar.dart
Normal file
@@ -0,0 +1,48 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
|
||||
/// [FriendsAppBar] est une barre d'application personnalisée utilisée dans l'écran des amis.
|
||||
/// Elle permet d'ajouter et de gérer les amis avec des actions spécifiques.
|
||||
/// Toutes les actions sont loguées pour une traçabilité complète.
|
||||
class FriendsAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final Logger _logger = Logger(); // Logger pour tracer toutes les actions
|
||||
|
||||
FriendsAppBar({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppBar(
|
||||
backgroundColor: Colors.grey.shade800, // Couleur de fond de la barre d'application
|
||||
title: const Text(
|
||||
'Mes Amis', // Titre de l'écran
|
||||
style: TextStyle(color: Colors.white), // Couleur du texte
|
||||
),
|
||||
actions: [
|
||||
Tooltip(
|
||||
message: 'Ajouter un ami', // Améliore l'accessibilité pour l'icône d'ajout
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.group_add, color: Colors.white), // Icône pour ajouter un nouvel ami
|
||||
onPressed: () {
|
||||
_logger.i("[LOG] Bouton 'Ajouter un ami' pressé.");
|
||||
// Logique à implémenter pour ajouter un nouvel ami
|
||||
},
|
||||
),
|
||||
),
|
||||
Tooltip(
|
||||
message: 'Gérer les groupes d\'amis', // Améliore l'accessibilité pour l'icône de gestion des groupes
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.group, color: Colors.white), // Icône pour gérer les groupes d'amis
|
||||
onPressed: () {
|
||||
_logger.i("[LOG] Bouton 'Gérer les groupes' pressé.");
|
||||
// Logique à implémenter pour gérer les groupes d'amis
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Définit la taille préférée de la barre d'application.
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
73
lib/presentation/widgets/friends_circle.dart
Normal file
73
lib/presentation/widgets/friends_circle.dart
Normal file
@@ -0,0 +1,73 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import '../../domain/entities/friend.dart';
|
||||
|
||||
/// [FriendsCircle] est un widget qui affiche un ami sous forme d'avatar circulaire avec son nom.
|
||||
/// L'avatar est cliquable, permettant à l'utilisateur d'accéder aux détails de l'ami
|
||||
/// ou de déclencher d'autres actions liées.
|
||||
class FriendsCircle extends StatelessWidget {
|
||||
final Friend friend; // Représente l'entité Friend à afficher (nom et image).
|
||||
final VoidCallback onTap; // Fonction callback exécutée lorsque l'utilisateur clique sur l'avatar.
|
||||
|
||||
// Logger pour tracer les actions dans le terminal
|
||||
final Logger _logger = Logger();
|
||||
|
||||
/// Constructeur pour [FriendsCircle], prenant en entrée un ami et une fonction de callback.
|
||||
FriendsCircle({
|
||||
Key? key,
|
||||
required this.friend, // L'ami à afficher (doit inclure friendId, name, imageUrl).
|
||||
required this.onTap, // Action à exécuter lors du clic.
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Combine firstName et lastName ou utilise "Ami inconnu" par défaut.
|
||||
String displayName = [friend.firstName, friend.lastName]
|
||||
.where((namePart) => namePart != null && namePart.isNotEmpty)
|
||||
.join(" ")
|
||||
.trim();
|
||||
|
||||
if (displayName.isEmpty) {
|
||||
displayName = 'Ami inconnu';
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
_logger.i('[LOG] Avatar de ${displayName.trim()} cliqué');
|
||||
onTap(); // Exécute l'action de clic définie par l'utilisateur
|
||||
},
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center, // Centre verticalement les éléments de la colonne.
|
||||
children: [
|
||||
Hero(
|
||||
tag: friend.friendId, // Tag unique pour l'animation Hero basé sur l'ID de l'ami.
|
||||
child: CircleAvatar(
|
||||
radius: 40,
|
||||
backgroundImage: friend.imageUrl != null && friend.imageUrl!.isNotEmpty
|
||||
? NetworkImage(friend.imageUrl!) // Utilise NetworkImage si l'URL est valide
|
||||
: AssetImage('lib/assets/images/default_avatar.png') as ImageProvider, // Utilise AssetImage pour l'avatar par défaut
|
||||
onBackgroundImageError: (error, stackTrace) {
|
||||
_logger.e('[ERROR] Erreur lors du chargement de l\'image pour ${displayName.trim()} : $error');
|
||||
},
|
||||
backgroundColor: Colors.grey.shade800, // Fond si l'image ne charge pas.
|
||||
child: friend.imageUrl == null || friend.imageUrl!.isEmpty
|
||||
? const Icon(Icons.person, size: 40, color: Colors.white) // Icône de remplacement si aucune image n'est disponible
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8), // Ajoute un espace entre l'image et le texte.
|
||||
Text(
|
||||
displayName, // Affiche le nom de l'ami sous l'avatar ou une valeur par défaut.
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
38
lib/presentation/widgets/search_friends.dart
Normal file
38
lib/presentation/widgets/search_friends.dart
Normal file
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// [SearchFriends] est un widget permettant à l'utilisateur de rechercher des amis.
|
||||
/// Il inclut un champ de texte stylisé pour saisir la requête de recherche.
|
||||
/// Chaque modification du texte dans le champ génère un log dans le terminal pour suivre en temps réel l'activité.
|
||||
class SearchFriends extends StatelessWidget {
|
||||
const SearchFriends({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextField(
|
||||
style: const TextStyle(
|
||||
color: Colors.white, // Le texte saisi est de couleur blanche.
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Rechercher un ami...', // Indication textuelle pour aider l'utilisateur.
|
||||
hintStyle: const TextStyle(
|
||||
color: Colors.white54, // Style de l'indicateur avec une couleur plus claire.
|
||||
),
|
||||
filled: true,
|
||||
fillColor: Colors.grey.shade800, // Couleur de fond du champ de recherche.
|
||||
prefixIcon: const Icon(
|
||||
Icons.search, // Icône de loupe pour indiquer la recherche.
|
||||
color: Colors.white54, // Couleur de l'icône de recherche.
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(30.0), // Bordure arrondie pour un style moderne.
|
||||
borderSide: BorderSide.none, // Aucune bordure visible pour un look propre.
|
||||
),
|
||||
),
|
||||
onChanged: (value) {
|
||||
// Fonction appelée chaque fois que l'utilisateur modifie le texte dans le champ de recherche.
|
||||
debugPrint('[LOG] Recherche d\'amis : $value'); // Log de chaque saisie.
|
||||
// Vous pouvez ajouter ici la logique de filtrage de la liste des amis en fonction de la recherche.
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
49
lib/presentation/widgets/social_badge_widget.dart
Normal file
49
lib/presentation/widgets/social_badge_widget.dart
Normal file
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../core/constants/colors.dart';
|
||||
|
||||
class BadgeWidget extends StatelessWidget {
|
||||
final String badge;
|
||||
final IconData? icon; // Optionnel : ajouter une icône au badge
|
||||
|
||||
const BadgeWidget({
|
||||
Key? key,
|
||||
required this.badge,
|
||||
this.icon,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.accentColor.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
border: Border.all(
|
||||
color: AppColors.accentColor,
|
||||
width: 1.0,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (icon != null) ...[
|
||||
Icon(
|
||||
icon,
|
||||
color: AppColors.accentColor,
|
||||
size: 16.0,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
],
|
||||
Text(
|
||||
badge,
|
||||
style: TextStyle(
|
||||
color: AppColors.accentColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
119
lib/presentation/widgets/social_header_widget.dart
Normal file
119
lib/presentation/widgets/social_header_widget.dart
Normal file
@@ -0,0 +1,119 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../core/constants/colors.dart';
|
||||
import '../../../data/models/social_post_model.dart';
|
||||
import 'social_badge_widget.dart'; // Import du widget BadgeWidget
|
||||
|
||||
class SocialHeaderWidget extends StatelessWidget {
|
||||
final SocialPost post;
|
||||
final VoidCallback onEditPost;
|
||||
final VoidCallback onClosePost; // Ajout du callback pour la fermeture du post
|
||||
final GlobalKey menuKey;
|
||||
final BuildContext menuContext;
|
||||
|
||||
const SocialHeaderWidget({
|
||||
Key? key,
|
||||
required this.post,
|
||||
required this.onEditPost,
|
||||
required this.onClosePost, // Initialisation du callback de fermeture
|
||||
required this.menuKey,
|
||||
required this.menuContext,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundColor: Colors.grey.shade800,
|
||||
backgroundImage: post.userImage.isNotEmpty
|
||||
? AssetImage(post.userImage)
|
||||
: const AssetImage('lib/assets/images/placeholder.png'),
|
||||
radius: 22,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
post.userName,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Wrap(
|
||||
spacing: 6,
|
||||
children: post.badges
|
||||
.map((badge) => BadgeWidget(badge: badge))
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Ajout des boutons dans le coin supérieur droit
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min, // Réduit la taille du Row au minimum
|
||||
children: [
|
||||
IconButton(
|
||||
key: menuKey,
|
||||
icon: const Icon(Icons.more_vert, color: Colors.white54, size: 20),
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
_showOptionsMenu(menuContext, menuKey);
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 4), // Espacement entre les boutons
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, color: Colors.white54, size: 20),
|
||||
splashRadius: 20,
|
||||
onPressed: onClosePost, // Appel du callback de fermeture
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _showOptionsMenu(BuildContext context, GlobalKey menuKey) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return Container(
|
||||
color: AppColors.backgroundColor,
|
||||
child: Wrap(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
leading: Icon(Icons.edit, color: AppColors.iconPrimary),
|
||||
title: const Text('Modifier'),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
onEditPost();
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.delete, color: AppColors.iconPrimary),
|
||||
title: const Text('Supprimer'),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
48
lib/presentation/widgets/social_interaction_row.dart
Normal file
48
lib/presentation/widgets/social_interaction_row.dart
Normal file
@@ -0,0 +1,48 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../core/constants/colors.dart';
|
||||
import '../../../data/models/social_post_model.dart';
|
||||
|
||||
class SocialInteractionRow extends StatelessWidget {
|
||||
final SocialPost post;
|
||||
final VoidCallback onLike;
|
||||
final VoidCallback onComment;
|
||||
final VoidCallback onShare;
|
||||
|
||||
const SocialInteractionRow({
|
||||
Key? key,
|
||||
required this.post,
|
||||
required this.onLike,
|
||||
required this.onComment,
|
||||
required this.onShare,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildIconButton(Icons.thumb_up_alt_outlined, 'J’aime', post.likes, onLike),
|
||||
),
|
||||
Expanded(
|
||||
child: _buildIconButton(Icons.comment_outlined, 'Commentaires', post.comments, onComment),
|
||||
),
|
||||
Expanded(
|
||||
child: _buildIconButton(Icons.share_outlined, 'Partages', post.shares, onShare),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildIconButton(IconData icon, String label, int count, VoidCallback onPressed) {
|
||||
return TextButton.icon(
|
||||
onPressed: onPressed,
|
||||
icon: Icon(icon, color: AppColors.accentColor, size: 18),
|
||||
label: Text(
|
||||
'$label ($count)',
|
||||
style: const TextStyle(color: Colors.white70, fontSize: 12),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:afterwork/core/constants/colors.dart';
|
||||
|
||||
class SubmitButton extends StatelessWidget {
|
||||
final VoidCallback onPressed;
|
||||
|
||||
Reference in New Issue
Block a user