pre final ad services and correct call the services async
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_tank_web_app/services/geolocation_service.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import '../models/locationiq_model.dart';
|
||||
@@ -62,43 +63,26 @@ class EditController extends GetxController {
|
||||
}
|
||||
|
||||
Future<void> _requestLocationIQ() async {
|
||||
bool serviceEnabled;
|
||||
LocationPermission permission;
|
||||
|
||||
var geolocationService = GeolocationService();
|
||||
var locationIQService = LocationIQService();
|
||||
isLoadingLocation.value = true;
|
||||
try {
|
||||
isLoadingLocation.value = true;
|
||||
await geolocationService.getCurrentLocation();
|
||||
if (geolocationService.hasLocation) {
|
||||
print(
|
||||
'Aktuelle Position: ${geolocationService.latitude}, ${geolocationService.longitude}',
|
||||
);
|
||||
await locationIQService.fetchLocationIQ(
|
||||
geolocationService.latitude,
|
||||
geolocationService.longitude,
|
||||
);
|
||||
|
||||
// 1. Prüfen, ob Standortdienste aktiviert sind
|
||||
serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
return Future.error('Standortdienste sind deaktiviert.');
|
||||
currentLocationIQ = locationIQService.locationIQ;
|
||||
locationController.text =
|
||||
currentLocationIQ?.address?.shortAddress ?? '';
|
||||
} else {
|
||||
throw Exception('Standort nicht verfügbar');
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
print('📍 Verwende LocationIQ für Geocoding...');
|
||||
final LocationIQService locationIQService = LocationIQService();
|
||||
await locationIQService.fetchLocationIQ(lat, lon);
|
||||
currentLocationIQ = locationIQService.locationIQ;
|
||||
locationController.text = currentLocationIQ?.address?.shortAddress ?? '';
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
"Fehler",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../models/econtrol_model.dart';
|
||||
import '../services/geolocation_service.dart';
|
||||
import '../services/econtrol_service.dart';
|
||||
|
||||
class GasstationsController extends GetxController {
|
||||
@@ -23,59 +22,19 @@ class GasstationsController extends GetxController {
|
||||
|
||||
Future<void> _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,
|
||||
var gelocationService = GeolocationService();
|
||||
var eControlService = EControlService();
|
||||
// check if location is available
|
||||
await gelocationService.getCurrentLocation();
|
||||
if (gelocationService.hasLocation) {
|
||||
var listResult = await eControlService.getEControlData(
|
||||
gelocationService.latitude,
|
||||
gelocationService.longitude,
|
||||
'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;
|
||||
eControlData.value = listResult
|
||||
.map((json) => EControlModel.fromJson(json))
|
||||
.toList();
|
||||
}
|
||||
isLoading.value = false;
|
||||
update();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../controller/gasstations_controller.dart';
|
||||
import '../widgets/gasstation_card_widget.dart';
|
||||
|
||||
class GasstationsPage extends GetView<GasstationsController> {
|
||||
static const String namedRoute = '/gasstations-page';
|
||||
@@ -9,43 +10,161 @@ class GasstationsPage extends GetView<GasstationsController> {
|
||||
@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]!,
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.blueGrey[800],
|
||||
foregroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
title: const Row(
|
||||
children: [
|
||||
Icon(Icons.local_gas_station, size: 28),
|
||||
SizedBox(width: 12),
|
||||
Text(
|
||||
'Tankstellen',
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 22),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Colors.blueGrey[800]!,
|
||||
Colors.blueGrey[600]!,
|
||||
Colors.blueGrey[400]!,
|
||||
Colors.blueGrey[200]!,
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Obx(() {
|
||||
if (staCtrl.isLoading.value) {
|
||||
return const CircularProgressIndicator();
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
||||
strokeWidth: 3,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'Lade Tankstellen...',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else if (staCtrl.eControlData.isEmpty) {
|
||||
return const Text('No gas stations found.');
|
||||
return Center(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(24),
|
||||
padding: const EdgeInsets.all(32),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.search_off,
|
||||
size: 64,
|
||||
color: Colors.blueGrey[300],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Keine Tankstellen gefunden',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blueGrey[800],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Bitte überprüfen Sie Ihre Standortfreigabe',
|
||||
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
} 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'),
|
||||
);
|
||||
},
|
||||
return Column(
|
||||
children: [
|
||||
// Info Header
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.95),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.info_outline,
|
||||
color: Colors.blueGrey[700],
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'Top 5 von ${staCtrl.eControlData.length} Tankstellen',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.blueGrey[800],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// List
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
itemCount: staCtrl.eControlData.length > 5
|
||||
? 5
|
||||
: staCtrl.eControlData.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GasStationCard(
|
||||
station: staCtrl.eControlData[index],
|
||||
index: index,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -1,70 +1,17 @@
|
||||
|
||||
|
||||
import '../models/econtrol_model.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class EControlService {
|
||||
late List<EControlModel> eControlData;
|
||||
|
||||
Future<void> 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')],
|
||||
),
|
||||
];
|
||||
Future<List<dynamic>> getEControlData(
|
||||
double latitude,
|
||||
double longitude,
|
||||
String fuelType,
|
||||
) async {
|
||||
// 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');
|
||||
}
|
||||
String apiUrl =
|
||||
'https://api.e-control.at/sprit/1.0/search/gas-stations/by-address?latitude=$latitude&longitude=$longitude&fuelType=$fuelType&includeClosed=false';
|
||||
var response = await http.get(Uri.parse(apiUrl));
|
||||
print('${response.statusCode}');
|
||||
return jsonDecode(response.body);
|
||||
}
|
||||
}
|
||||
|
||||
54
lib/services/geolocation_service.dart
Normal file
54
lib/services/geolocation_service.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
|
||||
class GeolocationService {
|
||||
late double latitude;
|
||||
late double longitude;
|
||||
late bool hasLocation;
|
||||
|
||||
|
||||
|
||||
Future<void> getCurrentLocation() async {
|
||||
|
||||
bool serviceEnabled = false;
|
||||
LocationPermission permission;
|
||||
|
||||
try {
|
||||
// 1. Prüfen, ob Standortdienste aktiviert sind
|
||||
serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
return Future.error('Standortdienste sind deaktiviert.');
|
||||
}
|
||||
|
||||
hasLocation = serviceEnabled;
|
||||
|
||||
// 2. Berechtigungen prüfen
|
||||
permission = await Geolocator.checkPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
permission = await Geolocator.requestPermission();
|
||||
hasLocation = true;
|
||||
if (permission == LocationPermission.denied) {
|
||||
hasLocation = false;
|
||||
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
|
||||
latitude = position.latitude;
|
||||
longitude = position.longitude;
|
||||
if(latitude > 0 && longitude > 0) {
|
||||
hasLocation = true;
|
||||
}
|
||||
} catch (e) {
|
||||
print("Fehler beim Abrufen des Standorts: $e");
|
||||
hasLocation = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,32 +11,6 @@ class LocationIQService {
|
||||
|
||||
Future<void> fetchLocationIQ(double lat, double lon) async {
|
||||
// https://eu1.locationiq.com/v1/reverse?key=$locationIQKey&lat=47.93875449671056&lon=13.762706553431048&format=json
|
||||
// Simulierte Antwort (für Testzwecke)
|
||||
locationIQ = LocationIQ(
|
||||
placeId: '12345',
|
||||
licence: 'Data © OpenStreetMap contributors',
|
||||
osmType: 'node',
|
||||
osmId: '67890',
|
||||
lat: lat.toString(),
|
||||
lon: lon.toString(),
|
||||
displayName: 'Test Location',
|
||||
address: Address(
|
||||
houseNumber: '123',
|
||||
road: 'Test Street',
|
||||
village: 'Test Village',
|
||||
county: 'Test County',
|
||||
state: 'Test State',
|
||||
postcode: '12345',
|
||||
country: 'Test Country',
|
||||
countryCode: 'TC',
|
||||
),
|
||||
boundingbox: [
|
||||
'47.93875449671056',
|
||||
'47.93875449671056',
|
||||
'13.762706553431048',
|
||||
'13.762706553431048',
|
||||
],
|
||||
);
|
||||
|
||||
// Http Request
|
||||
var httpClient = http.Client();
|
||||
|
||||
235
lib/widgets/gasstation_card_widget.dart
Normal file
235
lib/widgets/gasstation_card_widget.dart
Normal file
@@ -0,0 +1,235 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/econtrol_model.dart';
|
||||
|
||||
class GasStationCard extends StatelessWidget {
|
||||
final EControlModel station;
|
||||
final int index;
|
||||
|
||||
const GasStationCard({super.key, required this.station, required this.index});
|
||||
|
||||
Color _getPriceColor(double? price) {
|
||||
if (price == null) return Colors.grey;
|
||||
if (price < 1.50) return Colors.green;
|
||||
if (price < 1.70) return Colors.orange;
|
||||
return Colors.red;
|
||||
}
|
||||
|
||||
String _formatDistance(double? distance) {
|
||||
if (distance == null) return 'N/A';
|
||||
if (distance < 1) {
|
||||
return '${(distance * 1000).toStringAsFixed(0)} m';
|
||||
} else {
|
||||
return '${distance.toStringAsFixed(2)} km';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final price = station.prices?.isNotEmpty == true
|
||||
? station.prices!.first.amount
|
||||
: null;
|
||||
final priceLabel = station.prices?.isNotEmpty == true
|
||||
? station.prices!.first.label
|
||||
: '';
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
elevation: 4,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [Colors.white, Colors.grey[50]!],
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header Row with Position and Status
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blueGrey[700],
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Text(
|
||||
'#${index + 1}',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: station.open == true
|
||||
? Colors.green[400]
|
||||
: Colors.red[400],
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
station.open == true
|
||||
? Icons.check_circle
|
||||
: Icons.cancel,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
station.open == true ? 'Geöffnet' : 'Geschlossen',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Station Name
|
||||
Text(
|
||||
station.name ?? 'Unbekannte Tankstelle',
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
// Address
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.location_on,
|
||||
size: 16,
|
||||
color: Colors.blueGrey[600],
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'${station.location?.address ?? ''}, '
|
||||
'${station.location?.postalCode ?? ''} '
|
||||
'${station.location?.city ?? ''}',
|
||||
style: TextStyle(fontSize: 14, color: Colors.grey[700]),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Price and Distance Row
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
// Price
|
||||
if (price != null)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: _getPriceColor(price).withAlpha(50),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: _getPriceColor(price),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.local_gas_station,
|
||||
color: _getPriceColor(price),
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'€ ${price.toStringAsFixed(3)}',
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: _getPriceColor(price),
|
||||
),
|
||||
),
|
||||
if (priceLabel?.isNotEmpty == true)
|
||||
Text(
|
||||
priceLabel!,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Distance
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue[50],
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.navigation,
|
||||
color: Colors.blue[700],
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
_formatDistance(station.distance),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue[700],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user