(Feat) Add google

This commit is contained in:
2026-07-18 13:11:03 +02:00
parent 01a0f1029f
commit 8dd5873f25
20 changed files with 596 additions and 379 deletions
+10 -10
View File
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:pocketbase/pocketbase.dart';
import '../pocketbase_config.dart';
import '../services/session_client.dart';
import '../supabase_config.dart';
import 'complete_profile_screen.dart';
import 'home_client_screen.dart';
import 'welcome_screen.dart';
@@ -13,14 +13,14 @@ class AuthGate extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (!SupabaseConfig.estConfigure) return const _EcranNonConfigure();
if (!PbConfig.estConfigure) return const _EcranNonConfigure();
return StreamBuilder<AuthState>(
stream: supabase.auth.onAuthStateChange,
return StreamBuilder<AuthStoreEvent>(
stream: pb.authStore.onChange,
builder: (context, snapshot) {
final session = supabase.auth.currentSession;
if (session == null) return const WelcomeScreen();
return _SessionChargee(key: ValueKey(session.user.id));
if (!pb.authStore.isValid) return const WelcomeScreen();
final uid = pb.authStore.record?.id ?? '';
return _SessionChargee(key: ValueKey(uid));
},
);
}
@@ -82,11 +82,11 @@ class _EcranNonConfigure extends StatelessWidget {
children: [
Icon(Icons.cloud_off, size: 56, color: Colors.grey),
SizedBox(height: 16),
Text('Supabase non configuré',
Text('Backend non configuré',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700)),
SizedBox(height: 8),
Text(
'Renseignez l\'URL et la clé anon dans lib/supabase_config.dart.',
'Renseignez l\'URL PocketBase dans lib/pocketbase_config.dart.',
textAlign: TextAlign.center,
style: TextStyle(color: Color(0xFF6B6B72)),
),
+2 -2
View File
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import '../pocketbase_config.dart';
import '../services/session_client.dart';
import '../supabase_config.dart';
import '../theme.dart';
/// Affiché quand le compte est connecté mais n'a pas encore de fiche fidélité
@@ -61,7 +61,7 @@ class _CompleteProfileScreenState extends State<CompleteProfileScreen> {
IconButton(
tooltip: 'Se déconnecter',
icon: const Icon(Icons.logout),
onPressed: () => supabase.auth.signOut(),
onPressed: () => pb.authStore.clear(),
),
],
),
+2 -2
View File
@@ -3,8 +3,8 @@ import 'package:qr_flutter/qr_flutter.dart';
import '../models/mouvement.dart';
import '../models/recompense.dart';
import '../pocketbase_config.dart';
import '../services/session_client.dart';
import '../supabase_config.dart';
import '../theme.dart';
import '../utils/format.dart';
@@ -58,7 +58,7 @@ class _HomeClientScreenState extends State<HomeClientScreen>
);
if (ok == true) {
_session.vider();
await supabase.auth.signOut();
pb.authStore.clear();
}
}
+11 -8
View File
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:pocketbase/pocketbase.dart';
import '../supabase_config.dart';
import '../pocketbase_config.dart';
/// Connexion d'un client existant (email + mot de passe).
class LoginScreen extends StatefulWidget {
@@ -33,14 +33,17 @@ class _LoginScreenState extends State<LoginScreen> {
_erreur = null;
});
try {
await supabase.auth.signInWithPassword(
email: _emailCtrl.text.trim(),
password: _mdpCtrl.text,
);
await pb.collection('users').authWithPassword(
_emailCtrl.text.trim(),
_mdpCtrl.text,
);
// L'AuthGate prend le relais automatiquement (pop de cet écran).
if (mounted) Navigator.of(context).pop();
} on AuthException catch (e) {
if (mounted) setState(() => _erreur = e.message);
} on ClientException catch (e) {
if (mounted) {
setState(() =>
_erreur = messageErreurPb(e, 'Email ou mot de passe incorrect.'));
}
} catch (e) {
if (mounted) setState(() => _erreur = 'Erreur : $e');
} finally {
+23 -40
View File
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:pocketbase/pocketbase.dart';
import '../pocketbase_config.dart';
import '../services/session_client.dart';
import '../supabase_config.dart';
import '../theme.dart';
/// Création d'un compte client : email + mot de passe + profil (nom, téléphone).
@@ -42,27 +42,29 @@ class _SignupScreenState extends State<SignupScreen> {
_erreur = null;
});
try {
final res = await supabase.auth.signUp(
email: _emailCtrl.text.trim(),
password: _mdpCtrl.text,
);
final email = _emailCtrl.text.trim();
// Création du compte, puis connexion immédiate (pas de confirmation
// d'email requise). On ne transmet PAS is_staff → compte client par défaut.
await pb.collection('users').create(body: {
'email': email,
'password': _mdpCtrl.text,
'passwordConfirm': _mdpCtrl.text,
});
await pb.collection('users').authWithPassword(email, _mdpCtrl.text);
if (res.session != null) {
// Connecté directement (confirmation d'email désactivée) → on crée le
// profil fidélité. L'AuthGate basculera ensuite vers l'accueil.
await SessionClient.instance.creerProfil(
nom: _nomCtrl.text,
prenom: _prenomCtrl.text,
telephone: _telCtrl.text,
);
if (mounted) Navigator.of(context).pop();
} else {
// Confirmation d'email requise : le profil sera finalisé à la 1re
// connexion (après validation du mail).
if (mounted) await _popupVerifierEmail();
// Compte connecté → on crée le profil fidélité (nom + téléphone + code).
// L'AuthGate basculera ensuite automatiquement vers l'accueil.
await SessionClient.instance.creerProfil(
nom: _nomCtrl.text,
prenom: _prenomCtrl.text,
telephone: _telCtrl.text,
);
if (mounted) Navigator.of(context).pop();
} on ClientException catch (e) {
if (mounted) {
setState(() => _erreur =
messageErreurPb(e, 'Impossible de créer le compte.'));
}
} on AuthException catch (e) {
if (mounted) setState(() => _erreur = e.message);
} catch (e) {
if (mounted) setState(() => _erreur = 'Erreur : $e');
} finally {
@@ -70,25 +72,6 @@ class _SignupScreenState extends State<SignupScreen> {
}
}
Future<void> _popupVerifierEmail() async {
await showDialog<void>(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('Vérifiez votre email'),
content: const Text(
'Un email de confirmation vous a été envoyé. Validez-le puis '
'connectez-vous pour finaliser votre carte de fidélité.'),
actions: [
FilledButton(
onPressed: () => Navigator.of(ctx).pop(),
child: const Text('OK'),
),
],
),
);
if (mounted) Navigator.of(context).pop(); // retour à l'accueil
}
@override
Widget build(BuildContext context) {
return Scaffold(
+3
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import '../theme.dart';
import '../widgets/oauth_boutons.dart';
import 'login_screen.dart';
import 'signup_screen.dart';
@@ -57,6 +58,8 @@ class WelcomeScreen extends StatelessWidget {
),
child: const Text('J\'ai déjà un compte'),
),
const SizedBox(height: 16),
const OAuthBoutons(),
const SizedBox(height: 12),
],
),