import 'package:flutter/material.dart'; import 'package:pocketbase/pocketbase.dart'; import '../pocketbase_config.dart'; import '../theme.dart'; /// Connexion du personnel du magasin (staff). Les comptes staff sont créés dans /// PocketBase (champ is_staff = true) — pas d'inscription libre ici. class StaffLoginScreen extends StatefulWidget { const StaffLoginScreen({super.key}); @override State createState() => _StaffLoginScreenState(); } class _StaffLoginScreenState extends State { final _formKey = GlobalKey(); final _emailCtrl = TextEditingController(); final _mdpCtrl = TextEditingController(); bool _enCours = false; bool _voirMdp = false; String? _erreur; @override void dispose() { _emailCtrl.dispose(); _mdpCtrl.dispose(); super.dispose(); } Future _connexion() async { if (!_formKey.currentState!.validate()) return; setState(() { _enCours = true; _erreur = null; }); try { await pb.collection('users').authWithPassword( _emailCtrl.text.trim(), _mdpCtrl.text, ); // Vérifie que ce compte est bien autorisé (staff). if (!estStaff) { pb.authStore.clear(); if (mounted) { setState(() => _erreur = 'Ce compte n\'est pas autorisé pour la tablette (staff).'); } } // Si staff : l'AuthGate bascule automatiquement vers l'app. } on ClientException catch (e) { if (mounted) { setState(() => _erreur = 'Identifiants incorrects'); } debugPrint('Login error: ${e.response}'); } catch (e) { if (mounted) setState(() => _erreur = 'Erreur : $e'); } finally { if (mounted) setState(() => _enCours = false); } } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Center( child: Container( padding: const EdgeInsets.all(18), decoration: BoxDecoration( color: AppTheme.accent.withValues(alpha: 0.12), shape: BoxShape.circle, ), child: const Icon(Icons.storefront, size: 40, color: AppTheme.accent), ), ), const SizedBox(height: 20), const Text('Espace magasin', textAlign: TextAlign.center, style: TextStyle( fontSize: 24, fontWeight: FontWeight.w800)), const SizedBox(height: 6), const Text('Connexion du personnel', textAlign: TextAlign.center, style: TextStyle(color: AppTheme.grisTexte)), const SizedBox(height: 28), TextFormField( controller: _emailCtrl, keyboardType: TextInputType.emailAddress, autofillHints: const [AutofillHints.email], decoration: const InputDecoration( labelText: 'Email', prefixIcon: Icon(Icons.mail_outline), ), validator: (v) => (v == null || !v.contains('@')) ? 'Email invalide' : null, ), const SizedBox(height: 14), TextFormField( controller: _mdpCtrl, obscureText: !_voirMdp, decoration: InputDecoration( labelText: 'Mot de passe', prefixIcon: const Icon(Icons.lock_outline), suffixIcon: IconButton( icon: Icon(_voirMdp ? Icons.visibility_off : Icons.visibility), onPressed: () => setState(() => _voirMdp = !_voirMdp), ), ), validator: (v) => (v == null || v.isEmpty) ? 'Mot de passe requis' : null, onFieldSubmitted: (_) => _connexion(), ), if (_erreur != null) ...[ const SizedBox(height: 16), Text(_erreur!, textAlign: TextAlign.center, style: TextStyle(color: Colors.red.shade600)), ], const SizedBox(height: 24), FilledButton( onPressed: _enCours ? null : _connexion, child: _enCours ? const SizedBox( height: 22, width: 22, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white)) : const Text('Se connecter'), ), ], ), ), ), ), ), ), ); } }