ajout page mon compte, design boff

This commit is contained in:
2025-05-05 19:24:56 +02:00
parent 456d0bb4b8
commit 4c7ce27a0c
6 changed files with 457 additions and 72 deletions

View 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,
),
),
),
],
),
),
);
}
}

View File

@ -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'),
),
],
);
}
}

View 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,
);
}
}