import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../l10n/generated/app_localizations.dart'; import '../data/auth_repository.dart'; class LoginScreen extends ConsumerStatefulWidget { const LoginScreen({super.key}); @override ConsumerState createState() => _LoginScreenState(); } class _LoginScreenState extends ConsumerState { final _formKey = GlobalKey(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); bool _isSignUp = false; bool _busy = false; String? _errorText; @override void dispose() { _emailController.dispose(); _passwordController.dispose(); super.dispose(); } String _messageForCode(String code, AppLocalizations l10n) { return switch (code) { 'invalid-credential' || 'user-not-found' || 'wrong-password' => l10n.authErrorInvalidCredential, 'email-already-in-use' => l10n.authErrorEmailInUse, 'weak-password' => l10n.authErrorWeakPassword, 'invalid-email' => l10n.authErrorInvalidEmail, _ => l10n.authErrorGeneric, }; } Future _submit() async { final l10n = AppLocalizations.of(context); if (!_formKey.currentState!.validate()) return; setState(() { _busy = true; _errorText = null; }); try { final repo = ref.read(authRepositoryProvider); final email = _emailController.text.trim(); final password = _passwordController.text; if (_isSignUp) { await repo.signUp(email: email, password: password); } else { await repo.signIn(email: email, password: password); } // Weiterleitung übernimmt der Router (redirect bei Auth-Änderung). } on FirebaseAuthException catch (e) { setState(() => _errorText = _messageForCode(e.code, l10n)); } catch (_) { setState(() => _errorText = l10n.authErrorGeneric); } finally { if (mounted) setState(() => _busy = false); } } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context); final theme = Theme.of(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: [ Icon(Icons.eco, size: 64, color: theme.colorScheme.primary), const SizedBox(height: 12), Text( l10n.appTitle, style: theme.textTheme.headlineMedium, textAlign: TextAlign.center, ), const SizedBox(height: 4), Text( l10n.loginSubtitle, style: theme.textTheme.bodyLarge, textAlign: TextAlign.center, ), const SizedBox(height: 32), TextFormField( controller: _emailController, decoration: InputDecoration( labelText: l10n.emailLabel, border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.mail_outline), ), keyboardType: TextInputType.emailAddress, autocorrect: false, textInputAction: TextInputAction.next, validator: (value) => (value == null || value.trim().isEmpty) ? l10n.requiredField : null, ), const SizedBox(height: 16), TextFormField( controller: _passwordController, decoration: InputDecoration( labelText: l10n.passwordLabel, border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.lock_outline), ), obscureText: true, textInputAction: TextInputAction.done, onFieldSubmitted: (_) => _submit(), validator: (value) => (value == null || value.isEmpty) ? l10n.requiredField : null, ), if (_errorText != null) ...[ const SizedBox(height: 16), Text( _errorText!, style: theme.textTheme.bodyMedium ?.copyWith(color: theme.colorScheme.error), textAlign: TextAlign.center, ), ], const SizedBox(height: 24), FilledButton( onPressed: _busy ? null : _submit, child: _busy ? const SizedBox( height: 22, width: 22, child: CircularProgressIndicator(strokeWidth: 2), ) : Text( _isSignUp ? l10n.signUpButton : l10n.signInButton), ), const SizedBox(height: 8), TextButton( onPressed: _busy ? null : () => setState(() { _isSignUp = !_isSignUp; _errorText = null; }), child: Text(_isSignUp ? l10n.switchToSignIn : l10n.switchToSignUp), ), ], ), ), ), ), ), ), ); } }