commit aeca07a5a35041c1fe698e6f114c669b69cbf65b Author: atseirjo Date: Fri Jan 23 07:33:20 2026 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3820a95 --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..644060a --- /dev/null +++ b/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "3b62efc2a3da49882f43c372e0bc53daef7295a6" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + - platform: web + create_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + base_revision: 3b62efc2a3da49882f43c372e0bc53daef7295a6 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/README.md b/README.md new file mode 100644 index 0000000..93af291 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# flutter_tank_web_app + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..ace0476 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,31 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +analyzer: + errors: + avoid_print: ignore +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/assets/images/guru.png b/assets/images/guru.png new file mode 100644 index 0000000..1de6dc1 Binary files /dev/null and b/assets/images/guru.png differ diff --git a/assets/images/guru01.png b/assets/images/guru01.png new file mode 100644 index 0000000..1638908 Binary files /dev/null and b/assets/images/guru01.png differ diff --git a/lib/config/environment.dart b/lib/config/environment.dart new file mode 100644 index 0000000..7ccea88 --- /dev/null +++ b/lib/config/environment.dart @@ -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'; +} diff --git a/lib/controller/home_controller.dart b/lib/controller/home_controller.dart new file mode 100644 index 0000000..c5648eb --- /dev/null +++ b/lib/controller/home_controller.dart @@ -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 = [].obs; + final appwriteService = AppwriteService(); + + @override + void onInit() { + _loadListDocument(); + super.onInit(); + } + + @override + void onReady() {} + + @override + void onClose() {} + + Future _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 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, + ); + } + } +} diff --git a/lib/controller/login_controller.dart b/lib/controller/login_controller.dart new file mode 100644 index 0000000..d0036fc --- /dev/null +++ b/lib/controller/login_controller.dart @@ -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); + } +} diff --git a/lib/controller/signin_controller.dart b/lib/controller/signin_controller.dart new file mode 100644 index 0000000..317cc22 --- /dev/null +++ b/lib/controller/signin_controller.dart @@ -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; + } +} diff --git a/lib/helper/helper.dart b/lib/helper/helper.dart new file mode 100644 index 0000000..adfd4c5 --- /dev/null +++ b/lib/helper/helper.dart @@ -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); +} diff --git a/lib/helper/sample_bindings.dart b/lib/helper/sample_bindings.dart new file mode 100644 index 0000000..2ee4238 --- /dev/null +++ b/lib/helper/sample_bindings.dart @@ -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()); + Get.lazyPut(() => SigninController()); + Get.lazyPut(() => HomeController()); + + + } +} diff --git a/lib/helper/sample_routes.dart b/lib/helper/sample_routes.dart new file mode 100644 index 0000000..d22f7f2 --- /dev/null +++ b/lib/helper/sample_routes.dart @@ -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> 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, + ), + + ]; +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..5a6d027 --- /dev/null +++ b/lib/main.dart @@ -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, + ); + } +} + diff --git a/lib/models/tank_model.dart b/lib/models/tank_model.dart new file mode 100644 index 0000000..148fe4b --- /dev/null +++ b/lib/models/tank_model.dart @@ -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 toMap() { + final result = {}; + + 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 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)'; + } +} diff --git a/lib/pages/home_view.dart b/lib/pages/home_view.dart new file mode 100644 index 0000000..e216320 --- /dev/null +++ b/lib/pages/home_view.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../controller/home_controller.dart'; + +class HomePage extends GetView { + 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()), + ), + ), + ), + ); + } +} diff --git a/lib/pages/login_view.dart b/lib/pages/login_view.dart new file mode 100644 index 0000000..8e0bf0f --- /dev/null +++ b/lib/pages/login_view.dart @@ -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 { + 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, + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/signin_view.dart b/lib/pages/signin_view.dart new file mode 100644 index 0000000..b77639b --- /dev/null +++ b/lib/pages/signin_view.dart @@ -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 { + 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(), + ), + ), + ), + ), + ); + } +} diff --git a/lib/services/appwrite_service.dart b/lib/services/appwrite_service.dart new file mode 100644 index 0000000..d799376 --- /dev/null +++ b/lib/services/appwrite_service.dart @@ -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 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 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 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 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 from Realtime Collection + Future> 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 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 createDocumentInCollection(Map 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 updateDocumentInCollection( + String documentId, + Map 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 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; + } + } +} diff --git a/lib/widgets/my_login_widget.dart b/lib/widgets/my_login_widget.dart new file mode 100644 index 0000000..5602f1c --- /dev/null +++ b/lib/widgets/my_login_widget.dart @@ -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( + Colors.orange.shade500, + ), + foregroundColor: WidgetStatePropertyAll( + Colors.blue.shade900, + ), + minimumSize: WidgetStatePropertyAll(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!!'), + ], + ), + ), + ], + ); + } +} diff --git a/lib/widgets/my_signin_widget.dart b/lib/widgets/my_signin_widget.dart new file mode 100644 index 0000000..fffef7f --- /dev/null +++ b/lib/widgets/my_signin_widget.dart @@ -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( + Colors.orange.shade500, + ), + foregroundColor: WidgetStatePropertyAll( + Colors.blue.shade900, + ), + minimumSize: WidgetStatePropertyAll(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!!'), + ], + ), + ), + ], + ); + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..591b9dc --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,610 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + appwrite: + dependency: "direct main" + description: + name: appwrite + sha256: "3e1f618c8f75bafa49ef7b1b445f64c53cf4620a195443f4d119bbc95a666d0a" + url: "https://pub.dev" + source: hosted + version: "14.0.0" + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + cookie_jar: + dependency: transitive + description: + name: cookie_jar + sha256: a6ac027d3ed6ed756bfce8f3ff60cb479e266f3b0fdabd6242b804b6765e52de + url: "https://pub.dev" + source: hosted + version: "4.0.8" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 + url: "https://pub.dev" + source: hosted + version: "10.1.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f + url: "https://pub.dev" + source: hosted + version: "7.0.3" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c + url: "https://pub.dev" + source: hosted + version: "2.1.5" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_auth_2: + dependency: transitive + description: + name: flutter_web_auth_2 + sha256: "4d3d2fd3d26bf1a26b3beafd4b4b899c0ffe10dc99af25abc58ffe24e991133c" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + flutter_web_auth_2_platform_interface: + dependency: transitive + description: + name: flutter_web_auth_2_platform_interface + sha256: e8669e262005a8354389ba2971f0fc1c36188481234ff50d013aaf993f30f739 + url: "https://pub.dev" + source: hosted + version: "3.1.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + get: + dependency: "direct main" + description: + name: get + sha256: "5ed34a7925b85336e15d472cc4cfe7d9ebf4ab8e8b9f688585bf6b50f4c3d79a" + url: "https://pub.dev" + source: hosted + version: "4.7.3" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: "6996212014b996eaa17074e02b1b925b212f5e053832d9048970dc27255a8fb3" + url: "https://pub.dev" + source: hosted + version: "7.1.0" + hooks: + dependency: transitive + description: + name: hooks + sha256: "5d309c86e7ce34cd8e37aa71cb30cb652d3829b900ab145e4d9da564b31d59f7" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + http: + dependency: transitive + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + intl: + dependency: "direct main" + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + lints: + dependency: transitive + description: + name: lints + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 + url: "https://pub.dev" + source: hosted + version: "6.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "89e83885ba09da5fdf2cdacc8002a712ca238c28b7f717910b34bcd27b0d03ac" + url: "https://pub.dev" + source: hosted + version: "0.17.4" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "9922a1ad59ac5afb154cc948aa6ded01987a75003651d0a2866afc23f4da624e" + url: "https://pub.dev" + source: hosted + version: "9.2.3" + package_info_plus: + dependency: transitive + description: + name: package_info_plus + sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" + url: "https://pub.dev" + source: hosted + version: "8.3.1" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e + url: "https://pub.dev" + source: hosted + version: "2.2.22" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + url: "https://pub.dev" + source: hosted + version: "1.10.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + url: "https://pub.dev" + source: hosted + version: "0.7.7" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + url_launcher: + dependency: transitive + description: + name: url_launcher + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611" + url: "https://pub.dev" + source: hosted + version: "6.3.28" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad + url: "https://pub.dev" + source: hosted + version: "6.3.6" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" + url: "https://pub.dev" + source: hosted + version: "3.2.5" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f + url: "https://pub.dev" + source: hosted + version: "2.4.2" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.dev" + source: hosted + version: "15.0.2" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" + url: "https://pub.dev" + source: hosted + version: "1.1.5" + window_to_front: + dependency: transitive + description: + name: window_to_front + sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee" + url: "https://pub.dev" + source: hosted + version: "0.0.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.10.7 <4.0.0" + flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..269d5ab --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,29 @@ +name: flutter_tank_web_app +description: "A new Flutter project." + +publish_to: "none" + +version: 1.0.0+1 + +environment: + sdk: ^3.10.7 + +dependencies: + cupertino_icons: ^1.0.8 + flutter: + sdk: flutter + get: ^4.7.3 + google_fonts: ^7.1.0 + intl: ^0.20.2 + appwrite: ^14.0.0 + +dev_dependencies: + flutter_lints: ^6.0.0 + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true + + assets: + - assets/images/ diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..52420c2 --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:flutter_tank_web_app/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..1daee35 --- /dev/null +++ b/web/index.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + flutter_tank_web_app + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..d15b55b --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "flutter_tank_web_app", + "short_name": "flutter_tank_web_app", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +}