diff --git a/lib/data/repository/appwrite_repository.dart b/lib/data/repository/appwrite_repository.dart index cea06c0..de24e15 100644 --- a/lib/data/repository/appwrite_repository.dart +++ b/lib/data/repository/appwrite_repository.dart @@ -103,4 +103,13 @@ class AppwriteRepository { ); return response; } + + Future listTankStops(String userId) async { + final response = await _databases.listDocuments( + databaseId: dotenv.get('APPWRITE_DATABASE_ID'), + collectionId: dotenv.get('APPWRITE_COLLECTION_ID'), + queries: [Query.equal('userId', userId)], + ); + return response; + } } diff --git a/lib/pages/login/login_controller.dart b/lib/pages/login/login_controller.dart index 841d211..ed53346 100644 --- a/lib/pages/login/login_controller.dart +++ b/lib/pages/login/login_controller.dart @@ -25,6 +25,12 @@ class LoginController extends GetxController { @override void onInit() { super.onInit(); + print('LoginController initialized'); + } + + @override + void onReady() { + super.onReady(); // Initialize any necessary data or state here var isSessionId = _dataBox.hasData('sessionId'); if (isSessionId) { @@ -35,12 +41,6 @@ class LoginController extends GetxController { // If no session ID, initialize the login controller print('No session ID found, initializing LoginController'); } - print('LoginController initialized'); - } - - @override - void onReady() { - super.onReady(); // This method is called when the controller is ready print('LoginController is ready'); } diff --git a/lib/pages/tank/tank_controller.dart b/lib/pages/tank/tank_controller.dart index 78ad838..18fedf0 100644 --- a/lib/pages/tank/tank_controller.dart +++ b/lib/pages/tank/tank_controller.dart @@ -9,6 +9,7 @@ import '../../utils/extensions/static_helper.dart'; import '../../data/repository/location_repository.dart'; import '../../data/repository/appwrite_repository.dart'; import '../login/login_view.dart'; +import '../tanklist/tanklist_view.dart'; class TankController extends GetxController { final _dataBox = GetStorage('MyUserStorage'); @@ -149,9 +150,6 @@ class TankController extends GetxController { @override void onInit() { super.onInit(); - if (_dataBox.hasData('sessionId')) { - rxSessionIdString(_dataBox.read('sessionId').toString()); - } // Rufe den Standort direkt beim Initialisieren des Controllers ab, falls gewünscht. fetchCurrentLocation(); } @@ -159,6 +157,9 @@ class TankController extends GetxController { @override void onReady() async { super.onReady(); + if (_dataBox.hasData('sessionId')) { + rxSessionIdString(_dataBox.read('sessionId').toString()); + } await getCurrentLoggedinUser(); FocusScope.of(Get.context!).requestFocus(firstFocusNode); print('TankController is ready'); @@ -263,6 +264,6 @@ class TankController extends GetxController { goToTankStopsView() async { clearTextEditingController(); - //await Get.offAndToNamed(TanklistPage.namedRoute); + await Get.offAndToNamed(TanklistPage.namedRoute); } } diff --git a/lib/pages/tanklist/tanklist_controller.dart b/lib/pages/tanklist/tanklist_controller.dart new file mode 100644 index 0000000..2e60ef1 --- /dev/null +++ b/lib/pages/tanklist/tanklist_controller.dart @@ -0,0 +1,113 @@ +import 'package:appwrite/appwrite.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; + +import '../../data/models/tank_model.dart'; +import '../../data/repository/appwrite_repository.dart'; +import '../../pages/tank/tank_view.dart'; +import '../login/login_view.dart'; + +class TanklistController extends GetxController { + final _dataBox = GetStorage('MyUserStorage'); + final isloadingList = false.obs; + final tankList = [].obs; + final szRxUserId = 'NoUser'.obs; + //AppWrite API-REST get Data + final AppwriteRepository _authRepository = AppwriteRepository(); + + @override + void onInit() { + szRxUserId(_dataBox.read('userId')); + super.onInit(); + } + + @override + void onReady() { + getTankList(); + super.onReady(); + } + + @override + void onClose() {} + + void getTankList() async { + isloadingList(true); + bool isErrorByLoading = false; + String message = ''; + try { + await _authRepository + .listTankStops(szRxUserId.value) + .then((tankListData) { + if (tankListData.documents.isEmpty) { + isErrorByLoading = true; + message = 'Leere Liste keine Daten vorhanden'; + return; + } + tankList.clear(); + var data = tankListData.toMap(); + List d = data['documents'].toList(); + tankList.value = + d.map((e) => AppWriteTankModel.fromMap(e['data'])).toList(); + tankList.sort((a, b) { + final DateTime dateA = DateTime.parse(a.date); + final DateTime dateB = DateTime.parse(b.date); + return dateB.compareTo(dateA); + }); + message = 'Liste wurde erfolgreich geladen'; + }).catchError((error) { + isErrorByLoading = true; + if (error is AppwriteException) { + message = error.message!; + } else { + message = 'Uuups da ist was schief gelaufen'; + } + }); + } catch (e) { + isErrorByLoading = true; + message = 'Fehler beim Laden der Tankliste'; + print('Error fetching tank list: $e'); + } finally { + if (!isErrorByLoading){ + isloadingList(false); + } + } + String title = isErrorByLoading ? 'Fehler' : 'Erfolg'; + Get.snackbar( + title, + message, + backgroundColor: isErrorByLoading ? Colors.red : Colors.green, + snackPosition: SnackPosition.BOTTOM, + duration: const Duration(seconds: 4), + ); + update(); + } + + void goToUpdatePage() { + // Go to Update Page + } + void goToInputPage() { + Get.offAndToNamed(TankPage.namedRoute); + } + + void logoutSessionAndGoToLoginPage() async { + // Handle logout logic here + print('Logout session and go to login page'); + // Clear GetStorage session ID + _dataBox.remove('sessionId'); + _dataBox.remove('userId'); + _dataBox.remove('userName'); + _dataBox.remove('userEmail'); + print('Session ID removed from GetStorage'); + await _authRepository.logout(); + Get.offAndToNamed(LoginPage.namedRoute); + } + + void goToChartView() { + //Get.offAndToNamed(GraphPage.namedRoute); + } + + void goToTrackingPage() { + //Get.offAndToNamed(TrackingPage.namedRoute); + } +} diff --git a/lib/pages/tanklist/tanklist_view.dart b/lib/pages/tanklist/tanklist_view.dart new file mode 100644 index 0000000..ddb7bef --- /dev/null +++ b/lib/pages/tanklist/tanklist_view.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import './tanklist_controller.dart'; +import './widgets/my_list_tile_item.dart'; + +class TanklistPage extends GetView { + static const namedRoute = '/tank-stop-liste-page'; + const TanklistPage({super.key}); + + @override + Widget build(BuildContext context) { + var tankListCtrl = controller; + return SafeArea( + child: Scaffold( + appBar: AppBar( + title: Text('Tankstops'), + centerTitle: true, + //backgroundColor: Colors.grey.shade600, + actions: [ + IconButton( + icon: Icon(Icons.add_chart, color: Colors.grey.shade300), + onPressed: () async { + // Handle go to Chart View + tankListCtrl.goToChartView(); + }, + ), + IconButton( + icon: Icon(Icons.logout, color: Colors.grey.shade300), + onPressed: () async { + // Handle logout logic here + tankListCtrl.logoutSessionAndGoToLoginPage(); + }, + ), + ], + ), + floatingActionButton: Column( + mainAxisAlignment: + MainAxisAlignment.end, // Positioniere die Buttons am unteren Ende + crossAxisAlignment: CrossAxisAlignment.end, // Richte sie rechts aus + mainAxisSize: MainAxisSize.min, // Nimm nur den benötigten Platz ein + children: [ + FloatingActionButton( + onPressed: () => tankListCtrl.goToInputPage(), + backgroundColor: Colors.blue, + child: Icon(Icons.add), + ), + const SizedBox(width: 16), + FloatingActionButton( + onPressed: () => tankListCtrl.goToTrackingPage(), + backgroundColor: Colors.green, + child: Icon(Icons.gps_fixed_rounded), + ), + ], + ), + body: Obx(() + => tankListCtrl.isloadingList.value == false ? Padding( + padding: EdgeInsetsGeometry.only(left: 25, right: 25), + child: ListView.builder( + padding: EdgeInsets.only(top: 8, bottom: 8), + physics: const BouncingScrollPhysics(), + itemBuilder: ((BuildContext context, int index) { + var item = tankListCtrl.tankList[index]; + return Column( + children: [ + Container( + decoration: BoxDecoration( + color: Colors.blue.withValues(alpha: 0.2), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(20), + bottomRight: Radius.circular(20), + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withValues( + alpha: 0.7, + ), // Die Farbe des Schattens + spreadRadius: + 2, // Wie weit sich der Schatten ausbreitet + blurRadius: + 3, // Wie stark der Schatten verschwommen ist + offset: const Offset( + 0, + 3, + ), // Der Versatz des Schattens (x, y) + ), + ], + ), + child: MyListTileItem(listItem: item), + ), + SizedBox(height: 15), + ], + ); + }), + itemCount: tankListCtrl.tankList.length, + ), + ):Center( + child: CircularProgressIndicator( + color: Colors.blue, + ), + ) + ), + ), + ); + } +} diff --git a/lib/pages/tanklist/widgets/my_list_tile_item.dart b/lib/pages/tanklist/widgets/my_list_tile_item.dart new file mode 100644 index 0000000..a707a59 --- /dev/null +++ b/lib/pages/tanklist/widgets/my_list_tile_item.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; + +import '../../../data/models/tank_model.dart'; + + +class MyListTileItem extends StatelessWidget { + const MyListTileItem({super.key, required this.listItem}); + + final AppWriteTankModel listItem; + + @override + Widget build(BuildContext context) { + return _myListItem(context); + } + + Widget _myListItem(BuildContext context) { + var textColor = Colors.orange.shade400; + var summePrice = + (double.parse(listItem.liters) * double.parse(listItem.pricePerLiter)) + .toStringAsFixed(2); + return Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + alignment: WrapAlignment.spaceBetween, + children: [ + Row( + children: [ + Icon(Icons.date_range), + SizedBox(width: 10), + Text( + listItem.date, + style: TextStyle(color: textColor, fontSize: 25), + ), + ], + ), + Row( + children: [ + Image.asset('lib/icons/kilometer.png'), + SizedBox(width: 10), + Text( + '${listItem.odometer} km', + style: TextStyle(color: textColor, fontSize: 25), + ), + ], + ), + ], + ), + Divider(thickness: 3, color: Colors.black), + Row( + children: [ + Icon(Icons.local_gas_station), + SizedBox(width: 10), + Text( + '${listItem.liters} L', + style: TextStyle(color: textColor, fontSize: 25), + ), + ], + ), + Divider(thickness: 1, color: Colors.black), + Row( + children: [ + Icon(Icons.euro), + SizedBox(width: 10), + Text( + '${listItem.pricePerLiter} €/L ', + style: TextStyle(color: textColor, fontSize: 25), + ), + ], + ), + Divider(thickness: 1, color: Colors.black), + Row( + children: [ + Icon(Icons.price_change), + SizedBox(width: 10), + Text('$summePrice €', style: TextStyle(color: textColor, fontSize: 25)), + ], + ), + Divider(thickness: 1, color: Colors.black), + Row( + children: [ + Icon(Icons.pin_drop), + SizedBox(width: 10), + SizedBox( + width: 250, + child: Text( + listItem.location, + style: TextStyle(color: textColor, fontSize: 16), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/utils/extensions/sample_bindings.dart b/lib/utils/extensions/sample_bindings.dart index bfd1318..0ea1507 100644 --- a/lib/utils/extensions/sample_bindings.dart +++ b/lib/utils/extensions/sample_bindings.dart @@ -2,6 +2,7 @@ import 'package:get/get.dart'; import '../../pages/login/login_controller.dart'; import '../../pages/tank/tank_controller.dart'; +import '../../pages/tanklist/tanklist_controller.dart'; @@ -11,7 +12,7 @@ class SampleBindings extends Bindings { // Define your dependencies here Get.lazyPut(() => LoginController()); Get.lazyPut(() => TankController()); - // Get.lazyPut(() => TanklistController(AuthRepository(AppWriteProvider()))); + Get.lazyPut(() => TanklistController()); // Get.lazyPut(() => GraphController(AuthRepository(AppWriteProvider()))); // Get.lazyPut(() => TrackingController(AuthRepository(AppWriteProvider()))); // Get.lazyPut(() => MapController(AuthRepository(AppWriteProvider()), LocationRepository(LocationProvider()))); diff --git a/lib/utils/extensions/sample_routes.dart b/lib/utils/extensions/sample_routes.dart index 380aa4c..439ce0e 100644 --- a/lib/utils/extensions/sample_routes.dart +++ b/lib/utils/extensions/sample_routes.dart @@ -2,6 +2,7 @@ import 'package:get/get.dart'; import '../../pages/login/login_view.dart'; import '../../pages/tank/tank_view.dart'; +import '../../pages/tanklist/tanklist_view.dart'; import './sample_bindings.dart'; @@ -19,11 +20,11 @@ class SampleRouts { page: () => const TankPage(), binding: sampleBindings, ), - // GetPage( - // name: TanklistPage.namedRoute, - // page: () => const TanklistPage(), - // binding: sampleBindings, - // ), + GetPage( + name: TanklistPage.namedRoute, + page: () => const TanklistPage(), + binding: sampleBindings, + ), // GetPage( // name: GraphPage.namedRoute, // page: () => const GraphPage(),