CPD-Gitty/trainerbox/lib/screens/login_screen.dart

217 lines
8.1 KiB
Dart

// login_screen.dart
// This file contains the LoginScreen widget, which handles user authentication (login and registration) and role selection.
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
/// The LoginScreen allows users to log in or register, and select their role (trainer or player).
class LoginScreen extends StatefulWidget {
final void Function() onLoginSuccess;
const LoginScreen({super.key, required this.onLoginSuccess});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
/// State for the LoginScreen, manages form state, authentication, and error handling.
class _LoginScreenState extends State<LoginScreen> {
final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _nameController = TextEditingController();
String? _error;
bool _loading = false;
bool _isLogin = true;
bool _isTrainer = false;
/// Handles login or registration when the form is submitted.
Future<void> _submit() async {
setState(() { _loading = true; _error = null; });
try {
if (_isLogin) {
// Login
try {
UserCredential cred = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
// Check if user profile exists in Firestore
final uid = cred.user!.uid;
final userDoc = await FirebaseFirestore.instance.collection('User').doc(uid).get();
if (userDoc.exists) {
widget.onLoginSuccess();
} else {
setState(() { _error = 'Kein Benutzerprofil in der Datenbank gefunden!'; });
await FirebaseAuth.instance.signOut();
}
} catch (e) {
rethrow;
}
} else {
// Registration - Direct attempt to create user
try {
UserCredential cred = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
// Create user document in Firestore
final uid = cred.user!.uid;
await FirebaseFirestore.instance.collection('User').doc(uid).set({
'email': _emailController.text.trim(),
'name': _nameController.text.trim(),
'role': _isTrainer ? 'trainer' : 'player',
'createdAt': FieldValue.serverTimestamp(),
'favorites': [],
'trainings': {},
'cancelledTrainings': [],
'trainingTimes': {},
'trainingDurations': {},
});
widget.onLoginSuccess();
} catch (e) {
rethrow;
}
}
} on FirebaseAuthException catch (e) {
// Handle Firebase authentication errors
String errorMessage;
switch (e.code) {
case 'user-not-found':
errorMessage = 'Kein Benutzer mit dieser E-Mail-Adresse gefunden.';
break;
case 'wrong-password':
errorMessage = 'Falsches Passwort.';
break;
case 'invalid-email':
errorMessage = 'Ungültige E-Mail-Adresse.';
break;
case 'user-disabled':
errorMessage = 'Dieses Konto wurde deaktiviert.';
break;
case 'email-already-in-use':
errorMessage = 'Diese E-Mail-Adresse wird bereits verwendet. Bitte melde dich an oder verwende eine andere E-Mail-Adresse.';
break;
case 'weak-password':
errorMessage = 'Das Passwort ist zu schwach.';
break;
case 'operation-not-allowed':
errorMessage = 'Diese Aktion ist nicht erlaubt.';
break;
default:
errorMessage = 'Ein Fehler ist aufgetreten: ${e.message}';
}
setState(() { _error = errorMessage; });
} catch (e) {
setState(() { _error = 'Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es später erneut.'; });
} finally {
setState(() { _loading = false; });
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Title
Text(_isLogin ? 'Anmeldung' : 'Registrieren', style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 32),
if (!_isLogin) ...[
// Name field for registration
TextFormField(
controller: _nameController,
decoration: const InputDecoration(labelText: 'Name'),
validator: (v) => v != null && v.trim().isNotEmpty ? null : 'Bitte gib deinen Namen ein',
),
const SizedBox(height: 16),
// Role selection
Row(
children: [
Checkbox(
value: _isTrainer,
onChanged: (v) {
setState(() { _isTrainer = v ?? false; });
},
),
const Text('Ich bin Trainer'),
const SizedBox(width: 16),
Checkbox(
value: !_isTrainer,
onChanged: (v) {
setState(() { _isTrainer = !(v ?? false); });
},
),
const Text('Ich bin Spieler'),
],
),
const SizedBox(height: 16),
],
// Email field
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
validator: (v) => v != null && v.contains('@') ? null : 'Bitte gib eine gültige E-Mail ein',
),
const SizedBox(height: 16),
// Password field
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(labelText: 'Passwort'),
obscureText: true,
validator: (v) => v != null && v.length >= 6 ? null : 'Mindestens 6 Zeichen',
),
const SizedBox(height: 24),
if (_error != null) ...[
// Error message
Text(_error!, style: const TextStyle(color: Colors.red)),
const SizedBox(height: 12),
],
// Submit button
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _loading
? null
: () {
if (_formKey.currentState!.validate()) {
_submit();
}
},
child: _loading
? const CircularProgressIndicator()
: Text(_isLogin ? 'Anmelden' : 'Registrieren'),
),
),
const SizedBox(height: 16),
// Switch between login and registration
TextButton(
onPressed: _loading
? null
: () {
setState(() {
_isLogin = !_isLogin;
_error = null;
});
},
child: Text(_isLogin ? 'Noch kein Konto? Jetzt registrieren!' : 'Schon registriert? Jetzt anmelden!'),
),
],
),
),
),
),
);
}
}