feat: Integrate Firebase Authentication and Firestore
- Added Firebase configuration to Android and iOS projects. - Created `google-services.json` and `GoogleService-Info.plist` for Firebase setup. - Implemented `AuthService` for handling user authentication with Firebase. - Updated `UserProvider` to manage user data with Firestore. - Refactored `ProfileContent`, `LoginPage`, and `SignUpPage` to use the new authentication service. - Removed the old `UserService` and replaced it with Firestore-based user management. - Added Firebase options in `firebase_options.dart` for platform-specific configurations. - Updated dependencies in `pubspec.yaml` for Firebase packages.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../providers/user_provider.dart';
|
||||
import '../../services/auth_service.dart';
|
||||
|
||||
class ProfileContent extends StatelessWidget {
|
||||
const ProfileContent({super.key});
|
||||
@@ -143,12 +144,34 @@ class ProfileContent extends StatelessWidget {
|
||||
child: Text('Annuler'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// TODO: Implémenter la mise à jour
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Profil mis à jour !')));
|
||||
onPressed: () async {
|
||||
if (prenomController.text.trim().isNotEmpty &&
|
||||
nomController.text.trim().isNotEmpty) {
|
||||
final updatedUser = user.copyWith(
|
||||
nom: nomController.text.trim(),
|
||||
prenom: prenomController.text.trim(),
|
||||
);
|
||||
|
||||
final success = await Provider.of<UserProvider>(context,
|
||||
listen: false)
|
||||
.updateUser(updatedUser);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
|
||||
if (success) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Profil mis à jour !'),
|
||||
backgroundColor: Colors.green),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Erreur lors de la mise à jour'),
|
||||
backgroundColor: Colors.red),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text('Sauvegarder'),
|
||||
),
|
||||
@@ -159,6 +182,11 @@ class ProfileContent extends StatelessWidget {
|
||||
}
|
||||
|
||||
void _showChangePasswordDialog(BuildContext context) {
|
||||
final currentPasswordController = TextEditingController();
|
||||
final newPasswordController = TextEditingController();
|
||||
final confirmPasswordController = TextEditingController();
|
||||
final authService = AuthService();
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
@@ -168,16 +196,19 @@ class ProfileContent extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
controller: currentPasswordController,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(labelText: 'Mot de passe actuel'),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
TextField(
|
||||
controller: newPasswordController,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(labelText: 'Nouveau mot de passe'),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
TextField(
|
||||
controller: confirmPasswordController,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Confirmer le mot de passe',
|
||||
@@ -191,12 +222,59 @@ class ProfileContent extends StatelessWidget {
|
||||
child: Text('Annuler'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// TODO: Implémenter le changement de mot de passe
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Mot de passe changé !')),
|
||||
);
|
||||
onPressed: () async {
|
||||
if (currentPasswordController.text.isEmpty ||
|
||||
newPasswordController.text.isEmpty ||
|
||||
confirmPasswordController.text.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Tous les champs sont requis'),
|
||||
backgroundColor: Colors.red),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPasswordController.text != confirmPasswordController.text) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Les mots de passe ne correspondent pas'),
|
||||
backgroundColor: Colors.red),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPasswordController.text.length < 8) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content:
|
||||
Text('Le mot de passe doit contenir au moins 8 caractères'),
|
||||
backgroundColor: Colors.red),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final user = Provider.of<UserProvider>(context, listen: false)
|
||||
.currentUser;
|
||||
await authService.resetPasswordFromCurrentPassword(
|
||||
currentPassword: currentPasswordController.text,
|
||||
newPassword: newPasswordController.text,
|
||||
email: user!.email,
|
||||
);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Mot de passe changé !'),
|
||||
backgroundColor: Colors.green),
|
||||
);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Erreur: Mot de passe actuel incorrect'),
|
||||
backgroundColor: Colors.red),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text('Changer'),
|
||||
),
|
||||
@@ -207,13 +285,30 @@ class ProfileContent extends StatelessWidget {
|
||||
}
|
||||
|
||||
void _showDeleteAccountDialog(BuildContext context) {
|
||||
final passwordController = TextEditingController();
|
||||
final authService = AuthService();
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Supprimer le compte'),
|
||||
content: Text(
|
||||
'Êtes-vous sûr de vouloir supprimer votre compte ? Cette action est irréversible.',
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Êtes-vous sûr de vouloir supprimer votre compte ? Cette action est irréversible.',
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
TextField(
|
||||
controller: passwordController,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Confirmez votre mot de passe',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
@@ -221,15 +316,39 @@ class ProfileContent extends StatelessWidget {
|
||||
child: Text('Annuler'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
// TODO: Implémenter la suppression
|
||||
Provider.of<UserProvider>(context, listen: false).logout();
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context,
|
||||
'/login',
|
||||
(route) => false,
|
||||
);
|
||||
onPressed: () async {
|
||||
if (passwordController.text.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Mot de passe requis'),
|
||||
backgroundColor: Colors.red),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final user = Provider.of<UserProvider>(context, listen: false)
|
||||
.currentUser;
|
||||
await authService.deleteAccount(
|
||||
password: passwordController.text,
|
||||
email: user!.email,
|
||||
);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
Provider.of<UserProvider>(context, listen: false).logout();
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context,
|
||||
'/login',
|
||||
(route) => false,
|
||||
);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content:
|
||||
Text('Erreur lors de la suppression: Mot de passe incorrect'),
|
||||
backgroundColor: Colors.red),
|
||||
);
|
||||
}
|
||||
},
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||
child: Text('Supprimer'),
|
||||
|
||||
Reference in New Issue
Block a user