ajout page mon compte, design boff
This commit is contained in:
		| @@ -1,10 +1,9 @@ | ||||
| import 'package:em2rp/providers/local_user_provider.dart'; | ||||
| import 'package:em2rp/providers/users_provider.dart'; | ||||
| import 'package:em2rp/views/widgets/image/profile_picture.dart'; | ||||
| import 'package:em2rp/views/widgets/nav/main_drawer.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:em2rp/views/widgets/inputs/styled_text_field.dart'; | ||||
| import 'package:em2rp/views/widgets/image/profile_picture_selector.dart'; | ||||
|  | ||||
| class MyAccountPage extends StatelessWidget { | ||||
|   const MyAccountPage({super.key}); | ||||
| @@ -17,7 +16,6 @@ class MyAccountPage extends StatelessWidget { | ||||
|       body: Consumer<LocalUserProvider>( | ||||
|         builder: (context, userProvider, child) { | ||||
|           final user = userProvider.currentUser; | ||||
|           final usersProvider = context.read<UsersProvider>(); | ||||
|  | ||||
|           if (user == null) { | ||||
|             return const Center(child: CircularProgressIndicator()); | ||||
| @@ -34,18 +32,7 @@ class MyAccountPage extends StatelessWidget { | ||||
|               child: Column( | ||||
|                 crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                 children: [ | ||||
|                   GestureDetector( | ||||
|                     //onTap: () => userProvider.changeProfilePicture(); TODO | ||||
|                     child: Stack( | ||||
|                       alignment: Alignment.center, | ||||
|                       children: [ | ||||
|                         ProfilePictureWidget( | ||||
|                           userId: user.uid, | ||||
|                           radius: 80, | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|                   const ProfilePictureSelector(), | ||||
|                   Center( | ||||
|                     child: Card( | ||||
|                       elevation: 4.0, | ||||
|   | ||||
| @@ -1,66 +1,147 @@ | ||||
| import 'package:em2rp/providers/local_user_provider.dart'; | ||||
| import 'package:em2rp/views/widgets/nav/main_drawer.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:em2rp/providers/users_provider.dart'; | ||||
| import 'package:em2rp/models/user_model.dart'; | ||||
| import 'package:em2rp/views/widgets/user_management/user_card.dart'; | ||||
| import 'package:em2rp/views/widgets/user_management/edit_user_dialog.dart'; | ||||
| import 'package:em2rp/utils/colors.dart'; | ||||
|  | ||||
| class UserManagementPage extends StatelessWidget { | ||||
|   const UserManagementPage({super.key}); | ||||
| class UserManagementPage extends StatefulWidget { | ||||
|   const UserManagementPage({Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   State<UserManagementPage> createState() => _UserManagementPageState(); | ||||
| } | ||||
|  | ||||
| class _UserManagementPageState extends State<UserManagementPage> { | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     Future.microtask( | ||||
|         () => Provider.of<UsersProvider>(context, listen: false).fetchUsers()); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     // final userViewModel = Provider.of<UserManagementViewModel>(context); | ||||
|     final authProvider = Provider.of<LocalUserProvider>(context); | ||||
|  | ||||
|     if (authProvider.role != 'ADMIN') { | ||||
|       return Scaffold( | ||||
|         appBar: AppBar(title: const Text('Gestion des Utilisateurs')), | ||||
|         body: const Center( | ||||
|             child: Text('Accès non autorisé', | ||||
|                 style: TextStyle(color: Colors.red))), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return Scaffold( | ||||
|       appBar: AppBar(title: const Text('Gestion des Utilisateurs')), | ||||
|       // body: userViewModel.isLoading | ||||
|       //     ? const Center(child: CircularProgressIndicator()) | ||||
|       //     : ListView.builder( | ||||
|       //         itemCount: userViewModel.users.length, | ||||
|       //         itemBuilder: (context, index) { | ||||
|       //           final user = userViewModel.users[index]; | ||||
|       //           return ListTile( | ||||
|       //             leading: CircleAvatar( | ||||
|       //                 backgroundImage: NetworkImage(user.profilePhotoUrl)), | ||||
|       //             title: Text('${user.firstName} ${user.lastName}'), | ||||
|       //             subtitle: Text(user.email), | ||||
|       //             trailing: Row( | ||||
|       //               mainAxisSize: MainAxisSize.min, | ||||
|       //               children: [ | ||||
|       //                 IconButton( | ||||
|       //                   icon: const Icon(Icons.edit), | ||||
|       //                   onPressed: () { | ||||
|       //                     // Afficher la pop-up d'édition | ||||
|       //                   }, | ||||
|       //                 ), | ||||
|       //                 IconButton( | ||||
|       //                   icon: const Icon(Icons.lock_reset), | ||||
|       //                   onPressed: () => | ||||
|       //                       userViewModel.resetPassword(user.email), | ||||
|       //                 ), | ||||
|       //                 IconButton( | ||||
|       //                   icon: const Icon(Icons.delete, color: Colors.red), | ||||
|       //                   onPressed: () => userViewModel.deleteUser(user.uid), | ||||
|       //                 ), | ||||
|       //               ], | ||||
|       //             ), | ||||
|       //           ); | ||||
|       //         }, | ||||
|       //       ), | ||||
|       // floatingActionButton: FloatingActionButton( | ||||
|       //   onPressed: () { | ||||
|       //     // Ajouter un utilisateur | ||||
|       //   }, | ||||
|       //   child: const Icon(Icons.add), | ||||
|       // ), | ||||
|       appBar: AppBar( | ||||
|         title: const Text('Gestion des utilisateurs'), | ||||
|         backgroundColor: AppColors.rouge, | ||||
|       ), | ||||
|       drawer: const MainDrawer(currentPage: '/account_management'), | ||||
|       body: Consumer<UsersProvider>( | ||||
|         builder: (context, usersProvider, child) { | ||||
|           if (usersProvider.isLoading) { | ||||
|             return const Center(child: CircularProgressIndicator()); | ||||
|           } | ||||
|           final users = usersProvider.users; | ||||
|           if (users.isEmpty) { | ||||
|             return const Center(child: Text("Aucun utilisateur trouvé")); | ||||
|           } | ||||
|  | ||||
|           // Détermine le nombre de colonnes selon la largeur | ||||
|           final width = MediaQuery.of(context).size.width; | ||||
|           int crossAxisCount = 1; | ||||
|           if (width > 1200) | ||||
|             crossAxisCount = 4; | ||||
|           else if (width > 800) | ||||
|             crossAxisCount = 3; | ||||
|           else if (width > 600) crossAxisCount = 2; | ||||
|  | ||||
|           return Padding( | ||||
|             padding: const EdgeInsets.all(16), | ||||
|             child: GridView.builder( | ||||
|               itemCount: users.length, | ||||
|               // Dans GridView.builder | ||||
|               gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | ||||
|                 crossAxisCount: width > 1200 | ||||
|                     ? 4 | ||||
|                     : width > 800 | ||||
|                         ? 3 | ||||
|                         : width > 600 | ||||
|                             ? 2 | ||||
|                             : 1, | ||||
|                 crossAxisSpacing: 16, | ||||
|                 mainAxisSpacing: 16, | ||||
|                 // childAspectRatio fixé pour desktop ; mobile ignore car row layout | ||||
|               ), | ||||
|  | ||||
|               itemBuilder: (context, i) { | ||||
|                 final user = users[i]; | ||||
|                 return UserCard( | ||||
|                   user: user, | ||||
|                   onEdit: () => showDialog( | ||||
|                       context: context, | ||||
|                       builder: (_) => EditUserDialog(user: user)), | ||||
|                   onDelete: () => usersProvider.deleteUser(user.uid), | ||||
|                 ); | ||||
|               }, | ||||
|             ), | ||||
|           ); | ||||
|         }, | ||||
|       ), | ||||
|       floatingActionButton: FloatingActionButton( | ||||
|         backgroundColor: AppColors.rouge, | ||||
|         child: const Icon(Icons.add, color: AppColors.blanc), | ||||
|         onPressed: () => _showCreateUserDialog(context), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   void _showCreateUserDialog(BuildContext context) { | ||||
|     final firstNameController = TextEditingController(); | ||||
|     final lastNameController = TextEditingController(); | ||||
|     final emailController = TextEditingController(); | ||||
|     final phoneController = TextEditingController(); | ||||
|     final roleController = TextEditingController(); | ||||
|  | ||||
|     showDialog( | ||||
|       context: context, | ||||
|       builder: (context) => AlertDialog( | ||||
|         title: const Text('Créer un utilisateur'), | ||||
|         content: Column( | ||||
|           mainAxisSize: MainAxisSize.min, | ||||
|           children: [ | ||||
|             TextField( | ||||
|                 controller: firstNameController, | ||||
|                 decoration: const InputDecoration(labelText: 'Prénom')), | ||||
|             TextField( | ||||
|                 controller: lastNameController, | ||||
|                 decoration: const InputDecoration(labelText: 'Nom')), | ||||
|             TextField( | ||||
|                 controller: emailController, | ||||
|                 decoration: const InputDecoration(labelText: 'Email')), | ||||
|             TextField( | ||||
|                 controller: phoneController, | ||||
|                 decoration: const InputDecoration(labelText: 'Téléphone')), | ||||
|             TextField( | ||||
|                 controller: roleController, | ||||
|                 decoration: const InputDecoration(labelText: 'Rôle')), | ||||
|           ], | ||||
|         ), | ||||
|         actions: [ | ||||
|           TextButton( | ||||
|             onPressed: () => Navigator.pop(context), | ||||
|             child: const Text('Annuler'), | ||||
|           ), | ||||
|           TextButton( | ||||
|             onPressed: () { | ||||
|               final newUser = UserModel( | ||||
|                 uid: '', | ||||
|                 firstName: firstNameController.text, | ||||
|                 lastName: lastNameController.text, | ||||
|                 email: emailController.text, | ||||
|                 phoneNumber: phoneController.text, | ||||
|                 role: roleController.text, | ||||
|                 profilePhotoUrl: '', | ||||
|               ); | ||||
|               Navigator.pop(context); | ||||
|             }, | ||||
|             child: const Text('Créer'), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										63
									
								
								em2rp/lib/views/widgets/image/profile_picture_selector.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								em2rp/lib/views/widgets/image/profile_picture_selector.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:image_picker/image_picker.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:em2rp/providers/local_user_provider.dart'; | ||||
| import 'package:em2rp/views/widgets/image/profile_picture.dart'; | ||||
|  | ||||
| class ProfilePictureSelector extends StatefulWidget { | ||||
|   const ProfilePictureSelector({super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<ProfilePictureSelector> createState() => _ProfilePictureSelectorState(); | ||||
| } | ||||
|  | ||||
| class _ProfilePictureSelectorState extends State<ProfilePictureSelector> { | ||||
|   bool _isHovering = false; | ||||
|  | ||||
|   Future<void> _pickAndUploadImage() async { | ||||
|     final ImagePicker picker = ImagePicker(); | ||||
|     final XFile? image = await picker.pickImage(source: ImageSource.gallery); | ||||
|     if (image != null) { | ||||
|       // Envoie l'image au provider | ||||
|       await Provider.of<LocalUserProvider>(context, listen: false) | ||||
|           .changeProfilePicture(image); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final userProvider = Provider.of<LocalUserProvider>(context); | ||||
|     final String userId = userProvider.uid ?? ''; | ||||
|  | ||||
|     return MouseRegion( | ||||
|       onEnter: (_) => setState(() => _isHovering = true), | ||||
|       onExit: (_) => setState(() => _isHovering = false), | ||||
|       cursor: SystemMouseCursors.click, | ||||
|       child: GestureDetector( | ||||
|         onTap: _pickAndUploadImage, | ||||
|         child: Stack( | ||||
|           alignment: Alignment.center, | ||||
|           children: [ | ||||
|             ProfilePictureWidget(userId: userId, radius: 80), | ||||
|             if (_isHovering) | ||||
|               Container( | ||||
|                 width: 160, | ||||
|                 height: 160, | ||||
|                 decoration: BoxDecoration( | ||||
|                   color: Colors.black54, | ||||
|                   shape: BoxShape.circle, | ||||
|                 ), | ||||
|                 child: const Center( | ||||
|                   child: Icon( | ||||
|                     Icons.edit, | ||||
|                     size: 36, | ||||
|                     color: Colors.white, | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,89 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:em2rp/models/user_model.dart'; | ||||
| import 'package:em2rp/providers/users_provider.dart'; | ||||
|  | ||||
| class EditUserDialog extends StatefulWidget { | ||||
|   final UserModel user; | ||||
|   const EditUserDialog({required this.user, super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<EditUserDialog> createState() => _EditUserDialogState(); | ||||
| } | ||||
|  | ||||
| class _EditUserDialogState extends State<EditUserDialog> { | ||||
|   late final TextEditingController firstNameController; | ||||
|   late final TextEditingController lastNameController; | ||||
|   late final TextEditingController emailController; | ||||
|   late final TextEditingController phoneController; | ||||
|   late final TextEditingController roleController; | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     firstNameController = TextEditingController(text: widget.user.firstName); | ||||
|     lastNameController = TextEditingController(text: widget.user.lastName); | ||||
|     emailController = TextEditingController(text: widget.user.email); | ||||
|     phoneController = TextEditingController(text: widget.user.phoneNumber); | ||||
|     roleController = TextEditingController(text: widget.user.role); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   void dispose() { | ||||
|     firstNameController.dispose(); | ||||
|     lastNameController.dispose(); | ||||
|     emailController.dispose(); | ||||
|     phoneController.dispose(); | ||||
|     roleController.dispose(); | ||||
|     super.dispose(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return AlertDialog( | ||||
|       title: const Text('Modifier utilisateur'), | ||||
|       content: SingleChildScrollView( | ||||
|         child: Column( | ||||
|           children: [ | ||||
|             TextField( | ||||
|                 controller: firstNameController, | ||||
|                 decoration: const InputDecoration(labelText: 'Prénom')), | ||||
|             TextField( | ||||
|                 controller: lastNameController, | ||||
|                 decoration: const InputDecoration(labelText: 'Nom')), | ||||
|             TextField( | ||||
|                 controller: emailController, | ||||
|                 decoration: const InputDecoration(labelText: 'Email')), | ||||
|             TextField( | ||||
|                 controller: phoneController, | ||||
|                 decoration: const InputDecoration(labelText: 'Téléphone')), | ||||
|             TextField( | ||||
|                 controller: roleController, | ||||
|                 decoration: const InputDecoration(labelText: 'Rôle')), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|       actions: [ | ||||
|         TextButton( | ||||
|           onPressed: () => Navigator.pop(context), | ||||
|           child: const Text('Annuler'), | ||||
|         ), | ||||
|         ElevatedButton( | ||||
|           onPressed: () { | ||||
|             final updatedUser = widget.user.copyWith( | ||||
|               firstName: firstNameController.text, | ||||
|               lastName: lastNameController.text, | ||||
|               email: emailController.text, | ||||
|               phoneNumber: phoneController.text, | ||||
|               role: roleController.text, | ||||
|             ); | ||||
|             Provider.of<UsersProvider>(context, listen: false) | ||||
|                 .updateUser(updatedUser); | ||||
|             Navigator.pop(context); | ||||
|           }, | ||||
|           child: const Text('Enregistrer'), | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										166
									
								
								em2rp/lib/views/widgets/user_management/user_card.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								em2rp/lib/views/widgets/user_management/user_card.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:em2rp/models/user_model.dart'; | ||||
| import 'package:em2rp/utils/colors.dart'; | ||||
|  | ||||
| class UserCard extends StatelessWidget { | ||||
|   final UserModel user; | ||||
|   final VoidCallback onEdit; | ||||
|   final VoidCallback onDelete; | ||||
|  | ||||
|   // Hauteurs fixes selon le device | ||||
|   static const double _mobileHeight = 150; | ||||
|   static const double _desktopHeight = 280; | ||||
|  | ||||
|   const UserCard({ | ||||
|     Key? key, | ||||
|     required this.user, | ||||
|     required this.onEdit, | ||||
|     required this.onDelete, | ||||
|   }) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final width = MediaQuery.of(context).size.width; | ||||
|     final isMobile = width < 600; | ||||
|     final cardHeight = isMobile ? _mobileHeight : _desktopHeight; | ||||
|  | ||||
|     return SizedBox( | ||||
|       height: cardHeight, // Hauteur fixe | ||||
|       child: Card( | ||||
|         shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), | ||||
|         elevation: 3, | ||||
|         child: Padding( | ||||
|           padding: const EdgeInsets.all(12), | ||||
|           child: isMobile | ||||
|               ? _buildMobileRow(context) | ||||
|               : _buildDesktopColumn(context), | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildMobileRow(BuildContext context) { | ||||
|     return Row( | ||||
|       children: [ | ||||
|         _profileAvatar(48), | ||||
|         const SizedBox(width: 12), | ||||
|         Expanded( | ||||
|           child: Column( | ||||
|             mainAxisAlignment: MainAxisAlignment.center, // Centré verticalement | ||||
|             crossAxisAlignment: CrossAxisAlignment.start, | ||||
|             children: [ | ||||
|               Text("${user.firstName} ${user.lastName}", | ||||
|                   style: Theme.of(context).textTheme.titleSmall), | ||||
|               Text(user.email, style: Theme.of(context).textTheme.bodySmall), | ||||
|               const SizedBox(height: 8), | ||||
|               Row( | ||||
|                 children: [ | ||||
|                   Flexible( | ||||
|                     child: ElevatedButton.icon( | ||||
|                       icon: const Icon(Icons.edit, size: 14), | ||||
|                       label: const Text("Modifier"), | ||||
|                       onPressed: onEdit, | ||||
|                       style: ElevatedButton.styleFrom( | ||||
|                         backgroundColor: AppColors.rouge, | ||||
|                         foregroundColor: AppColors.blanc, | ||||
|                         padding: const EdgeInsets.symmetric( | ||||
|                             horizontal: 8, vertical: 4), | ||||
|                         textStyle: const TextStyle(fontSize: 12), | ||||
|                         shape: RoundedRectangleBorder( | ||||
|                             borderRadius: BorderRadius.circular(6)), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                   const SizedBox(width: 8), | ||||
|                   Flexible( | ||||
|                     child: ElevatedButton.icon( | ||||
|                       icon: const Icon(Icons.delete, size: 14), | ||||
|                       label: const Text("Supprimer"), | ||||
|                       onPressed: onDelete, | ||||
|                       style: ElevatedButton.styleFrom( | ||||
|                         backgroundColor: AppColors.gris, | ||||
|                         foregroundColor: AppColors.blanc, | ||||
|                         padding: const EdgeInsets.symmetric( | ||||
|                             horizontal: 8, vertical: 4), | ||||
|                         textStyle: const TextStyle(fontSize: 12), | ||||
|                         shape: RoundedRectangleBorder( | ||||
|                             borderRadius: BorderRadius.circular(6)), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _buildDesktopColumn(BuildContext context) { | ||||
|     return Column( | ||||
|       mainAxisAlignment: MainAxisAlignment.spaceBetween, // Écarte haut/bas | ||||
|       children: [ | ||||
|         _profileAvatar(80), | ||||
|         Column( | ||||
|           children: [ | ||||
|             Text("${user.firstName} ${user.lastName}", | ||||
|                 style: Theme.of(context).textTheme.titleSmall), | ||||
|             const SizedBox(height: 4), | ||||
|             Text(user.email, style: Theme.of(context).textTheme.bodySmall), | ||||
|             const SizedBox(height: 4), | ||||
|             Text(user.role, | ||||
|                 style: Theme.of(context) | ||||
|                     .textTheme | ||||
|                     .bodySmall! | ||||
|                     .copyWith(color: AppColors.gris)), | ||||
|           ], | ||||
|         ), | ||||
|         Row( | ||||
|           mainAxisAlignment: MainAxisAlignment.spaceEvenly, | ||||
|           children: [ | ||||
|             ElevatedButton.icon( | ||||
|               icon: const Icon(Icons.edit, size: 18), | ||||
|               label: const Text("Modifier"), | ||||
|               onPressed: onEdit, | ||||
|               style: ElevatedButton.styleFrom( | ||||
|                 backgroundColor: AppColors.rouge, | ||||
|                 foregroundColor: AppColors.blanc, | ||||
|                 padding: | ||||
|                     const EdgeInsets.symmetric(horizontal: 12, vertical: 8), | ||||
|                 shape: RoundedRectangleBorder( | ||||
|                     borderRadius: BorderRadius.circular(8)), | ||||
|               ), | ||||
|             ), | ||||
|             ElevatedButton.icon( | ||||
|               icon: const Icon(Icons.delete, size: 18), | ||||
|               label: const Text("Supprimer"), | ||||
|               onPressed: onDelete, | ||||
|               style: ElevatedButton.styleFrom( | ||||
|                 backgroundColor: AppColors.gris, | ||||
|                 foregroundColor: AppColors.blanc, | ||||
|                 padding: | ||||
|                     const EdgeInsets.symmetric(horizontal: 12, vertical: 8), | ||||
|                 shape: RoundedRectangleBorder( | ||||
|                     borderRadius: BorderRadius.circular(8)), | ||||
|               ), | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   Widget _profileAvatar(double size) { | ||||
|     return CircleAvatar( | ||||
|       radius: size / 2, | ||||
|       backgroundImage: user.profilePhotoUrl.isNotEmpty | ||||
|           ? NetworkImage(user.profilePhotoUrl) | ||||
|           : null, | ||||
|       backgroundColor: Colors.grey[200], | ||||
|       child: user.profilePhotoUrl.isEmpty | ||||
|           ? Icon(Icons.person, size: size * 0.6, color: AppColors.noir) | ||||
|           : null, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user