first commit
This commit is contained in:
7
lib/config/environment.dart
Normal file
7
lib/config/environment.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
class Environment {
|
||||
static const String appwritePublicEndpoint = 'https://appwrite.joshihomeserver.ipv64.net/v1';
|
||||
static const String appwriteProjectId = '6894f2b0001f127bab72';
|
||||
static const String appwriteProjectName = 'Flutter Projects';
|
||||
static const String appwriteRealtimeCollectionId = '68a22f520035a95d6666';
|
||||
static const String appwriteDatabaseId = '68a22ef90021b90f0f43';
|
||||
}
|
||||
85
lib/controller/home_controller.dart
Normal file
85
lib/controller/home_controller.dart
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../models/tank_model.dart';
|
||||
import '../services/appwrite_service.dart';
|
||||
|
||||
class HomeController extends GetxController {
|
||||
final isLoading = false.obs;
|
||||
final listTankModel = <TankModel>[].obs;
|
||||
final appwriteService = AppwriteService();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
_loadListDocument();
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {}
|
||||
|
||||
@override
|
||||
void onClose() {}
|
||||
|
||||
Future<void> _loadListDocument() async {
|
||||
isLoading.value = true;
|
||||
if(listTankModel.isNotEmpty){
|
||||
listTankModel.clear();
|
||||
}
|
||||
var dateYear = DateTime.now().year;
|
||||
var userId = await appwriteService.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
//User nicht eingeloggt, evtl. zur Login-Seite navigieren
|
||||
update();
|
||||
return;
|
||||
}
|
||||
var resultList = await appwriteService.getDocumentsFromCollection(userId);
|
||||
if (resultList.isEmpty) {
|
||||
//Dokumente erfolgreich geladen, hier können Sie die Liste verarbeiten
|
||||
print('Dokumente wurden nicht geladen: ${resultList.length}');
|
||||
} else {
|
||||
for (var doc in resultList) {
|
||||
var tankModel = TankModel.fromMap(doc.data);
|
||||
listTankModel.add(tankModel);
|
||||
}
|
||||
if (listTankModel.isNotEmpty) {
|
||||
var sortList = listTankModel.where((tank) {
|
||||
var year = (DateTime.tryParse(tank.szDate)!).year;
|
||||
return year == dateYear;
|
||||
}).toList();
|
||||
listTankModel.clear();
|
||||
listTankModel.addAll(sortList);
|
||||
listTankModel.sort((a, b) {
|
||||
var dateA = DateTime.tryParse(a.szDate)!;
|
||||
var dateB = DateTime.tryParse(b.szDate)!;
|
||||
return dateB.compareTo(dateA);
|
||||
});
|
||||
for (var tank in listTankModel) {
|
||||
print(
|
||||
'SortTankModel: ${tank.szDate} - ${tank.szLiters}L - ${tank.szPricePerLiter}€/L - Total: ${tank.szPriceTotal}€',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
isLoading.value = false;
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
var logoutSuccess = await appwriteService.logout();
|
||||
if (logoutSuccess) {
|
||||
Get.snackbar(
|
||||
'Logout erfolgreich',
|
||||
'Sie wurden abgemeldet.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
Get.offAllNamed('/login-page');
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Logout fehlgeschlagen',
|
||||
'Bitte versuchen Sie es erneut.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
lib/controller/login_controller.dart
Normal file
46
lib/controller/login_controller.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../pages/home_view.dart';
|
||||
import '../pages/signin_view.dart';
|
||||
import '../services/appwrite_service.dart';
|
||||
|
||||
class LoginController extends GetxController {
|
||||
final emailController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
final appwriteService = AppwriteService();
|
||||
|
||||
@override
|
||||
void onReady() {}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
emailController.dispose();
|
||||
passwordController.dispose();
|
||||
}
|
||||
|
||||
void login() async {
|
||||
var email = emailController.text;
|
||||
var password = passwordController.text;
|
||||
// Hier können Sie die Login-Logik implementieren
|
||||
print('Login mit E-Mail: $email, Passwort: $password');
|
||||
var loginSuccess = await appwriteService.login(email, password);
|
||||
if (loginSuccess) {
|
||||
Get.snackbar(
|
||||
'Login erfolgreich',
|
||||
'Willkommen zurück!',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
Get.offAndToNamed(HomePage.namedRoute);
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Login fehlgeschlagen',
|
||||
'Bitte überprüfen Sie Ihre E-Mail und Ihr Passwort und versuchen Sie es erneut.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void goToSignInPage() {
|
||||
Get.offAndToNamed(SigninPage.namedRoute);
|
||||
}
|
||||
}
|
||||
87
lib/controller/signin_controller.dart
Normal file
87
lib/controller/signin_controller.dart
Normal file
@@ -0,0 +1,87 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../pages/home_view.dart';
|
||||
import '../pages/login_view.dart';
|
||||
import '../services/appwrite_service.dart';
|
||||
|
||||
class SigninController extends GetxController {
|
||||
final userNameController = TextEditingController();
|
||||
final emailController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
final appwriteService = AppwriteService();
|
||||
|
||||
@override
|
||||
void onReady() {}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
userNameController.dispose();
|
||||
emailController.dispose();
|
||||
passwordController.dispose();
|
||||
}
|
||||
|
||||
void register() async {
|
||||
//Eingaben überprüfen
|
||||
if (!_checkInputs()) return;
|
||||
//Registrierungslogik
|
||||
var userName = userNameController.text;
|
||||
var email = emailController.text;
|
||||
var password = passwordController.text;
|
||||
// Testausgabe
|
||||
print(
|
||||
'Registrieren mit Benutzername: $userName, E-Mail: $email, Passwort: $password',
|
||||
);
|
||||
//appwrite Registrierung und login Logik hier einfügen
|
||||
var registrationSuccess = await appwriteService.register(
|
||||
userName,
|
||||
email,
|
||||
password,
|
||||
);
|
||||
//Nach erfolgreicher Registrierung Meldung und zur Startseite navigieren
|
||||
if (registrationSuccess) {
|
||||
Get.snackbar(
|
||||
'Registrierung erfolgreich, sie werden weitergeleitet',
|
||||
'Willkommen, $userName!',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
Get.offAndToNamed(HomePage.namedRoute);
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Registrierung fehlgeschlagen',
|
||||
'Bitte überprüfen Sie Ihre Eingaben und versuchen Sie es erneut.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void goToLoginPage() {
|
||||
Get.offAndToNamed(LoginPage.namedRoute);
|
||||
}
|
||||
|
||||
bool _checkInputs() {
|
||||
var isOk = false;
|
||||
if (userNameController.text.isEmpty ||
|
||||
emailController.text.isEmpty ||
|
||||
passwordController.text.isEmpty) {
|
||||
Get.snackbar(
|
||||
'Fehler',
|
||||
'Bitte alle Felder ausfüllen',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
isOk = false;
|
||||
} else {
|
||||
isOk = true;
|
||||
}
|
||||
if (passwordController.text.length < 6) {
|
||||
Get.snackbar(
|
||||
'Fehler',
|
||||
'Passwort muss mindestens 6 Zeichen lang sein',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
isOk = false;
|
||||
} else {
|
||||
isOk = true;
|
||||
}
|
||||
return isOk;
|
||||
}
|
||||
}
|
||||
10
lib/helper/helper.dart
Normal file
10
lib/helper/helper.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
/// Retrieves the current date in the format "yyyy-MM-dd".
|
||||
///
|
||||
/// @return [String] A formatted date.
|
||||
String getCurrentDate(DateTime date) {
|
||||
return DateFormat("yyyy-MM-dd").format(date);
|
||||
}
|
||||
19
lib/helper/sample_bindings.dart
Normal file
19
lib/helper/sample_bindings.dart
Normal file
@@ -0,0 +1,19 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../controller/home_controller.dart';
|
||||
import '../controller/login_controller.dart';
|
||||
import '../controller/signin_controller.dart';
|
||||
|
||||
|
||||
|
||||
class SampleBindings extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
// Define your dependencies here no permanent Binding
|
||||
Get.lazyPut<LoginController>(() => LoginController());
|
||||
Get.lazyPut<SigninController>(() => SigninController());
|
||||
Get.lazyPut<HomeController>(() => HomeController());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
27
lib/helper/sample_routes.dart
Normal file
27
lib/helper/sample_routes.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'sample_bindings.dart';
|
||||
import '../pages/home_view.dart';
|
||||
import '../pages/signin_view.dart';
|
||||
import '../pages/login_view.dart';
|
||||
|
||||
class SampleRouts {
|
||||
static final sampleBindings = SampleBindings();
|
||||
static List<GetPage<dynamic>> samplePages = [
|
||||
GetPage(
|
||||
name: LoginPage.namedRoute,
|
||||
page: () => const LoginPage(),
|
||||
binding: sampleBindings,
|
||||
),
|
||||
GetPage(
|
||||
name: SigninPage.namedRoute,
|
||||
page: () => const SigninPage(),
|
||||
binding: sampleBindings,
|
||||
),
|
||||
GetPage(
|
||||
name: HomePage.namedRoute,
|
||||
page: () => const HomePage(),
|
||||
binding: sampleBindings,
|
||||
),
|
||||
|
||||
];
|
||||
}
|
||||
28
lib/main.dart
Normal file
28
lib/main.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'helper/sample_bindings.dart';
|
||||
import 'helper/sample_routes.dart';
|
||||
import 'pages/login_view.dart';
|
||||
|
||||
void main() {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetMaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(colorScheme: .fromSeed(seedColor: Colors.deepPurple)),
|
||||
initialBinding: SampleBindings(),
|
||||
initialRoute: LoginPage.namedRoute,
|
||||
getPages: SampleRouts.samplePages,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
82
lib/models/tank_model.dart
Normal file
82
lib/models/tank_model.dart
Normal file
@@ -0,0 +1,82 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class TankModel {
|
||||
final String szDocumentId;
|
||||
final String szUserId;
|
||||
final String szDate;
|
||||
final String szOdometer;
|
||||
final String szLiters;
|
||||
final String szPricePerLiter;
|
||||
final String szLocation;
|
||||
final String szPriceTotal;
|
||||
|
||||
TankModel({
|
||||
required this.szDocumentId,
|
||||
required this.szUserId,
|
||||
required this.szDate,
|
||||
required this.szOdometer,
|
||||
required this.szLiters,
|
||||
required this.szPricePerLiter,
|
||||
required this.szLocation,
|
||||
required this.szPriceTotal,
|
||||
});
|
||||
|
||||
TankModel copyWith({
|
||||
String? szDocumentId,
|
||||
String? szUserId,
|
||||
String? szDate,
|
||||
String? szOdometer,
|
||||
String? szLiters,
|
||||
String? szPricePerLiter,
|
||||
String? szLocation,
|
||||
String? szPriceTotal,
|
||||
}) {
|
||||
return TankModel(
|
||||
szDocumentId: szDocumentId ?? this.szDocumentId,
|
||||
szUserId: szUserId ?? this.szUserId,
|
||||
szDate: szDate ?? this.szDate,
|
||||
szOdometer: szOdometer ?? this.szOdometer,
|
||||
szLiters: szLiters ?? this.szLiters,
|
||||
szPricePerLiter: szPricePerLiter ?? this.szPricePerLiter,
|
||||
szLocation: szLocation ?? this.szLocation,
|
||||
szPriceTotal: szPriceTotal ?? this.szPriceTotal,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
final result = <String, dynamic>{};
|
||||
|
||||
result.addAll({'\$id': szDocumentId});
|
||||
result.addAll({'userId': szUserId});
|
||||
result.addAll({'date': szDate});
|
||||
result.addAll({'odometer': szOdometer});
|
||||
result.addAll({'liters': szLiters});
|
||||
result.addAll({'pricePerLiter': szPricePerLiter});
|
||||
result.addAll({'location': szLocation});
|
||||
result.addAll({'priceTotal': szPriceTotal});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
factory TankModel.fromMap(Map<String, dynamic> map) {
|
||||
return TankModel(
|
||||
szDocumentId: map['\$id'] ?? '',
|
||||
szUserId: map['userId'] ?? '',
|
||||
szDate: map['date'] ?? '',
|
||||
szOdometer: map['odometer'] ?? '',
|
||||
szLiters: map['liters'] ?? '',
|
||||
szPricePerLiter: map['pricePerLiter'] ?? '',
|
||||
szLocation: map['location'] ?? '',
|
||||
szPriceTotal: (double.parse(map['liters']?.toString() ?? '0') * double.parse(map['pricePerLiter']?.toString() ?? '0')).toStringAsFixed(2),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory TankModel.fromJson(String source) => TankModel.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TankModel(szDocumentId: $szDocumentId, szUserId: $szUserId, szDate: $szDate, szOdometer: $szOdometer, szLiters: $szLiters, szPricePerLiter: $szPricePerLiter, szLocation: $szLocation, szPriceTotal: $szPriceTotal)';
|
||||
}
|
||||
}
|
||||
56
lib/pages/home_view.dart
Normal file
56
lib/pages/home_view.dart
Normal file
@@ -0,0 +1,56 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../controller/home_controller.dart';
|
||||
|
||||
class HomePage extends GetView<HomeController> {
|
||||
static const String namedRoute = '/home-page';
|
||||
const HomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var homCtrl = controller;
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
child: SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.blueGrey,
|
||||
foregroundColor: Colors.white,
|
||||
title: const Text('Tank List'),
|
||||
centerTitle: true,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
controller.onInit();
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => homCtrl.logout(),
|
||||
icon: Icon(Icons.logout),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Obx(
|
||||
() => homCtrl.isLoading.value == false
|
||||
? ListView.builder(
|
||||
itemBuilder: (context, index) {
|
||||
var tank = homCtrl.listTankModel[index];
|
||||
return ListTile(
|
||||
title: Text(
|
||||
'${tank.szDate} - ${tank.szLiters}L - ${tank.szPricePerLiter}€/L',
|
||||
),
|
||||
subtitle: Text(
|
||||
'Total: ${tank.szPriceTotal}€ - Odometer: ${tank.szOdometer}km',
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: homCtrl.listTankModel.length,
|
||||
)
|
||||
: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
36
lib/pages/login_view.dart
Normal file
36
lib/pages/login_view.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../controller/login_controller.dart';
|
||||
import '../widgets/my_login_widget.dart';
|
||||
|
||||
class LoginPage extends GetView<LoginController> {
|
||||
static const String namedRoute = '/login-page';
|
||||
const LoginPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var logCtrl = controller;
|
||||
var displayWidth = MediaQuery.of(context).size.width;
|
||||
var displayHeight = MediaQuery.of(context).size.height;
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
body: Container(
|
||||
height: displayHeight,
|
||||
width: displayWidth,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 130.0,
|
||||
),
|
||||
color: Colors.blue.shade100,
|
||||
child: SingleChildScrollView(
|
||||
child: MyLoginWidget(
|
||||
onButtonPressed: () => logCtrl.login(),
|
||||
signInOnTab: () => logCtrl.goToSignInPage(),
|
||||
logCtrl: logCtrl,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
36
lib/pages/signin_view.dart
Normal file
36
lib/pages/signin_view.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../controller/signin_controller.dart';
|
||||
import '../widgets/my_signin_widget.dart';
|
||||
|
||||
class SigninPage extends GetView<SigninController> {
|
||||
static const String namedRoute = '/signin-page';
|
||||
const SigninPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var sigCtrl = controller;
|
||||
var displayWidth = MediaQuery.of(context).size.width;
|
||||
var displayHeight = MediaQuery.of(context).size.height;
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
body: Container(
|
||||
height: displayHeight,
|
||||
width: displayWidth,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 100.0,
|
||||
),
|
||||
color: Colors.blue.shade100,
|
||||
child: SingleChildScrollView(
|
||||
child: MySigninWidget(
|
||||
signCtrl: sigCtrl,
|
||||
onButtonPressed: () => sigCtrl.register(),
|
||||
logInOnTab: () => sigCtrl.goToLoginPage(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
168
lib/services/appwrite_service.dart
Normal file
168
lib/services/appwrite_service.dart
Normal file
@@ -0,0 +1,168 @@
|
||||
import 'package:appwrite/models.dart';
|
||||
import 'package:appwrite/appwrite.dart';
|
||||
import '../config/environment.dart';
|
||||
|
||||
class AppwriteService {
|
||||
static final String endpoint = Environment.appwritePublicEndpoint;
|
||||
static final String projectId = Environment.appwriteProjectId;
|
||||
static final String projectName = Environment.appwriteProjectName;
|
||||
static final String realtimeCollectionId =
|
||||
Environment.appwriteRealtimeCollectionId;
|
||||
static final String databaseId = Environment.appwriteDatabaseId;
|
||||
|
||||
final Client _client = Client().setProject(projectId).setEndpoint(endpoint);
|
||||
|
||||
// ignore: unused_field
|
||||
late final Account _account;
|
||||
// ignore: unused_field
|
||||
late final Databases _databases;
|
||||
|
||||
AppwriteService._internal() {
|
||||
_account = Account(_client);
|
||||
_databases = Databases(_client);
|
||||
}
|
||||
|
||||
static final AppwriteService _instance = AppwriteService._internal();
|
||||
|
||||
/// Singleton instance getter
|
||||
factory AppwriteService() => _instance;
|
||||
|
||||
// register new user with userName, e-Mail and password
|
||||
Future<bool> register(String userName, String email, String password) async {
|
||||
try {
|
||||
final user = await _account.create(
|
||||
userId: ID.unique(),
|
||||
email: email,
|
||||
password: password,
|
||||
name: userName,
|
||||
);
|
||||
print('Registrierung erfolgreich: ${user.$id}');
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('Registrierung fehlgeschlagen: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// login with e-Mail and password
|
||||
Future<bool> login(String email, String password) async {
|
||||
await logout();
|
||||
try {
|
||||
final session = await _account.createEmailPasswordSession(
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
print('Login erfolgreich: ${session.$id}');
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('Login fehlgeschlagen: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// logout current user
|
||||
Future<bool> logout() async {
|
||||
try {
|
||||
await _account.deleteSession(sessionId: 'current');
|
||||
print('Logout erfolgreich');
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('Logout fehlgeschlagen: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Get current user ID
|
||||
Future<String?> getCurrentUserId() async {
|
||||
try {
|
||||
final user = await _account.get();
|
||||
return user.$id;
|
||||
} catch (e) {
|
||||
print('Fehler beim Abrufen der Benutzer-ID: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Get List<Document> from Realtime Collection
|
||||
Future<List<Document>> getDocumentsFromCollection(String userId) async {
|
||||
try {
|
||||
final documents = await _databases.listDocuments(
|
||||
databaseId: databaseId,
|
||||
collectionId: realtimeCollectionId,
|
||||
queries: [Query.equal('userId', userId), Query.orderDesc('date')],
|
||||
);
|
||||
return documents.documents;
|
||||
} catch (e) {
|
||||
print('Fehler beim Abrufen der Dokumente: $e');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Get Document per Id from Realtime Collection
|
||||
Future<Document?> getDocumentById(String documentId) async {
|
||||
try {
|
||||
final document = await _databases.getDocument(
|
||||
databaseId: databaseId,
|
||||
collectionId: realtimeCollectionId,
|
||||
documentId: documentId,
|
||||
);
|
||||
return document;
|
||||
} catch (e) {
|
||||
print('Fehler beim Abrufen des Dokuments: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Save a new document to Realtime Collection
|
||||
Future<bool> createDocumentInCollection(Map<String, dynamic> data) async {
|
||||
try {
|
||||
await _databases.createDocument(
|
||||
databaseId: databaseId,
|
||||
collectionId: realtimeCollectionId,
|
||||
documentId: ID.unique(),
|
||||
data: data,
|
||||
);
|
||||
print('Dokument erfolgreich erstellt');
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('Fehler beim Erstellen des Dokuments: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Update an existing document in Realtime Collection
|
||||
Future<bool> updateDocumentInCollection(
|
||||
String documentId,
|
||||
Map<String, dynamic> data,
|
||||
) async {
|
||||
try {
|
||||
await _databases.updateDocument(
|
||||
databaseId: databaseId,
|
||||
collectionId: realtimeCollectionId,
|
||||
documentId: documentId,
|
||||
data: data,
|
||||
);
|
||||
print('Dokument erfolgreich aktualisiert');
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('Fehler beim Aktualisieren des Dokuments: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a document from Realtime Collection
|
||||
Future<bool> deleteDocumentFromCollection(String documentId) async {
|
||||
try {
|
||||
await _databases.deleteDocument(
|
||||
databaseId: databaseId,
|
||||
collectionId: realtimeCollectionId,
|
||||
documentId: documentId,
|
||||
);
|
||||
print('Dokument erfolgreich gelöscht');
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('Fehler beim Löschen des Dokuments: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
lib/widgets/my_login_widget.dart
Normal file
134
lib/widgets/my_login_widget.dart
Normal file
@@ -0,0 +1,134 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart' show GoogleFonts;
|
||||
import '../controller/login_controller.dart';
|
||||
|
||||
class MyLoginWidget extends StatelessWidget {
|
||||
final void Function()? onButtonPressed;
|
||||
final void Function()? signInOnTab;
|
||||
final LoginController logCtrl;
|
||||
|
||||
const MyLoginWidget({
|
||||
super.key,
|
||||
this.onButtonPressed,
|
||||
this.signInOnTab,
|
||||
required this.logCtrl,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final googleFont = GoogleFonts.righteous().fontFamily;
|
||||
return Column(
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
// Umriss (Outline)
|
||||
Text(
|
||||
"Login Page",
|
||||
style: TextStyle(
|
||||
fontSize: 44,
|
||||
fontFamily: googleFont,
|
||||
fontStyle: FontStyle.normal,
|
||||
letterSpacing: 5.0,
|
||||
foreground: Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 5
|
||||
..color = Colors.blue.shade900,
|
||||
),
|
||||
),
|
||||
// Füllung
|
||||
Text(
|
||||
"Login Page",
|
||||
style: TextStyle(
|
||||
fontSize: 44,
|
||||
fontFamily: googleFont,
|
||||
fontStyle: FontStyle.normal,
|
||||
color: Colors.orange.shade300,
|
||||
letterSpacing: 5.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.orange.shade400, width: 8),
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
child: Image.asset(
|
||||
'assets/images/guru.png',
|
||||
width: 400,
|
||||
height: 400,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50.0),
|
||||
child: TextField(
|
||||
controller: logCtrl.emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'E-Mail',
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50.0),
|
||||
child: TextField(
|
||||
obscureText: true,
|
||||
controller: logCtrl.passwordController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Password',
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
Colors.orange.shade500,
|
||||
),
|
||||
foregroundColor: WidgetStatePropertyAll<Color>(
|
||||
Colors.blue.shade900,
|
||||
),
|
||||
minimumSize: WidgetStatePropertyAll<Size>(Size(430, 60)),
|
||||
),
|
||||
onPressed: onButtonPressed,
|
||||
child: Text(
|
||||
'Login',
|
||||
style: TextStyle(fontSize: 34, fontFamily: googleFont),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(fontSize: 16, color: Colors.black),
|
||||
children: [
|
||||
TextSpan(text: 'Zum registrieren '),
|
||||
WidgetSpan(
|
||||
child: GestureDetector(
|
||||
onTap: signInOnTab,
|
||||
child: Text(
|
||||
'Sign in',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.blue.shade700,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TextSpan(text: ' clicken!!'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
146
lib/widgets/my_signin_widget.dart
Normal file
146
lib/widgets/my_signin_widget.dart
Normal file
@@ -0,0 +1,146 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart' show GoogleFonts;
|
||||
import '../controller/signin_controller.dart';
|
||||
|
||||
class MySigninWidget extends StatelessWidget {
|
||||
final void Function()? onButtonPressed;
|
||||
final void Function()? logInOnTab;
|
||||
final SigninController signCtrl;
|
||||
|
||||
const MySigninWidget({
|
||||
super.key,
|
||||
this.onButtonPressed,
|
||||
this.logInOnTab,
|
||||
required this.signCtrl,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final googleFont = GoogleFonts.righteous().fontFamily;
|
||||
return Column(
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
// Umriss (Outline)
|
||||
Text(
|
||||
"Signin Page",
|
||||
style: TextStyle(
|
||||
fontSize: 44,
|
||||
fontFamily: googleFont,
|
||||
fontStyle: FontStyle.normal,
|
||||
letterSpacing: 5.0,
|
||||
foreground: Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 5
|
||||
..color = Colors.blue.shade900,
|
||||
),
|
||||
),
|
||||
// Füllung
|
||||
Text(
|
||||
"Signin Page",
|
||||
style: TextStyle(
|
||||
fontSize: 44,
|
||||
fontFamily: googleFont,
|
||||
fontStyle: FontStyle.normal,
|
||||
color: Colors.orange.shade300,
|
||||
letterSpacing: 5.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.orange.shade400, width: 8),
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
child: Image.asset(
|
||||
'assets/images/guru01.png',
|
||||
width: 400,
|
||||
height: 400,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50.0),
|
||||
child: TextField(
|
||||
controller: signCtrl.userNameController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Username',
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50.0),
|
||||
child: TextField(
|
||||
controller: signCtrl.emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Email',
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50.0),
|
||||
child: TextField(
|
||||
obscureText: true,
|
||||
controller: signCtrl.passwordController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Password',
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
Colors.orange.shade500,
|
||||
),
|
||||
foregroundColor: WidgetStatePropertyAll<Color>(
|
||||
Colors.blue.shade900,
|
||||
),
|
||||
minimumSize: WidgetStatePropertyAll<Size>(Size(430, 60)),
|
||||
),
|
||||
onPressed: onButtonPressed,
|
||||
child: Text(
|
||||
'Register',
|
||||
style: TextStyle(fontSize: 34, fontFamily: googleFont),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(fontSize: 16, color: Colors.black),
|
||||
children: [
|
||||
TextSpan(text: 'Zum login '),
|
||||
WidgetSpan(
|
||||
child: GestureDetector(
|
||||
onTap: logInOnTab,
|
||||
child: Text(
|
||||
'Log in',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.blue.shade700,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TextSpan(text: ' clicken!!'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user