diff --git a/lib/controller/gasstations_controller.dart b/lib/controller/gasstations_controller.dart new file mode 100644 index 0000000..fb85828 --- /dev/null +++ b/lib/controller/gasstations_controller.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:get/get.dart'; +import '../models/econtrol_model.dart'; +import '../services/econtrol_service.dart'; + +class GasstationsController extends GetxController { + final isLoading = false.obs; + final isLoadingLocation = false.obs; + final eControlData = [].obs; + + @override + void onInit() { + _loadStationInfosList(); + super.onInit(); + } + + @override + void onReady() {} + + @override + void onClose() {} + + Future _loadStationInfosList() async { + isLoading.value = true; + bool serviceEnabled; + if (eControlData.isNotEmpty) { + eControlData.clear(); + } + final eControlService = EControlService(); + LocationPermission permission; + + try { + isLoadingLocation.value = true; + + // 1. Prüfen, ob Standortdienste aktiviert sind + serviceEnabled = await Geolocator.isLocationServiceEnabled(); + if (!serviceEnabled) { + return Future.error('Standortdienste sind deaktiviert.'); + } + + // 2. Berechtigungen prüfen + permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.denied) { + return Future.error('Berechtigung verweigert.'); + } + } + + // 3. Position abrufen + Position position = await Geolocator.getCurrentPosition( + locationSettings: const LocationSettings( + accuracy: LocationAccuracy.high, + ), + ); + + // 4. Standort über Backend-Proxy abrufen + var lat = position.latitude; + var lon = position.longitude; + // Simulate fetching data from an API or database + await eControlService.getEControlData( + lat, + lon, + 'DIE', + ); + eControlData.addAll(eControlService.eControlData); + } catch (e) { + Get.snackbar( + "Fehler", + "Standort konnte nicht abgerufen werden: $e", + snackPosition: SnackPosition.BOTTOM, + backgroundColor: Colors.red[100], + colorText: Colors.red[900], + ); + print("Fehler beim Abrufen des Standorts: $e"); + } finally { + isLoadingLocation.value = false; + } + isLoading.value = false; + update(); + } +} diff --git a/lib/controller/home_controller.dart b/lib/controller/home_controller.dart index 8e4aabd..a5d8084 100644 --- a/lib/controller/home_controller.dart +++ b/lib/controller/home_controller.dart @@ -1,3 +1,4 @@ +import 'package:flutter_tank_web_app/pages/gasstations_view.dart'; import 'package:get/get.dart'; import '../models/tank_model.dart'; @@ -105,4 +106,8 @@ class HomeController extends GetxController { void goToGraphPage() { Get.toNamed(GraphPage.namedRoute, arguments: listTankModel); } + + void goToGasStations() { + Get.toNamed(GasstationsPage.namedRoute); + } } diff --git a/lib/helper/sample_bindings.dart b/lib/helper/sample_bindings.dart index 1c41969..3c800fa 100644 --- a/lib/helper/sample_bindings.dart +++ b/lib/helper/sample_bindings.dart @@ -6,6 +6,7 @@ import '../controller/graph_controller.dart'; import '../controller/home_controller.dart'; import '../controller/login_controller.dart'; import '../controller/signin_controller.dart'; +import '../controller/gasstations_controller.dart'; @@ -19,6 +20,7 @@ class SampleBindings extends Bindings { Get.lazyPut(() => DetailController()); Get.lazyPut(() => EditController()); Get.lazyPut(() => GraphController()); + Get.lazyPut(() => GasstationsController()); } diff --git a/lib/helper/sample_routes.dart b/lib/helper/sample_routes.dart index 908e7cb..46e1ef4 100644 --- a/lib/helper/sample_routes.dart +++ b/lib/helper/sample_routes.dart @@ -1,6 +1,7 @@ import 'package:get/get.dart'; import '../pages/detail_view.dart'; import '../pages/edit_view.dart'; +import '../pages/gasstations_view.dart'; import '../pages/graph_view.dart'; import 'sample_bindings.dart'; import '../pages/home_view.dart'; @@ -40,5 +41,10 @@ class SampleRouts { page: () => const GraphPage(), binding: sampleBindings, ), + GetPage( + name: GasstationsPage.namedRoute, + page: () => const GasstationsPage(), + binding: sampleBindings, + ), ]; } diff --git a/lib/models/econtrol_model.dart b/lib/models/econtrol_model.dart new file mode 100644 index 0000000..48487e1 --- /dev/null +++ b/lib/models/econtrol_model.dart @@ -0,0 +1,269 @@ + + +class EControlModel { + int? id; + String? name; + Location? location; + Contact? contact; + List? openingHours; + OfferInformation? offerInformation; + PaymentMethods? paymentMethods; + PaymentArrangements? paymentArrangements; + int? position; + bool? open; + double? distance; + List? prices; + + EControlModel( + {this.id, + this.name, + this.location, + this.contact, + this.openingHours, + this.offerInformation, + this.paymentMethods, + this.paymentArrangements, + this.position, + this.open, + this.distance, + this.prices}); + + EControlModel.fromJson(Map json) { + id = json['id']; + name = json['name']; + location = json['location'] != null + ? Location.fromJson(json['location']) + : null; + contact = + json['contact'] != null ? Contact.fromJson(json['contact']) : null; + if (json['openingHours'] != null) { + openingHours = []; + json['openingHours'].forEach((v) { + openingHours!.add(OpeningHours.fromJson(v)); + }); + } + offerInformation = json['offerInformation'] != null + ? OfferInformation.fromJson(json['offerInformation']) + : null; + paymentMethods = json['paymentMethods'] != null + ? PaymentMethods.fromJson(json['paymentMethods']) + : null; + paymentArrangements = json['paymentArrangements'] != null + ? PaymentArrangements.fromJson(json['paymentArrangements']) + : null; + position = json['position']; + open = json['open']; + distance = json['distance']; + if (json['prices'] != null) { + prices = []; + json['prices'].forEach((v) { + prices!.add(Prices.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['name'] = name; + if (location != null) { + data['location'] = location!.toJson(); + } + if (contact != null) { + data['contact'] = contact!.toJson(); + } + if (openingHours != null) { + data['openingHours'] = openingHours!.map((v) => v.toJson()).toList(); + } + if (offerInformation != null) { + data['offerInformation'] = offerInformation!.toJson(); + } + if (paymentMethods != null) { + data['paymentMethods'] = paymentMethods!.toJson(); + } + if (paymentArrangements != null) { + data['paymentArrangements'] = paymentArrangements!.toJson(); + } + data['position'] = position; + data['open'] = open; + data['distance'] = distance; + if (prices != null) { + data['prices'] = prices!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Location { + String? address; + String? postalCode; + String? city; + double? latitude; + double? longitude; + + Location( + {this.address, + this.postalCode, + this.city, + this.latitude, + this.longitude}); + + Location.fromJson(Map json) { + address = json['address']; + postalCode = json['postalCode']; + city = json['city']; + latitude = json['latitude']; + longitude = json['longitude']; + } + + Map toJson() { + final Map data = {}; + data['address'] = address; + data['postalCode'] = postalCode; + data['city'] = city; + data['latitude'] = latitude; + data['longitude'] = longitude; + return data; + } +} + +class Contact { + String? telephone; + String? fax; + String? mail; + String? website; + + Contact({this.telephone, this.fax, this.mail, this.website}); + + Contact.fromJson(Map json) { + telephone = json['telephone']; + fax = json['fax']; + mail = json['mail']; + website = json['website']; + } + + Map toJson() { + final Map data = {}; + data['telephone'] = telephone; + data['fax'] = fax; + data['mail'] = mail; + data['website'] = website; + return data; + } +} + +class OpeningHours { + String? day; + String? label; + int? order; + String? from; + String? to; + + OpeningHours({this.day, this.label, this.order, this.from, this.to}); + + OpeningHours.fromJson(Map json) { + day = json['day']; + label = json['label']; + order = json['order']; + from = json['from']; + to = json['to']; + } + + Map toJson() { + final Map data = {}; + data['day'] = day; + data['label'] = label; + data['order'] = order; + data['from'] = from; + data['to'] = to; + return data; + } +} + +class OfferInformation { + bool? service; + bool? selfService; + bool? unattended; + + OfferInformation({this.service, this.selfService, this.unattended}); + + OfferInformation.fromJson(Map json) { + service = json['service']; + selfService = json['selfService']; + unattended = json['unattended']; + } + + Map toJson() { + final Map data = {}; + data['service'] = service; + data['selfService'] = selfService; + data['unattended'] = unattended; + return data; + } +} + +class PaymentMethods { + bool? cash; + bool? debitCard; + bool? creditCard; + String? others; + + PaymentMethods({this.cash, this.debitCard, this.creditCard, this.others}); + + PaymentMethods.fromJson(Map json) { + cash = json['cash']; + debitCard = json['debitCard']; + creditCard = json['creditCard']; + others = json['others']; + } + + Map toJson() { + final Map data = {}; + data['cash'] = cash; + data['debitCard'] = debitCard; + data['creditCard'] = creditCard; + data['others'] = others; + return data; + } +} + +class PaymentArrangements { + bool? cooperative; + bool? clubCard; + + PaymentArrangements({this.cooperative, this.clubCard}); + + PaymentArrangements.fromJson(Map json) { + cooperative = json['cooperative']; + clubCard = json['clubCard']; + } + + Map toJson() { + final Map data = {}; + data['cooperative'] = cooperative; + data['clubCard'] = clubCard; + return data; + } +} + +class Prices { + String? fuelType; + double? amount; + String? label; + + Prices({this.fuelType, this.amount, this.label}); + + Prices.fromJson(Map json) { + fuelType = json['fuelType']; + amount = json['amount']; + label = json['label']; + } + + Map toJson() { + final Map data = {}; + data['fuelType'] = fuelType; + data['amount'] = amount; + data['label'] = label; + return data; + } +} diff --git a/lib/pages/gasstations_view.dart b/lib/pages/gasstations_view.dart new file mode 100644 index 0000000..c634743 --- /dev/null +++ b/lib/pages/gasstations_view.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../controller/gasstations_controller.dart'; + +class GasstationsPage extends GetView { + static const String namedRoute = '/gasstations-page'; + const GasstationsPage({super.key}); + + @override + Widget build(BuildContext context) { + var staCtrl = controller; + return Scaffold( + appBar: AppBar( + toolbarHeight: 100, + backgroundColor: Colors.blueGrey, + foregroundColor: Colors.white, + title: const Text('Gas Stations'), + ), + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.blueGrey[800]!, + Colors.blueGrey[600]!, + Colors.blueGrey[300]!, + Colors.blue[100]!, + ], + ), + ), + child: Center( + child: Obx(() { + if (staCtrl.isLoading.value) { + return const CircularProgressIndicator(); + } else if (staCtrl.eControlData.isEmpty) { + return const Text('No gas stations found.'); + } else { + return ListView.builder( + itemCount: staCtrl.eControlData.length, + itemBuilder: (context, index) { + final station = staCtrl.eControlData[index]; + return ListTile( + title: Text(station.name ?? 'Unknown Station'), + subtitle: Text(station.location?.address ?? 'No address'), + trailing: Text(station.open == true ? 'Open' : 'Closed'), + ); + }, + ); + } + }), + ), + ), + ); + } +} diff --git a/lib/pages/home_view.dart b/lib/pages/home_view.dart index 56ffc36..5a0d537 100644 --- a/lib/pages/home_view.dart +++ b/lib/pages/home_view.dart @@ -51,6 +51,12 @@ class HomePage extends GetView { homCtrl.onInit(); }, ), + IconButton( + icon: const Icon(Icons.gas_meter), + onPressed: () { + homCtrl.goToGasStations(); + }, + ), IconButton( icon: const Icon(Icons.collections), onPressed: () { diff --git a/lib/services/econtrol_service.dart b/lib/services/econtrol_service.dart new file mode 100644 index 0000000..78a7919 --- /dev/null +++ b/lib/services/econtrol_service.dart @@ -0,0 +1,70 @@ + + +import '../models/econtrol_model.dart'; +import 'package:http/http.dart' as http; + +class EControlService { + late List eControlData; + + Future getEControlData(double latitude, double longitude, String fuelType) async { + // Simulate fetching data from an API or database + await Future.delayed(Duration(seconds: 2)); // Simulate network delay + eControlData = [ + EControlModel( + id: 1, + name: 'E-Control Station 1', + location: Location( + latitude: 47.93875449671056, + longitude: 13.762706553431048, + ), + contact: Contact( + telephone: '+43 123 456789', + mail: '', + website: 'https://www.econtrol.at', + ), + openingHours: [ + OpeningHours( + day: 'Tuesday', + label: '08:00', + order: 1, + from: '08:00', + to: '18:00', + ), + ], + offerInformation: OfferInformation( + service: true, + selfService: true, + unattended: true, + ), + paymentMethods: PaymentMethods( + cash: true, + debitCard: true, + creditCard: false, + others: '', + ), + paymentArrangements: PaymentArrangements( + cooperative: false, + clubCard: true, + ), + position: 1, + open: true, + distance: 0.5, + prices: [Prices(fuelType: 'DIE', amount: 1.445, label: 'Diesel')], + ), + ]; + // REST Service... URL + String apiUrl = 'https://api.e-control.at/sprit/1.0/search/gas-stations/by-address?latitude=$latitude&longitude=$longitude&fuelType=$fuelType&includeClosed=false'; + try { + var response = await http.get(Uri.parse(apiUrl)); + if (response.statusCode == 200) { + eControlData.clear(); // Clear existing data before adding new results + // Parse the response and update eControlData + print('E-Control API response: ${response.body}'); + eControlData = (response.body as List).map((json) => EControlModel.fromJson(json)).toList(); + print('E-Control data parsed successfully: ${eControlData.length} stations found'); + } + } catch (e) { + print('Error fetching E-Control data: $e'); + } + } +}