Page profile OK

This commit is contained in:
PC-PAUL\paulf 2025-03-10 17:45:46 +01:00
parent c579fd92a2
commit 471d6c5eef
4 changed files with 183 additions and 71 deletions

View File

@ -5,6 +5,20 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"name": "Launch Edge",
"request": "launch",
"type": "msedge",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
},
{
"name": "Attach to Edge",
"port": 9222,
"request": "attach",
"type": "msedge",
"webRoot": "${workspaceFolder}"
},
{ {
"name": "em2rp", "name": "em2rp",
"request": "launch", "request": "launch",

View File

@ -40,4 +40,19 @@ class UserProvider extends ChangeNotifier {
_phoneNumber = null; _phoneNumber = null;
notifyListeners(); notifyListeners();
} }
void setUserFirstName(String text) {
_firstName = text;
notifyListeners();
}
void setUserLastName(String text) {
_lastName = text;
notifyListeners();
}
void setUserPhoneNumber(String text) {
_phoneNumber = text;
notifyListeners();
}
} }

View File

@ -7,6 +7,7 @@ import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:em2rp/views/widgets/inputs/styled_text_field.dart';
class MyAccountPage extends StatefulWidget { class MyAccountPage extends StatefulWidget {
const MyAccountPage({super.key}); const MyAccountPage({super.key});
@ -50,11 +51,41 @@ class _MyAccountPageState extends State<MyAccountPage> {
Future<void> _updateUserData() async { Future<void> _updateUserData() async {
if (user != null) { if (user != null) {
await FirebaseFirestore.instance.collection('users').doc(user!.uid).set({ try {
'firstName': _firstNameController.text, await FirebaseFirestore.instance.collection('users').doc(user!.uid).set(
'lastName': _lastNameController.text, {
'phone': _phoneController.text, 'firstName': _firstNameController.text,
}, SetOptions(merge: true)); 'lastName': _lastNameController.text,
'phone': _phoneController.text,
},
SetOptions(merge: true),
);
// **MISE À JOUR DU USERPROVIDER APRÈS SUCCÈS**
final userProvider = Provider.of<UserProvider>(context, listen: false);
userProvider.setUserFirstName(_firstNameController.text);
userProvider.setUserLastName(_lastNameController.text);
userProvider.setUserPhoneNumber(_phoneController.text);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content:
Text('Informations personnelles mises à jour avec succès!'),
backgroundColor: Colors.green,
),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Erreur lors de la mise à jour des informations personnelles: ${e.toString()}',
),
backgroundColor: Colors.red,
),
);
print(
'Erreur lors de la mise à jour des informations utilisateur: ${e.toString()}');
}
} }
} }
@ -81,6 +112,7 @@ class _MyAccountPageState extends State<MyAccountPage> {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( const SnackBar(
content: Text('Photo de profil mise à jour avec succès!'), content: Text('Photo de profil mise à jour avec succès!'),
backgroundColor: Colors.green, // Optional: Style for success
), ),
); );
} else { } else {
@ -89,6 +121,7 @@ class _MyAccountPageState extends State<MyAccountPage> {
content: Text( content: Text(
'Erreur lors de la mise à jour de la photo de profil.', 'Erreur lors de la mise à jour de la photo de profil.',
), ),
backgroundColor: Colors.red, // Optional: Style for error
), ),
); );
} }
@ -107,80 +140,101 @@ class _MyAccountPageState extends State<MyAccountPage> {
); // Get UserProvider instance ); // Get UserProvider instance
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Gestion du compte')), appBar:
AppBar(title: const Text('Mon Compte')), // More user-friendly title
drawer: MainDrawer( drawer: MainDrawer(
currentPage: '/my_account', currentPage: '/my_account',
userProvider: userProvider, userProvider: userProvider,
), // Pass UserProvider to MainDrawer ), // Pass UserProvider to MainDrawer
body: Padding( body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0), // Added SingleChildScrollView for better responsiveness
child: Column( child: Padding(
crossAxisAlignment: CrossAxisAlignment.center, padding: const EdgeInsets.all(
children: [ 24.0), // Increased padding around the main content
MouseRegion( child: Column(
onEnter: (_) => setState(() => _isHoveringProfilePic = true), crossAxisAlignment: CrossAxisAlignment.center,
onExit: (_) => setState(() => _isHoveringProfilePic = false), children: [
cursor: SystemMouseCursors.click, MouseRegion(
child: GestureDetector( onEnter: (_) => setState(() => _isHoveringProfilePic = true),
onTap: onExit: (_) => setState(() => _isHoveringProfilePic = false),
_changeProfilePicture, // Call _changeProfilePicture on tap cursor: SystemMouseCursors.click,
child: Stack( child: GestureDetector(
alignment: Alignment.center, onTap:
children: [ _changeProfilePicture, // Call _changeProfilePicture on tap
ProfilePictureWidget(userId: user!.uid, radius: 45), child: Stack(
if (_isHoveringProfilePic) alignment: Alignment.center,
Container( children: [
width: 140, ProfilePictureWidget(
height: 140, userId: user!.uid,
decoration: BoxDecoration( radius:
color: Colors.black54, 80), // Increased radius for larger profile picture
shape: BoxShape.circle, if (_isHoveringProfilePic)
), Container(
child: const Center( width: 160, // Slightly larger hover overlay
child: Icon( height: 160,
Icons.edit, decoration: BoxDecoration(
color: Colors.white, color: Colors.black54,
size: 30, shape: BoxShape.circle,
),
child: const Center(
child: Icon(
Icons.edit,
color: Colors.white,
size: 36, // Slightly larger edit icon
),
), ),
), ),
), ],
], ),
), ),
), ),
), Center(
const SizedBox(height: 20), child: Card(
_buildTextField('Prénom', _firstNameController), elevation: 4.0, // Ajouter un léger relief
_buildTextField('Nom', _lastNameController), shape: RoundedRectangleBorder(
_buildTextField('Numéro de téléphone', _phoneController), borderRadius:
_buildTextField( BorderRadius.circular(12.0)), // Bords arrondis
'Email', child: Padding(
TextEditingController(text: user?.email ?? ''), padding: const EdgeInsets.all(
enabled: false, 24.0), // Padding intérieur de la carte
), child: ConstrainedBox(
const SizedBox(height: 20), // Limiter la largeur des inputs dans la carte
ElevatedButton( constraints: BoxConstraints(
onPressed: _updateUserData, maxWidth:
child: const Text('Enregistrer'), 500), // Ajustez la largeur maximale souhaitée
), child: Column(
], children: [
), StyledTextField(
), labelText: 'Prénom',
); controller: _firstNameController),
} const SizedBox(height: 16),
StyledTextField(
Widget _buildTextField( labelText: 'Nom',
String label, controller: _lastNameController),
TextEditingController controller, { const SizedBox(height: 16),
bool enabled = true, StyledTextField(
}) { labelText: 'Numéro de téléphone',
return Padding( controller: _phoneController),
padding: const EdgeInsets.symmetric(vertical: 8.0), const SizedBox(height: 16),
child: TextField( StyledTextField(
controller: controller, labelText: 'Email',
enabled: enabled, controller:
decoration: InputDecoration( TextEditingController(text: user?.email ?? ''),
labelText: label, enabled: false,
border: OutlineInputBorder(), ),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _updateUserData,
child: const Text('Enregistrer'),
),
],
),
),
),
),
),
],
),
), ),
), ),
); );

View File

@ -0,0 +1,29 @@
import 'package:flutter/material.dart';
class StyledTextField extends StatelessWidget {
final String labelText;
final TextEditingController controller;
final bool enabled;
const StyledTextField({
Key? key,
required this.labelText,
required this.controller,
this.enabled = true,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: TextField(
controller: controller,
enabled: enabled,
decoration: InputDecoration(
labelText: labelText,
border: const OutlineInputBorder(),
),
),
);
}
}