Merge Firebase_aut branch and resolve pubspec.lock conflict
This commit is contained in:
+153
-124
@@ -1,19 +1,19 @@
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_storage/firebase_storage.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:image/image.dart' as img;
|
||||
|
||||
|
||||
class AddScreen extends StatefulWidget {
|
||||
final int initialIndex;
|
||||
|
||||
const AddScreen({super.key, required this.initialIndex});
|
||||
const AddScreen({Key? key, required this.initialIndex}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AddScreenState createState() => _AddScreenState();
|
||||
|
||||
}
|
||||
|
||||
class _AddScreenState extends State<AddScreen> {
|
||||
@@ -24,7 +24,6 @@ class _AddScreenState extends State<AddScreen> {
|
||||
bool _uploading = false;
|
||||
int _selectedIndex = 0;
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -42,14 +41,13 @@ class _AddScreenState extends State<AddScreen> {
|
||||
|
||||
if (originalImage != null) {
|
||||
int originSize = min(originalImage.width, originalImage.height);
|
||||
final croppedImage = img.copyCrop(
|
||||
originalImage,
|
||||
x: (originalImage.width - originSize)~/2,
|
||||
y: (originalImage.height - originSize)~/2,
|
||||
final croppedImage = img.copyCrop(originalImage,
|
||||
x: (originalImage.width - originSize) ~/ 2,
|
||||
y: (originalImage.height - originSize) ~/ 2,
|
||||
width: originSize,
|
||||
height: originSize
|
||||
);
|
||||
final newPath = imageFile.path.substring(0, imageFile.path.lastIndexOf('/'));
|
||||
height: originSize);
|
||||
final newPath =
|
||||
imageFile.path.substring(0, imageFile.path.lastIndexOf('/'));
|
||||
final newFile = File('$newPath/cropped.jpg');
|
||||
await newFile.writeAsBytes(img.encodePng(croppedImage));
|
||||
return newFile;
|
||||
@@ -71,33 +69,37 @@ class _AddScreenState extends State<AddScreen> {
|
||||
if (originalImage != null) {
|
||||
if (originalImage.width == originalImage.height) {
|
||||
// Wenn das Bild bereits im 1:1-Format ist, überspringen Sie das Zuschneiden
|
||||
setState(() {
|
||||
_imageFile = tempFile;
|
||||
print("1:1");
|
||||
});
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_imageFile = tempFile;
|
||||
print("1:1");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Wenn das Bild nicht im 1:1-Format ist, schneiden Sie es zu
|
||||
File croppedFile = await _cropImage(tempFile);
|
||||
setState(() {
|
||||
_imageFile = croppedFile;
|
||||
});
|
||||
print("decode");
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_imageFile = croppedFile;
|
||||
});
|
||||
print("decode");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw Exception('Unable to decode image file.');
|
||||
}
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Die Dateigröße darf maximal 10 MB betragen.')),
|
||||
const SnackBar(
|
||||
content: Text('Die Dateigröße darf maximal 10 MB betragen.')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future<void> addNewElementToFirestore(String title, String description, File imageFile, {required Function(bool) onComplete}) async {
|
||||
Future<void> addNewElementToFirestore(
|
||||
String title, String description, File imageFile,
|
||||
{required Function(bool) onComplete}) async {
|
||||
String collectionName;
|
||||
if (_selectedIndex == 0) {
|
||||
collectionName = "CitizensForum";
|
||||
@@ -107,36 +109,45 @@ class _AddScreenState extends State<AddScreen> {
|
||||
collectionName = "Issues";
|
||||
}
|
||||
|
||||
String imageUrl = await uploadImageToFirebaseStorage(imageFile, collectionName);
|
||||
try
|
||||
{
|
||||
String imageUrl =
|
||||
await uploadImageToFirebaseStorage(imageFile, collectionName);
|
||||
String? userId = FirebaseAuth.instance.currentUser?.uid; // get the user ID
|
||||
|
||||
try {
|
||||
await FirebaseFirestore.instance.collection(collectionName).add({
|
||||
"title": title,
|
||||
"description": description,
|
||||
"imageUrl": imageUrl,
|
||||
"createdDate": DateTime.now(),
|
||||
"author_uid": userId, // add the user ID to the document
|
||||
});
|
||||
onComplete(true);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
} catch (e) {
|
||||
onComplete(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<String> uploadImageToFirebaseStorage(File imageFile, String collectionName) async {
|
||||
Reference ref = FirebaseStorage.instance.ref().child("$collectionName/${DateTime.now().toString()}");
|
||||
UploadTask uploadTask = ref.putFile(imageFile);
|
||||
return await (await uploadTask).ref.getDownloadURL();
|
||||
Future<String> uploadImageToFirebaseStorage(
|
||||
File imageFile, String collectionName) async {
|
||||
String? userId = FirebaseAuth.instance.currentUser?.uid;
|
||||
if (userId != null) {
|
||||
Reference ref = FirebaseStorage.instance
|
||||
.ref()
|
||||
.child("$collectionName/$userId/${DateTime.now().toString()}");
|
||||
UploadTask uploadTask = ref.putFile(imageFile);
|
||||
return await (await uploadTask).ref.getDownloadURL();
|
||||
} else {
|
||||
throw Exception('Cannot upload without user ID');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String appBarTitle = '';
|
||||
|
||||
double keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
|
||||
|
||||
if (_selectedIndex == 0) {
|
||||
appBarTitle = 'Neue BürgerForum Information';
|
||||
} else if (_selectedIndex == 1) {
|
||||
@@ -166,20 +177,30 @@ class _AddScreenState extends State<AddScreen> {
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.check),
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate() && _imageFile != null && !_uploading) {
|
||||
if (_formKey.currentState!.validate() &&
|
||||
_imageFile != null &&
|
||||
!_uploading) {
|
||||
setState(() {
|
||||
_uploading = true;
|
||||
});
|
||||
Navigator.pop(context); // Fenster direkt schließen, nachdem der Upload-Button gedrückt wurde.
|
||||
await addNewElementToFirestore(_titleController.text, _descriptionController.text, _imageFile!, onComplete: (bool success) {
|
||||
setState(() {
|
||||
_uploading = false;
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(success ? 'Upload erfolgreich.' : 'Upload fehlgeschlagen.'),
|
||||
),
|
||||
);
|
||||
Navigator.pop(
|
||||
context); // Fenster direkt schließen, nachdem der Upload-Button gedrückt wurde.
|
||||
await addNewElementToFirestore(
|
||||
_titleController.text,
|
||||
_descriptionController.text,
|
||||
_imageFile!, onComplete: (bool success) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_uploading = false;
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(success
|
||||
? 'Upload erfolgreich.'
|
||||
: 'Upload fehlgeschlagen.'),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -230,96 +251,104 @@ class _AddScreenState extends State<AddScreen> {
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
_imageFile != null
|
||||
? Image.file(_imageFile!)
|
||||
? Expanded(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
double imageHeight =
|
||||
max(0, constraints.maxHeight - keyboardHeight);
|
||||
return Container(
|
||||
height: imageHeight,
|
||||
child: Image.file(_imageFile!),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
: Container(
|
||||
height: 200.0,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[200],
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
),
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
height: 60,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Bild hinzufügen',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 200.0,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[200],
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
),
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
height: 60,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Bild hinzufügen',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () {
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
height: 80,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.photo_library,
|
||||
size: 40),
|
||||
title: const Text(
|
||||
'Galerie auswählen',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
_getImage(ImageSource.gallery);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
height: 80,
|
||||
child: ListTile(
|
||||
leading: const Icon(
|
||||
Icons.photo_library, size: 40),
|
||||
title: const Text(
|
||||
'Galerie auswählen',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
_getImage(ImageSource.gallery);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
height: 80,
|
||||
child: ListTile(
|
||||
leading: const Icon(
|
||||
Icons.camera_alt, size: 40),
|
||||
title: const Text(
|
||||
'Kamera verwenden',
|
||||
style: TextStyle(fontSize: 20),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
height: 80,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.camera_alt,
|
||||
size: 40),
|
||||
title: const Text(
|
||||
'Kamera verwenden',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
_getImage(ImageSource.camera);
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
_getImage(ImageSource.camera);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'Bild hinzufügen',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'Bild hinzufügen',
|
||||
style: TextStyle(
|
||||
color: Theme
|
||||
.of(context)
|
||||
.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
+6
-1
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:oggauergemeindetrommler/register.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
LoginPage({Key? key}) : super(key: key);
|
||||
@@ -79,6 +80,11 @@ class _LoginPageState extends State<LoginPage> {
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// Navigiere zur Registrierungsseite
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const RegisterPage()),
|
||||
);
|
||||
},
|
||||
child: const Text('Registrieren'),
|
||||
),
|
||||
@@ -92,4 +98,3 @@ class _LoginPageState extends State<LoginPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+77
-27
@@ -1,9 +1,11 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_storage/firebase_storage.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:printing/printing.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'AddPage.dart';
|
||||
import 'DetailPage.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
@@ -11,6 +13,8 @@ import 'package:pdf/widgets.dart' as pdfWidgets;
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:image/image.dart' as img;
|
||||
|
||||
import 'anonym_aut.dart';
|
||||
|
||||
class UserDefinedItem extends StatelessWidget {
|
||||
final String title;
|
||||
final String datum;
|
||||
@@ -208,23 +212,59 @@ class _GenericListState extends State<GenericList> {
|
||||
final DateTime createdDate = data['createdDate'].toDate();
|
||||
final formattedDate =
|
||||
DateFormat('dd.MM.yyyy').format(createdDate);
|
||||
return Dismissible(
|
||||
key: UniqueKey(),
|
||||
direction: DismissDirection.endToStart,
|
||||
onDismissed: (direction) {
|
||||
_deleteDocument(documentId, data['imageUrl']);
|
||||
},
|
||||
background: Container(
|
||||
color: Colors.red,
|
||||
child: const Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.delete, color: Colors.white),
|
||||
final currentUser = FirebaseAuth.instance.currentUser;
|
||||
|
||||
if (currentUser != null && data['author_uid'] == currentUser.uid) {
|
||||
return Dismissible(
|
||||
key: UniqueKey(),
|
||||
direction: DismissDirection.endToStart,
|
||||
onDismissed: (direction) {
|
||||
_deleteDocument(documentId, data['imageUrl']);
|
||||
},
|
||||
background: Container(
|
||||
color: Colors.red,
|
||||
child: const Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.delete, color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: UserDefinedItem(
|
||||
child: UserDefinedItem(
|
||||
title: data['title'] ?? '',
|
||||
datum: formattedDate,
|
||||
description: data['description'] ?? '',
|
||||
imageUrl: data['imageUrl'] ?? '',
|
||||
isSelected: selectedItems.containsKey(documentId),
|
||||
onTap: () {
|
||||
clearSelectedItems();
|
||||
// Open a new screen when the user taps on the list item
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => DetailPage(
|
||||
title: data['title'],
|
||||
datum: formattedDate,
|
||||
description: data['description'],
|
||||
imageUrl: data['imageUrl'],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
onLongPress: () {
|
||||
setState(() {
|
||||
if (selectedItems.containsKey(documentId)) {
|
||||
selectedItems.remove(documentId);
|
||||
} else {
|
||||
selectedItems[documentId] = data;
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return UserDefinedItem(
|
||||
title: data['title'] ?? '',
|
||||
datum: formattedDate,
|
||||
description: data['description'] ?? '',
|
||||
@@ -254,8 +294,9 @@ class _GenericListState extends State<GenericList> {
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -295,17 +336,26 @@ class _GenericListState extends State<GenericList> {
|
||||
],
|
||||
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
clearSelectedItems();
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => AddScreen(initialIndex: widget.selectedIndex)),
|
||||
);
|
||||
floatingActionButton: Consumer<AuthState>(
|
||||
builder: (context, authState, child) {
|
||||
if (authState.user != null) {
|
||||
return FloatingActionButton(
|
||||
onPressed: () {
|
||||
clearSelectedItems();
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => AddScreen(initialIndex: widget.selectedIndex)),
|
||||
);
|
||||
},
|
||||
tooltip: "Neues Element hinzufügen",
|
||||
child: const Icon(Icons.add),
|
||||
);
|
||||
} else {
|
||||
return Container(); // Return an empty container when the user is not signed in
|
||||
}
|
||||
},
|
||||
tooltip: "Neues Element hinzufügen",
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
@@ -318,7 +368,7 @@ class _GenericListState extends State<GenericList> {
|
||||
final Uint8List bytes = response.bodyBytes;
|
||||
|
||||
final img.Image? image = img.decodeImage(bytes);
|
||||
final img.Image resizedImage = img.copyResize(image!, width: 500); // Beispielwert für die Breite
|
||||
final img.Image resizedImage = img.copyResize(image!, width: 290); // Beispielwert für die Breite
|
||||
final Uint8List resizedBytes = Uint8List.fromList(img.encodeJpg(resizedImage));
|
||||
|
||||
final imageProvider = pdfWidgets.MemoryImage(resizedBytes);
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AuthState extends ChangeNotifier {
|
||||
FirebaseAuth auth = FirebaseAuth.instance;
|
||||
User? _user;
|
||||
|
||||
User? get user => _user;
|
||||
|
||||
AuthState() {
|
||||
auth.authStateChanges().listen((User? user) {
|
||||
if (user == null) {
|
||||
print('User is currently signed out!');
|
||||
_user = null;
|
||||
} else {
|
||||
print('User is signed in!');
|
||||
_user = user;
|
||||
}
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> signInAnonymously() async {
|
||||
try {
|
||||
await auth.signInAnonymously();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> signOut() async {
|
||||
await auth.signOut();
|
||||
}
|
||||
}
|
||||
|
||||
class AnonymAuthScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Consumer<AuthState>(
|
||||
builder: (context, authState, child) {
|
||||
return ElevatedButton(
|
||||
onPressed: authState.user == null
|
||||
? authState.signInAnonymously
|
||||
: authState.signOut,
|
||||
child: Text(authState.user == null ? 'Anonym anmelden' : 'Abmelden'),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:oggauergemeindetrommler/LoginPage.dart';
|
||||
import 'UserDefinedList.dart';
|
||||
import 'anonym_aut.dart';
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({Key? key, required this.title});
|
||||
@@ -23,7 +24,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
const GenericList(collectionName: 'CitizensForum', selectedIndex: 0,),
|
||||
const GenericList(collectionName: 'News', selectedIndex: 1,),
|
||||
const GenericList(collectionName: 'Issues', selectedIndex: 2,),
|
||||
LoginPage()
|
||||
AnonymAuthScreen()
|
||||
];
|
||||
|
||||
return Scaffold(
|
||||
|
||||
+9
-2
@@ -1,4 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'anonym_aut.dart';
|
||||
import 'home.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'firebase_options.dart';
|
||||
@@ -8,10 +10,15 @@ void main() async {
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptions.currentPlatform,
|
||||
);
|
||||
runApp(const MyApp());
|
||||
|
||||
runApp(
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => AuthState(),
|
||||
child: const MyApp(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RegisterPage extends StatefulWidget {
|
||||
const RegisterPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_RegisterPageState createState() => _RegisterPageState();
|
||||
}
|
||||
|
||||
class _RegisterPageState extends State<RegisterPage> {
|
||||
final _emailController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
final _confirmPasswordController = TextEditingController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_emailController.dispose();
|
||||
_passwordController.dispose();
|
||||
_confirmPasswordController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool isValidEmail(String email) {
|
||||
// Die gleiche Validierung wie in Ihrer LoginPage
|
||||
return RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$').hasMatch(email);
|
||||
}
|
||||
|
||||
bool arePasswordsMatching(String password, String confirmPassword) {
|
||||
return password == confirmPassword;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: _emailController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'E-Mail',
|
||||
),
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Bitte geben Sie eine E-Mail-Adresse ein.';
|
||||
} else if (!isValidEmail(value)) {
|
||||
return 'Bitte geben Sie eine gültige E-Mail-Adresse ein.';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Passwort',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: _confirmPasswordController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Passwort bestätigen',
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
String email = _emailController.text;
|
||||
String password = _passwordController.text;
|
||||
String confirmPassword = _confirmPasswordController.text;
|
||||
if (isValidEmail(email) && arePasswordsMatching(password, confirmPassword)) {
|
||||
// E-Mail und Passwörter sind gültig, führe die entsprechende Aktion aus
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Ungültige Eingaben'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text('Registrieren'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@ dependencies:
|
||||
printing: ^5.10.4
|
||||
image_cropper: ^8.0.1
|
||||
logging: ^1.1.1
|
||||
provider: ^6.0.5
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
Reference in New Issue
Block a user