Regestrierung erweiter
parent
ecd362928d
commit
1a96eb25fe
|
|
@ -14,9 +14,11 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
final _emailController = TextEditingController();
|
final _emailController = TextEditingController();
|
||||||
final _passwordController = TextEditingController();
|
final _passwordController = TextEditingController();
|
||||||
|
final _nameController = TextEditingController();
|
||||||
String? _error;
|
String? _error;
|
||||||
bool _loading = false;
|
bool _loading = false;
|
||||||
bool _isLogin = true;
|
bool _isLogin = true;
|
||||||
|
bool _isTrainer = false;
|
||||||
|
|
||||||
Future<void> _submit() async {
|
Future<void> _submit() async {
|
||||||
setState(() { _loading = true; _error = null; });
|
setState(() { _loading = true; _error = null; });
|
||||||
|
|
@ -46,6 +48,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
final uid = cred.user!.uid;
|
final uid = cred.user!.uid;
|
||||||
await FirebaseFirestore.instance.collection('User').doc(uid).set({
|
await FirebaseFirestore.instance.collection('User').doc(uid).set({
|
||||||
'email': _emailController.text.trim(),
|
'email': _emailController.text.trim(),
|
||||||
|
'name': _nameController.text.trim(),
|
||||||
|
'role': _isTrainer ? 'trainer' : 'player',
|
||||||
'createdAt': FieldValue.serverTimestamp(),
|
'createdAt': FieldValue.serverTimestamp(),
|
||||||
});
|
});
|
||||||
widget.onLoginSuccess();
|
widget.onLoginSuccess();
|
||||||
|
|
@ -72,6 +76,34 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
children: [
|
children: [
|
||||||
Text(_isLogin ? 'Login' : 'Registrieren', style: Theme.of(context).textTheme.headlineMedium),
|
Text(_isLogin ? 'Login' : 'Registrieren', style: Theme.of(context).textTheme.headlineMedium),
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
|
if (!_isLogin) ...[
|
||||||
|
TextFormField(
|
||||||
|
controller: _nameController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Name'),
|
||||||
|
validator: (v) => v != null && v.trim().isNotEmpty ? null : 'Name angeben',
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
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),
|
||||||
|
],
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _emailController,
|
controller: _emailController,
|
||||||
decoration: const InputDecoration(labelText: 'E-Mail'),
|
decoration: const InputDecoration(labelText: 'E-Mail'),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
|
||||||
class ProfileTab extends StatelessWidget {
|
class ProfileTab extends StatelessWidget {
|
||||||
final VoidCallback? onLogoutSuccess;
|
final VoidCallback? onLogoutSuccess;
|
||||||
|
|
@ -16,125 +17,151 @@ class ProfileTab extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final user = FirebaseAuth.instance.currentUser;
|
final user = FirebaseAuth.instance.currentUser;
|
||||||
final email = user?.email ?? 'Keine E-Mail gefunden';
|
final email = user?.email ?? 'Keine E-Mail gefunden';
|
||||||
// Beispiel-Benutzerdaten (kannst du später dynamisch machen)
|
final uid = user?.uid;
|
||||||
final Map<String, dynamic> userData = {
|
|
||||||
'name': 'Max Mustermann',
|
|
||||||
'level': 'Fortgeschritten',
|
|
||||||
'joinedDate': '01.01.2024',
|
|
||||||
'workoutsCompleted': 42,
|
|
||||||
'totalMinutes': 1260,
|
|
||||||
};
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: CustomScrollView(
|
body: uid == null
|
||||||
slivers: [
|
? const Center(child: Text('Nicht eingeloggt'))
|
||||||
SliverAppBar(
|
: FutureBuilder<DocumentSnapshot>(
|
||||||
expandedHeight: 200,
|
future: FirebaseFirestore.instance.collection('User').doc(uid).get(),
|
||||||
pinned: true,
|
builder: (context, snapshot) {
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
title: Text(userData['name']),
|
return const Center(child: CircularProgressIndicator());
|
||||||
background: Container(
|
}
|
||||||
decoration: BoxDecoration(
|
if (!snapshot.hasData || !snapshot.data!.exists) {
|
||||||
gradient: LinearGradient(
|
return const Center(child: Text('Keine Profildaten gefunden'));
|
||||||
begin: Alignment.topCenter,
|
}
|
||||||
end: Alignment.bottomCenter,
|
final data = snapshot.data!.data() as Map<String, dynamic>;
|
||||||
colors: [Colors.blue[700]!, Colors.blue[500]!],
|
final name = data['name'] ?? 'Unbekannt';
|
||||||
),
|
final role = data['role'] == 'trainer' ? 'Trainer' : 'Spieler';
|
||||||
),
|
final createdAt = (data['createdAt'] is Timestamp)
|
||||||
child: const Center(
|
? (data['createdAt'] as Timestamp).toDate()
|
||||||
child: Icon(Icons.person, size: 80, color: Colors.white),
|
: null;
|
||||||
),
|
final createdAtStr = createdAt != null
|
||||||
),
|
? '${createdAt.day.toString().padLeft(2, '0')}.${createdAt.month.toString().padLeft(2, '0')}.${createdAt.year}'
|
||||||
),
|
: 'Unbekannt';
|
||||||
),
|
// Beispiel-Benutzerdaten (Statistiken als Demo)
|
||||||
SliverToBoxAdapter(
|
final Map<String, dynamic> userData = {
|
||||||
child: Padding(
|
'name': name,
|
||||||
padding: const EdgeInsets.all(16.0),
|
'level': role,
|
||||||
child: Column(
|
'joinedDate': createdAtStr,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
'workoutsCompleted': 42,
|
||||||
children: [
|
'totalMinutes': 1260,
|
||||||
_buildInfoCard(
|
};
|
||||||
title: 'Statistiken',
|
|
||||||
child: Column(
|
return CustomScrollView(
|
||||||
children: [
|
slivers: [
|
||||||
_buildStatisticRow(
|
SliverAppBar(
|
||||||
'Trainings absolviert',
|
expandedHeight: 200,
|
||||||
userData['workoutsCompleted'].toString(),
|
pinned: true,
|
||||||
Icons.fitness_center,
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
),
|
title: Text(userData['name']),
|
||||||
const Divider(),
|
background: Container(
|
||||||
_buildStatisticRow(
|
decoration: BoxDecoration(
|
||||||
'Gesamtzeit',
|
gradient: LinearGradient(
|
||||||
'${userData['totalMinutes']} Minuten',
|
begin: Alignment.topCenter,
|
||||||
Icons.timer,
|
end: Alignment.bottomCenter,
|
||||||
),
|
colors: [Colors.blue[700]!, Colors.blue[500]!],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
child: const Center(
|
||||||
const SizedBox(height: 16),
|
child: Icon(Icons.person, size: 80, color: Colors.white),
|
||||||
_buildInfoCard(
|
|
||||||
title: 'Persönliche Informationen',
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
_buildInfoRow('E-Mail', email, Icons.email),
|
|
||||||
const Divider(),
|
|
||||||
_buildInfoRow('Level', userData['level'], Icons.star),
|
|
||||||
const Divider(),
|
|
||||||
_buildInfoRow(
|
|
||||||
'Mitglied seit',
|
|
||||||
userData['joinedDate'],
|
|
||||||
Icons.calendar_today,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
_buildInfoCard(
|
|
||||||
title: 'Einstellungen',
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
ListTile(
|
|
||||||
leading: const Icon(Icons.notifications),
|
|
||||||
title: const Text('Benachrichtigungen'),
|
|
||||||
trailing: Switch(
|
|
||||||
value: true,
|
|
||||||
onChanged: (value) {},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(),
|
),
|
||||||
ListTile(
|
|
||||||
leading: const Icon(Icons.dark_mode),
|
|
||||||
title: const Text('Dark Mode'),
|
|
||||||
trailing: Switch(
|
|
||||||
value: false,
|
|
||||||
onChanged: (value) {},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(),
|
|
||||||
ListTile(
|
|
||||||
leading: const Icon(Icons.language),
|
|
||||||
title: const Text('Sprache'),
|
|
||||||
trailing: const Text('Deutsch'),
|
|
||||||
onTap: () {},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
SliverToBoxAdapter(
|
||||||
const SizedBox(height: 16),
|
child: Padding(
|
||||||
Center(
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: TextButton.icon(
|
child: Column(
|
||||||
onPressed: () => _logout(context),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
icon: const Icon(Icons.logout),
|
children: [
|
||||||
label: const Text('Abmelden'),
|
_buildInfoCard(
|
||||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
title: 'Statistiken',
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildStatisticRow(
|
||||||
|
'Trainings absolviert',
|
||||||
|
userData['workoutsCompleted'].toString(),
|
||||||
|
Icons.fitness_center,
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
_buildStatisticRow(
|
||||||
|
'Gesamtzeit',
|
||||||
|
'${userData['totalMinutes']} Minuten',
|
||||||
|
Icons.timer,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_buildInfoCard(
|
||||||
|
title: 'Persönliche Informationen',
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildInfoRow('E-Mail', email, Icons.email),
|
||||||
|
const Divider(),
|
||||||
|
_buildInfoRow('Name', name, Icons.person),
|
||||||
|
const Divider(),
|
||||||
|
_buildInfoRow('Rolle', role, Icons.badge),
|
||||||
|
const Divider(),
|
||||||
|
_buildInfoRow(
|
||||||
|
'Mitglied seit',
|
||||||
|
userData['joinedDate'],
|
||||||
|
Icons.calendar_today,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_buildInfoCard(
|
||||||
|
title: 'Einstellungen',
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.notifications),
|
||||||
|
title: const Text('Benachrichtigungen'),
|
||||||
|
trailing: Switch(
|
||||||
|
value: true,
|
||||||
|
onChanged: (value) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.dark_mode),
|
||||||
|
title: const Text('Dark Mode'),
|
||||||
|
trailing: Switch(
|
||||||
|
value: false,
|
||||||
|
onChanged: (value) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.language),
|
||||||
|
title: const Text('Sprache'),
|
||||||
|
trailing: const Text('Deutsch'),
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Center(
|
||||||
|
child: TextButton.icon(
|
||||||
|
onPressed: () => _logout(context),
|
||||||
|
icon: const Icon(Icons.logout),
|
||||||
|
label: const Text('Abmelden'),
|
||||||
|
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
);
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue