Ambulance order screens and geocoding request added
parent
5aef8d67de
commit
1ca39e1332
@ -0,0 +1,4 @@
|
||||
<svg width="10" height="13" viewBox="0 0 10 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 2.85449C3.79188 2.85449 2.8125 3.83387 2.8125 5.04199C2.8125 6.25011 3.79188 7.22949 5 7.22949C6.20812 7.22949 7.1875 6.25011 7.1875 5.04199C7.1875 3.83387 6.20812 2.85449 5 2.85449ZM3.6875 5.04199C3.6875 4.31712 4.27513 3.72949 5 3.72949C5.72487 3.72949 6.3125 4.31712 6.3125 5.04199C6.3125 5.76687 5.72487 6.35449 5 6.35449C4.27513 6.35449 3.6875 5.76687 3.6875 5.04199Z" fill="#ED1C2B"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 0.229492C2.38798 0.229492 0.1875 2.42783 0.1875 5.09268C0.1875 7.8228 2.43772 9.64709 4.31579 10.8329L4.32334 10.8377L4.33107 10.8422C4.5346 10.9593 4.76514 11.0212 5 11.0212C5.23486 11.0212 5.4654 10.9593 5.66893 10.8422L5.67567 10.8383L5.68227 10.8342C7.56769 9.65737 9.8125 7.81358 9.8125 5.09268C9.8125 2.42783 7.61202 0.229492 5 0.229492ZM1.0625 5.09268C1.0625 2.90553 2.87676 1.10449 5 1.10449C7.12324 1.10449 8.9375 2.90553 8.9375 5.09268C8.9375 7.29808 7.10717 8.91207 5.22662 10.0871C5.15694 10.1259 5.079 10.1462 5 10.1462C4.92132 10.1462 4.84369 10.1261 4.77422 10.0876C2.89372 8.89884 1.0625 7.30546 1.0625 5.09268Z" fill="#ED1C2B"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,4 @@
|
||||
enum AmbulanceCallingPlace{
|
||||
FROM_HOSPITAL,
|
||||
TO_HOSPITAL
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
enum AmbulanceDirection{
|
||||
ONE_WAY, TWO_WAY
|
||||
}
|
||||
@ -0,0 +1,205 @@
|
||||
|
||||
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/PatientERTransportationMethod.dart' show PatientERTransportationMethod;
|
||||
|
||||
class PatientER_RC {
|
||||
double? versionID;
|
||||
int? channel;
|
||||
int? languageID;
|
||||
String? iPAdress;
|
||||
String? generalid;
|
||||
bool? patientOutSA;
|
||||
String? sessionID;
|
||||
bool? isDentalAllowedBackend;
|
||||
int? deviceTypeID;
|
||||
int? patientID;
|
||||
String? tokenID;
|
||||
int? patientTypeID;
|
||||
int? patientType;
|
||||
int? orderServiceID;
|
||||
String? patientIdentificationID;
|
||||
dynamic patientOutSa;
|
||||
int? projectID;
|
||||
int? lineItemNo;
|
||||
TransportationDetails? transportationDetails;
|
||||
PatientERTransportationMethod? patientERTransportationMethod;
|
||||
|
||||
PatientER_RC(
|
||||
{this.versionID,
|
||||
this.channel,
|
||||
this.languageID,
|
||||
this.iPAdress,
|
||||
this.generalid,
|
||||
this.patientOutSA,
|
||||
this.sessionID,
|
||||
this.isDentalAllowedBackend,
|
||||
this.deviceTypeID,
|
||||
this.patientID,
|
||||
this.tokenID,
|
||||
this.patientTypeID,
|
||||
this.patientType,
|
||||
this.orderServiceID,
|
||||
this.patientIdentificationID,
|
||||
this.patientOutSa,
|
||||
this.projectID,
|
||||
this.lineItemNo,
|
||||
this.transportationDetails});
|
||||
|
||||
PatientER_RC.fromJson(Map<String, dynamic> json) {
|
||||
versionID = json['VersionID'];
|
||||
channel = json['Channel'];
|
||||
languageID = json['LanguageID'];
|
||||
iPAdress = json['IPAdress'];
|
||||
generalid = json['generalid'];
|
||||
patientOutSA = json['PatientOutSA'];
|
||||
sessionID = json['SessionID'];
|
||||
isDentalAllowedBackend = json['isDentalAllowedBackend'];
|
||||
deviceTypeID = json['DeviceTypeID'];
|
||||
patientID = json['PatientID'];
|
||||
tokenID = json['TokenID'];
|
||||
patientTypeID = json['PatientTypeID'];
|
||||
patientType = json['PatientType'];
|
||||
orderServiceID = json['OrderServiceID'];
|
||||
patientIdentificationID = json['PatientIdentificationID'];
|
||||
patientOutSa = json['patientOutSa'];
|
||||
projectID = json['projectID'];
|
||||
lineItemNo = json['lineItemNo'];
|
||||
transportationDetails = json['transportationDetails'] != null
|
||||
? new TransportationDetails.fromJson(json['transportationDetails'])
|
||||
: null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['VersionID'] = this.versionID;
|
||||
data['Channel'] = this.channel;
|
||||
data['LanguageID'] = this.languageID;
|
||||
data['IPAdress'] = this.iPAdress;
|
||||
data['generalid'] = this.generalid;
|
||||
data['PatientOutSA'] = this.patientOutSA;
|
||||
data['SessionID'] = this.sessionID;
|
||||
data['isDentalAllowedBackend'] = this.isDentalAllowedBackend;
|
||||
data['DeviceTypeID'] = this.deviceTypeID;
|
||||
data['PatientID'] = this.patientID;
|
||||
data['TokenID'] = this.tokenID;
|
||||
data['PatientTypeID'] = this.patientTypeID;
|
||||
data['PatientType'] = this.patientType;
|
||||
data['OrderServiceID'] = this.orderServiceID;
|
||||
data['PatientIdentificationID'] = this.patientIdentificationID;
|
||||
data['patientOutSa'] = this.patientOutSa;
|
||||
data['projectID'] = this.projectID;
|
||||
data['lineItemNo'] = this.lineItemNo;
|
||||
if (this.transportationDetails != null) {
|
||||
data['transportationDetails'] = this.transportationDetails!.toJson();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class TransportationDetails {
|
||||
int? direction;
|
||||
int? haveAppointment;
|
||||
int? tripType;
|
||||
int? pickupUrgency;
|
||||
int? pickupSpot;
|
||||
String? pickupDateTime;
|
||||
String? transportationType;
|
||||
int? ambulate;
|
||||
String? ambulateTitle;
|
||||
String? notes;
|
||||
int? requesterFileNo;
|
||||
String? requesterMobileNo;
|
||||
bool? requesterIsOutSA;
|
||||
String? pickupLocationName;
|
||||
String? dropoffLocationName;
|
||||
String? pickupLatitude;
|
||||
String? pickupLongitude;
|
||||
String? dropoffLatitude;
|
||||
String? dropoffLongitude;
|
||||
String? appointmentNo;
|
||||
String? appointmentClinicName;
|
||||
String? appointmentDoctorName;
|
||||
String? appointmentBranch;
|
||||
String? appointmentTime;
|
||||
|
||||
TransportationDetails(
|
||||
{this.direction,
|
||||
this.haveAppointment,
|
||||
this.tripType,
|
||||
this.pickupUrgency,
|
||||
this.pickupSpot,
|
||||
this.pickupDateTime,
|
||||
this.transportationType,
|
||||
this.ambulate,
|
||||
this.ambulateTitle,
|
||||
this.notes,
|
||||
this.requesterFileNo,
|
||||
this.requesterMobileNo,
|
||||
this.requesterIsOutSA,
|
||||
this.pickupLocationName,
|
||||
this.dropoffLocationName,
|
||||
this.pickupLatitude,
|
||||
this.pickupLongitude,
|
||||
this.dropoffLatitude,
|
||||
this.dropoffLongitude,
|
||||
this.appointmentNo,
|
||||
this.appointmentClinicName,
|
||||
this.appointmentDoctorName,
|
||||
this.appointmentBranch,
|
||||
this.appointmentTime});
|
||||
|
||||
TransportationDetails.fromJson(Map<String, dynamic> json) {
|
||||
direction = json['direction'];
|
||||
haveAppointment = json['haveAppointment'];
|
||||
tripType = json['tripType'];
|
||||
pickupUrgency = json['pickupUrgency'];
|
||||
pickupSpot = json['pickupSpot'];
|
||||
pickupDateTime = json['pickupDateTime'];
|
||||
transportationType = json['transportationType'];
|
||||
ambulate = json['ambulate'];
|
||||
ambulateTitle = "";
|
||||
notes = json['notes'];
|
||||
requesterFileNo = json['requesterFileNo'];
|
||||
requesterMobileNo = json['requesterMobileNo'];
|
||||
requesterIsOutSA = json['requesterIsOutSA'];
|
||||
pickupLocationName = json['pickupLocationName'];
|
||||
dropoffLocationName = json['dropoffLocationName'];
|
||||
pickupLatitude = json['pickup_Latitude'];
|
||||
pickupLongitude = json['pickup_Longitude'];
|
||||
dropoffLatitude = json['dropoff_Latitude'];
|
||||
dropoffLongitude = json['dropoff_Longitude'];
|
||||
appointmentNo = json['appointmentNo'];
|
||||
appointmentClinicName = json['appointmentClinicName'];
|
||||
appointmentDoctorName = json['appointmentDoctorName'];
|
||||
appointmentBranch = json['appointmentBranch'];
|
||||
appointmentTime = json['appointmentTime'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['direction'] = this.direction;
|
||||
data['haveAppointment'] = this.haveAppointment;
|
||||
data['tripType'] = this.tripType;
|
||||
data['pickupUrgency'] = this.pickupUrgency;
|
||||
data['pickupSpot'] = this.pickupSpot;
|
||||
data['pickupDateTime'] = this.pickupDateTime;
|
||||
data['transportationType'] = this.transportationType;
|
||||
data['ambulate'] = this.ambulate;
|
||||
data['ambulateTitle'] = this.ambulateTitle;
|
||||
data['notes'] = this.notes;
|
||||
data['requesterFileNo'] = this.requesterFileNo;
|
||||
data['requesterMobileNo'] = this.requesterMobileNo;
|
||||
data['requesterIsOutSA'] = this.requesterIsOutSA;
|
||||
data['pickupLocationName'] = this.pickupLocationName;
|
||||
data['dropoffLocationName'] = this.dropoffLocationName;
|
||||
data['pickup_Latitude'] = this.pickupLatitude;
|
||||
data['pickup_Longitude'] = this.pickupLongitude;
|
||||
data['dropoff_Latitude'] = this.dropoffLatitude;
|
||||
data['dropoff_Longitude'] = this.dropoffLongitude;
|
||||
data['appointmentNo'] = this.appointmentNo;
|
||||
data['appointmentClinicName'] = this.appointmentClinicName;
|
||||
data['appointmentDoctorName'] = this.appointmentDoctorName;
|
||||
data['appointmentBranch'] = this.appointmentBranch;
|
||||
data['appointmentTime'] = this.appointmentTime;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
class PatientERTransportationMethod {
|
||||
int? iD;
|
||||
String? serviceID;
|
||||
int? orderServiceID;
|
||||
String? text;
|
||||
String? textN;
|
||||
dynamic price;
|
||||
dynamic priceVAT;
|
||||
dynamic priceTotal;
|
||||
bool? isEnabled;
|
||||
int? orderId;
|
||||
int? quantity;
|
||||
|
||||
PatientERTransportationMethod(
|
||||
{this.iD,
|
||||
this.serviceID,
|
||||
this.orderServiceID,
|
||||
this.text,
|
||||
this.textN,
|
||||
this.price,
|
||||
this.priceVAT,
|
||||
this.priceTotal,
|
||||
this.isEnabled,
|
||||
this.orderId,
|
||||
this.quantity});
|
||||
|
||||
PatientERTransportationMethod.fromJson(Map<String, dynamic> json) {
|
||||
iD = json['ID'];
|
||||
serviceID = json['ServiceID'];
|
||||
orderServiceID = json['OrderServiceID'];
|
||||
text = json['Text'];
|
||||
textN = json['TextN'];
|
||||
price = json['Price'];
|
||||
priceVAT = json['PriceVAT'];
|
||||
priceTotal = json['PriceTotal'];
|
||||
isEnabled = json['IsEnabled'];
|
||||
orderId = json['OrderId'];
|
||||
quantity = json['Quantity'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['ID'] = this.iD;
|
||||
data['ServiceID'] = this.serviceID;
|
||||
data['OrderServiceID'] = this.orderServiceID;
|
||||
data['Text'] = this.text;
|
||||
data['TextN'] = this.textN;
|
||||
data['Price'] = this.price;
|
||||
data['PriceVAT'] = this.priceVAT;
|
||||
data['PriceTotal'] = this.priceTotal;
|
||||
data['IsEnabled'] = this.isEnabled;
|
||||
data['OrderId'] = this.orderId;
|
||||
data['Quantity'] = this.quantity;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
class GeocodeResponse {
|
||||
final List<GeocodeResult> results;
|
||||
final String status;
|
||||
|
||||
GeocodeResponse({
|
||||
required this.results,
|
||||
required this.status,
|
||||
});
|
||||
|
||||
factory GeocodeResponse.fromJson(Map<String, dynamic> json) {
|
||||
final resultsList = (json['results'] as List<dynamic>? ?? [])
|
||||
.map((e) => GeocodeResult.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
|
||||
return GeocodeResponse(
|
||||
results: resultsList,
|
||||
status: json['status'] ?? '',
|
||||
);
|
||||
}
|
||||
@override
|
||||
String toString() {
|
||||
return 'GeocodeResponse(status: $status, results: [${results.map((r) => r.toString()).join(', ')}])';
|
||||
}
|
||||
}
|
||||
|
||||
class GeocodeResult {
|
||||
final String formattedAddress;
|
||||
final Geometry geometry;
|
||||
final String placeId;
|
||||
|
||||
GeocodeResult({
|
||||
required this.formattedAddress,
|
||||
required this.geometry,
|
||||
required this.placeId,
|
||||
});
|
||||
|
||||
factory GeocodeResult.fromJson(Map<String, dynamic> json) {
|
||||
return GeocodeResult(
|
||||
formattedAddress: json['formatted_address'] ?? '',
|
||||
geometry: Geometry.fromJson(json['geometry']),
|
||||
placeId: json['place_id'] ?? '',
|
||||
);
|
||||
}
|
||||
@override
|
||||
String toString() {
|
||||
return 'GeocodeResult(formattedAddress: $formattedAddress, placeId: $placeId, geometry: ${geometry.toString()})';
|
||||
}
|
||||
}
|
||||
|
||||
class Geometry {
|
||||
final Location location;
|
||||
|
||||
Geometry({required this.location});
|
||||
|
||||
factory Geometry.fromJson(Map<String, dynamic> json) {
|
||||
return Geometry(
|
||||
location: Location.fromJson(json['location']),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'Geometry(location: ${location.toString()})';
|
||||
}
|
||||
|
||||
class Location {
|
||||
final double lat;
|
||||
final double lng;
|
||||
|
||||
Location({required this.lat, required this.lng});
|
||||
|
||||
factory Location.fromJson(Map<String, dynamic> json) {
|
||||
return Location(
|
||||
lat: (json['lat'] as num).toDouble(),
|
||||
lng: (json['lng'] as num).toDouble(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'Location(lat: $lat, lng: $lng)';
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
class PlaceDetails {
|
||||
final double lat;
|
||||
final double lng;
|
||||
|
||||
PlaceDetails({required this.lat, required this.lng});
|
||||
|
||||
factory PlaceDetails.fromJson(Map<String, dynamic> json) {
|
||||
final loc = json['result']['geometry']['location'];
|
||||
return PlaceDetails(
|
||||
lat: (loc['lat'] as num).toDouble(),
|
||||
lng: (loc['lng'] as num).toDouble(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
class PlacePrediction {
|
||||
final String description;
|
||||
final String placeID;
|
||||
PlacePrediction({required this.description, required this.placeID});
|
||||
factory PlacePrediction.fromJson(Map<String, dynamic> json) {
|
||||
return PlacePrediction(
|
||||
description: json['description'] ?? '',
|
||||
placeID: json['place_id'] ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,153 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:hmg_patient_app_new/core/api/api_client.dart';
|
||||
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
|
||||
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
|
||||
import 'package:hmg_patient_app_new/features/location/GeocodeResponse.dart';
|
||||
import 'package:hmg_patient_app_new/features/location/PlaceDetails.dart';
|
||||
|
||||
import '../../core/api_consts.dart';
|
||||
import 'PlacePrediction.dart';
|
||||
|
||||
abstract class LocationRepo {
|
||||
Future<Either<Failure, GenericApiModel<List<PlacePrediction>>>>
|
||||
getPlacePredictionsAsInput(String input);
|
||||
|
||||
Future<Either<Failure, GenericApiModel<PlaceDetails>>>
|
||||
getPlaceDetailsOfSelectedPrediction(String placeId);
|
||||
|
||||
Future<Either<Failure, GenericApiModel<GeocodeResponse>>>
|
||||
getGeoCodeFromLatLng(double lat, double lng);
|
||||
}
|
||||
|
||||
class LocationRepoImpl implements LocationRepo {
|
||||
final ApiClient apiClient;
|
||||
|
||||
LocationRepoImpl({required this.apiClient});
|
||||
|
||||
@override
|
||||
Future<Either<Failure, GenericApiModel<List<PlacePrediction>>>> getPlacePredictionsAsInput(
|
||||
String input) async {
|
||||
final url = Uri.parse(
|
||||
'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$input®ion=SA&key=$GOOGLE_API_KEY',
|
||||
);
|
||||
|
||||
GenericApiModel<List<PlacePrediction>>? apiResponse;
|
||||
Failure? failure;
|
||||
|
||||
try {
|
||||
await apiClient.get(
|
||||
url.toString(),
|
||||
isExternal: true,
|
||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
||||
failure = failureType;
|
||||
},
|
||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
||||
try {
|
||||
final list = response['predictions'];
|
||||
final predictionsList = list
|
||||
.map((item) =>
|
||||
PlacePrediction.fromJson(item as Map<String, dynamic>))
|
||||
.toList()
|
||||
.cast<PlacePrediction>();
|
||||
apiResponse = GenericApiModel<List<PlacePrediction>>(
|
||||
messageStatus: messageStatus,
|
||||
statusCode: statusCode,
|
||||
errorMessage: null,
|
||||
data: predictionsList,
|
||||
);
|
||||
} catch (e) {
|
||||
failure = DataParsingFailure(e.toString());
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (failure != null) return Left(failure!);
|
||||
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
|
||||
return Right(apiResponse!);
|
||||
} catch (e) {
|
||||
return Left(UnknownFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, GenericApiModel<GeocodeResponse>>> getGeoCodeFromLatLng(double lat, double lng) async {
|
||||
final url = Uri.parse(
|
||||
'https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=$GOOGLE_API_KEY',
|
||||
);
|
||||
|
||||
|
||||
GenericApiModel<GeocodeResponse>? apiResponse;
|
||||
Failure? failure;
|
||||
|
||||
try {
|
||||
await apiClient.get(
|
||||
url.toString(),
|
||||
isExternal: true,
|
||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
||||
failure = failureType;
|
||||
},
|
||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
||||
try {
|
||||
final predictionsList = GeocodeResponse.fromJson(response);
|
||||
apiResponse = GenericApiModel<GeocodeResponse>(
|
||||
messageStatus: messageStatus,
|
||||
statusCode: statusCode,
|
||||
errorMessage: null,
|
||||
data: predictionsList,
|
||||
);
|
||||
} catch (e) {
|
||||
failure = DataParsingFailure(e.toString());
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (failure != null) return Left(failure!);
|
||||
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
|
||||
return Right(apiResponse!);
|
||||
} catch (e) {
|
||||
return Left(UnknownFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, GenericApiModel<PlaceDetails>>> getPlaceDetailsOfSelectedPrediction(String placeId) async {
|
||||
|
||||
|
||||
final url = Uri.parse(
|
||||
'https://maps.googleapis.com/maps/api/place/details/json'
|
||||
'?place_id=$placeId&fields=geometry&key=$GOOGLE_API_KEY',
|
||||
);
|
||||
|
||||
GenericApiModel<PlaceDetails>? apiResponse;
|
||||
Failure? failure;
|
||||
|
||||
try {
|
||||
await apiClient.get(
|
||||
url.toString(),
|
||||
isExternal: true,
|
||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
||||
failure = failureType;
|
||||
},
|
||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
||||
try {
|
||||
final predictionsList = PlaceDetails.fromJson(response);
|
||||
apiResponse = GenericApiModel<PlaceDetails>(
|
||||
messageStatus: messageStatus,
|
||||
statusCode: statusCode,
|
||||
errorMessage: null,
|
||||
data: predictionsList,
|
||||
);
|
||||
} catch (e) {
|
||||
failure = DataParsingFailure(e.toString());
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (failure != null) return Left(failure!);
|
||||
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
|
||||
return Right(apiResponse!);
|
||||
} catch (e) {
|
||||
return Left(UnknownFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,120 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart' show ChangeNotifier;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_maps_flutter_platform_interface/src/types/camera.dart';
|
||||
import 'package:hmg_patient_app_new/features/location/GeocodeResponse.dart';
|
||||
import 'package:hmg_patient_app_new/features/location/PlaceDetails.dart';
|
||||
import 'package:hmg_patient_app_new/features/location/location_repo.dart';
|
||||
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
||||
import 'package:huawei_map/huawei_map.dart' as HMSCameraServices;
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart' as GMSMapServices;
|
||||
|
||||
|
||||
|
||||
import 'PlacePrediction.dart';
|
||||
|
||||
class LocationViewModel extends ChangeNotifier {
|
||||
final LocationRepo locationRepo;
|
||||
final ErrorHandlerService errorHandlerService;
|
||||
|
||||
LocationViewModel({required this.locationRepo, required this.errorHandlerService});
|
||||
|
||||
List<PlacePrediction> predictions = [];
|
||||
PlacePrediction? selectedPrediction;
|
||||
bool isPredictionLoading = false;
|
||||
GeocodeResponse? geocodeResponse;
|
||||
PlaceDetails? placeDetails;
|
||||
|
||||
Location? mapCapturedLocation;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FutureOr<void> getPlacesPrediction(String input) async {
|
||||
predictions = [];
|
||||
isPredictionLoading= true;
|
||||
final result = await locationRepo.getPlacePredictionsAsInput(input);
|
||||
result.fold(
|
||||
(failure) {
|
||||
errorHandlerService.handleError(failure: failure);
|
||||
},
|
||||
(apiModel) {
|
||||
predictions = apiModel.data??[];
|
||||
},
|
||||
);
|
||||
isPredictionLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
FutureOr<void> getPlaceEncodedData(double? lat, double? lng) async {
|
||||
geocodeResponse = null;
|
||||
final result = await locationRepo.getGeoCodeFromLatLng(lat!, lng!);
|
||||
result.fold(
|
||||
(failure) {
|
||||
errorHandlerService.handleError(failure: failure);
|
||||
},
|
||||
(apiModel) {
|
||||
print("Geocode Response: ${apiModel.data}");
|
||||
geocodeResponse = apiModel.data;
|
||||
},
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
FutureOr<void> getPlaceDetails(String placeID) async {
|
||||
placeDetails = null;
|
||||
final result = await locationRepo.getPlaceDetailsOfSelectedPrediction(placeID);
|
||||
result.fold(
|
||||
(failure) {
|
||||
errorHandlerService.handleError(failure: failure);
|
||||
},
|
||||
(apiModel) {
|
||||
placeDetails = apiModel.data;
|
||||
},
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
handleGMSMapCameraMoved(GMSMapServices.CameraPosition value) {
|
||||
mapCapturedLocation = Location(lat: value.target.latitude, lng: value.target.longitude);
|
||||
|
||||
}
|
||||
|
||||
handleHMSMapCameraMoved(HMSCameraServices.CameraPosition value) {
|
||||
mapCapturedLocation = Location(lat: value.target.lat, lng: value.target.lng);
|
||||
}
|
||||
|
||||
handleOnCameraIdle(){
|
||||
if(mapCapturedLocation != null) {
|
||||
getPlaceEncodedData(mapCapturedLocation!.lat, mapCapturedLocation!.lng);
|
||||
}
|
||||
}
|
||||
|
||||
void updateSearchQuery(String? value) {
|
||||
if(value == null || value.isEmpty){
|
||||
predictions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
getPlacesPrediction(value);
|
||||
}
|
||||
|
||||
void flushSearchPredictions() {
|
||||
predictions = [];
|
||||
mapCapturedLocation= null;
|
||||
placeDetails= null;
|
||||
geocodeResponse= null;
|
||||
selectedPrediction= null;
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
FutureOr<void> selectPlacePrediction(PlacePrediction placePrediction) async{
|
||||
selectedPrediction= placePrediction;
|
||||
await getPlaceDetails(placePrediction.placeID);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
// import 'package:flutter/cupertino.dart';
|
||||
// import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
// import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
// import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
|
||||
// import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
|
||||
// import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart';
|
||||
// import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/doctor_card.dart';
|
||||
// import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
// import 'package:provider/provider.dart';
|
||||
//
|
||||
// class AppointmentBottomSheet extends StatelessWidget{
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// // TODO: implement build
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
//
|
||||
// Widget getAppointList(EmergencyServicesViewModel viewmodel, List<PatientAppointmentHistoryResponseModel> filteredAppointmentList) {
|
||||
// return Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// ListView.separated(
|
||||
// padding: EdgeInsets.only(top: 24.h),
|
||||
// shrinkWrap: true,
|
||||
// physics: NeverScrollableScrollPhysics(),
|
||||
// itemCount: viewmodel.isMyAppointmentsLoading
|
||||
// ? 5
|
||||
// : filteredAppointmentList.isNotEmpty
|
||||
// ? filteredAppointmentList.length
|
||||
// : 1,
|
||||
// itemBuilder: (context, index) {
|
||||
// return viewmodel.isMyAppointmentsLoading
|
||||
// ? Container(
|
||||
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
|
||||
// child: DoctorCard(doctorsListResponseModel: doctorsListResponseModel, isLoading: viewmodel.isMyAppointmentsLoading, bookAppointmentsViewModel: bookAppointmentsViewModel),
|
||||
// ).paddingSymmetrical(24.h, 0.h)
|
||||
// : filteredAppointmentList.isNotEmpty
|
||||
// ? AnimationConfiguration.staggeredList(
|
||||
// position: index,
|
||||
// duration: const Duration(milliseconds: 500),
|
||||
// child: SlideAnimation(
|
||||
// verticalOffset: 100.0,
|
||||
// child: FadeInAnimation(
|
||||
// child: AnimatedContainer(
|
||||
// duration: Duration(milliseconds: 300),
|
||||
// curve: Curves.easeInOut,
|
||||
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
|
||||
// child: AppointmentCard(
|
||||
// patientAppointmentHistoryResponseModel: filteredAppointmentList[index],
|
||||
// myAppointmentsViewModel: myAppointmentsViewModel,
|
||||
// bookAppointmentsViewModel: bookAppointmentsViewModel,
|
||||
// isLoading: false,
|
||||
// isFromHomePage: false,
|
||||
// ),
|
||||
// ).paddingSymmetrical(24.h, 0.h),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// : Utils.getNoDataWidget(
|
||||
// context,
|
||||
// noDataText: "You don't have any appointments yet.".needTranslation,
|
||||
// callToActionButton: CustomButton(
|
||||
// text: LocaleKeys.bookAppo.tr(context: context),
|
||||
// onPressed: () {
|
||||
// Navigator.of(context).push(
|
||||
// CustomPageRoute(
|
||||
// page: BookAppointmentPage(),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// backgroundColor: Color(0xffFEE9EA),
|
||||
// borderColor: Color(0xffFEE9EA),
|
||||
// textColor: Color(0xffED1C2B),
|
||||
// fontSize: 14.f,
|
||||
// fontWeight: FontWeight.w500,
|
||||
// borderRadius: 12.r,
|
||||
// padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
|
||||
// height: 40.h,
|
||||
// icon: AppAssets.add_icon,
|
||||
// iconColor: AppColors.primaryRedColor,
|
||||
// ).paddingSymmetrical(48.h, 0.h),
|
||||
// );
|
||||
// },
|
||||
// separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
|
||||
// ),
|
||||
// SizedBox(height: 24.h),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
@ -0,0 +1,172 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_export.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/emergency_services/models/AmbulanceCallingPlace.dart';
|
||||
import 'package:hmg_patient_app_new/features/emergency_services/models/ambulance_direction.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../../generated/locale_keys.g.dart' show LocaleKeys;
|
||||
|
||||
class PickupLocation extends StatelessWidget {
|
||||
final VoidCallback onTap;
|
||||
const PickupLocation({super.key, required this.onTap});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
"Select Pickup Direction"
|
||||
.needTranslation
|
||||
.toText24(color: AppColors.textColor,isBold: true),
|
||||
SizedBox(
|
||||
height: 16.h,
|
||||
),
|
||||
"Select Direction"
|
||||
.needTranslation
|
||||
.toText14(color: AppColors.textColor, weight: FontWeight.w600),
|
||||
SizedBox(
|
||||
height: 12.h,
|
||||
),
|
||||
Selector<EmergencyServicesViewModel, AmbulanceCallingPlace>(
|
||||
selector: (context, viewModel) => viewModel.callingPlace,
|
||||
builder: (context, value, _) {
|
||||
return Column(
|
||||
spacing: 12.h,
|
||||
children: [
|
||||
RadioGroup<AmbulanceCallingPlace>(
|
||||
groupValue: value,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<EmergencyServicesViewModel>()
|
||||
.updateCallingPlace(value);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
spacing: 24.h,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: AmbulanceCallingPlace.TO_HOSPITAL,
|
||||
groupValue: value,
|
||||
activeColor: AppColors.primaryRedColor,
|
||||
|
||||
fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
|
||||
),
|
||||
"To Hospital"
|
||||
.needTranslation
|
||||
.toText12(color: AppColors.textColor)
|
||||
],
|
||||
).onPress((){
|
||||
context
|
||||
.read<EmergencyServicesViewModel>()
|
||||
.updateCallingPlace(AmbulanceCallingPlace.TO_HOSPITAL);
|
||||
}),
|
||||
Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: AmbulanceCallingPlace.FROM_HOSPITAL,
|
||||
activeColor: AppColors.primaryRedColor,
|
||||
|
||||
fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
|
||||
),
|
||||
"From Hospital"
|
||||
.needTranslation
|
||||
.toText12(color: AppColors.textColor)
|
||||
],
|
||||
).onPress((){
|
||||
context
|
||||
.read<EmergencyServicesViewModel>()
|
||||
.updateCallingPlace(AmbulanceCallingPlace.FROM_HOSPITAL);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: value == AmbulanceCallingPlace.TO_HOSPITAL,
|
||||
child: Selector<EmergencyServicesViewModel, AmbulanceDirection>(
|
||||
selector: (context, viewModel) =>
|
||||
viewModel.ambulanceDirection,
|
||||
builder: (context, directionValue, _) {
|
||||
return Column(
|
||||
spacing: 12.h,
|
||||
children: [
|
||||
"Select Way"
|
||||
.needTranslation
|
||||
.toText14(color: AppColors.textColor, weight: FontWeight.w600),
|
||||
RadioGroup<AmbulanceDirection>(
|
||||
groupValue: directionValue,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<EmergencyServicesViewModel>()
|
||||
.updateDirection(value);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
spacing: 24.h,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: AmbulanceDirection.ONE_WAY,
|
||||
activeColor: AppColors.primaryRedColor,
|
||||
|
||||
fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
|
||||
),
|
||||
"One Way"
|
||||
.needTranslation
|
||||
.toText12(color: AppColors.textColor)
|
||||
],
|
||||
).onPress((){
|
||||
context
|
||||
.read<EmergencyServicesViewModel>()
|
||||
.updateDirection(AmbulanceDirection.ONE_WAY);
|
||||
}),
|
||||
Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: AmbulanceDirection.TWO_WAY,
|
||||
// activeColor: AppColors.primaryRedColor,
|
||||
|
||||
fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
|
||||
),
|
||||
"Two Way"
|
||||
.needTranslation
|
||||
.toText12(color: AppColors.textColor)
|
||||
],
|
||||
).onPress((){
|
||||
context
|
||||
.read<EmergencyServicesViewModel>()
|
||||
.updateDirection(AmbulanceDirection.TWO_WAY);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
SizedBox(
|
||||
height: 16.h,
|
||||
),
|
||||
CustomButton(
|
||||
text: LocaleKeys.confirm.tr(context: context),
|
||||
onPressed: onTap,
|
||||
backgroundColor: AppColors.primaryRedColor,
|
||||
borderColor: AppColors.primaryRedColor,
|
||||
textColor: AppColors.whiteColor,
|
||||
iconColor: AppColors.whiteColor,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,118 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'
|
||||
show AnimationConfiguration, SlideAnimation, FadeInAnimation;
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_export.dart';
|
||||
import 'package:hmg_patient_app_new/core/enums.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/debouncer.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/location/GeocodeResponse.dart';
|
||||
import 'package:hmg_patient_app_new/features/location/PlacePrediction.dart';
|
||||
import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../theme/colors.dart';
|
||||
import '../../appointments/widgets/hospital_bottom_sheet/type_selection_widget.dart';
|
||||
|
||||
class LocationInputBottomSheet extends StatelessWidget {
|
||||
final Debouncer debouncer = Debouncer(milliseconds: 500);
|
||||
|
||||
LocationInputBottomSheet({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextInputWidget(
|
||||
labelText: LocaleKeys.search.tr(),
|
||||
hintText: "Search Location".needTranslation,
|
||||
controller: TextEditingController(),
|
||||
onChange: (value){
|
||||
debouncer.run(() {
|
||||
context.read<LocationViewModel>().updateSearchQuery(value);
|
||||
});
|
||||
},
|
||||
isEnable: true,
|
||||
prefix: null,
|
||||
autoFocus: false,
|
||||
isBorderAllowed: false,
|
||||
keyboardType: TextInputType.text,
|
||||
isAllowLeadingIcon: true,
|
||||
selectionType: SelectionTypeEnum.search,
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 10.h,
|
||||
horizontal: 15.h,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
Selector<LocationViewModel, List<PlacePrediction>>(
|
||||
selector: (_, vm) => vm.predictions ?? <PlacePrediction>[],
|
||||
builder: (context, predictions, _) {
|
||||
if (predictions.isEmpty) return SizedBox.shrink();
|
||||
return Expanded(
|
||||
child: ListView.separated(
|
||||
separatorBuilder: (_,__)=>SizedBox(height: 16.h,),
|
||||
itemCount: predictions.length,
|
||||
itemBuilder: (_, index) {
|
||||
final prediction = predictions[index];
|
||||
|
||||
return AnimationConfiguration.staggeredList(
|
||||
position: index,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: SlideAnimation(
|
||||
verticalOffset: 100.0,
|
||||
child: FadeInAnimation(
|
||||
child: AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
decoration: RoundedRectangleBorder()
|
||||
.toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 24.h,
|
||||
hasShadow: true),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: prediction.description.toText14(
|
||||
color: AppColors.textColor,
|
||||
weight: FontWeight.w500),
|
||||
),
|
||||
|
||||
Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon_small,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 20.h,
|
||||
height: 15.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
],
|
||||
).paddingAll(24.h),),
|
||||
),
|
||||
),
|
||||
).onPress(() async {
|
||||
await context.read<LocationViewModel>().selectPlacePrediction(prediction);
|
||||
Navigator.of(context).pop();
|
||||
var location = context.read<LocationViewModel>().placeDetails;
|
||||
if(location != null) {
|
||||
context.read<EmergencyServicesViewModel>().moveController(
|
||||
Location(lat: location.lat, lng: location.lng));
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,41 +1,63 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_export.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:huawei_map/huawei_map.dart' ;
|
||||
|
||||
class HMSMap extends StatefulWidget{
|
||||
final CameraPosition currentLocation;
|
||||
final Function(CameraPosition) onCameraMoved;
|
||||
final VoidCallback onCameraIdle;
|
||||
final MapType mapType;
|
||||
final bool compassEnabled;
|
||||
final bool myLocationEnabled;
|
||||
final bool showCenterMarker;
|
||||
final Completer<HuaweiMapController>? inputController;
|
||||
|
||||
HMSMap({super.key, required this.currentLocation ,required this.onCameraMoved, this.mapType = MapType.normal,this.compassEnabled = false, this.myLocationEnabled = true});
|
||||
HMSMap({super.key, required this.currentLocation ,required this.onCameraMoved,required this.onCameraIdle,
|
||||
this.mapType = MapType.normal,this.compassEnabled = false,this.showCenterMarker = false,
|
||||
this.myLocationEnabled = true, this.inputController});
|
||||
|
||||
@override
|
||||
State<HMSMap> createState() => _HMSMapState();
|
||||
}
|
||||
|
||||
class _HMSMapState extends State<HMSMap> {
|
||||
final Completer<HuaweiMapController> _controller = Completer<HuaweiMapController>();
|
||||
Completer<HuaweiMapController>? controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
HuaweiMapInitializer.initializeMap();
|
||||
controller = widget.inputController ?? Completer<HuaweiMapController>();
|
||||
super.initState();
|
||||
}
|
||||
// @override
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
HuaweiMap(
|
||||
mapType: widget.mapType,
|
||||
zoomControlsEnabled: false,
|
||||
myLocationEnabled: widget.myLocationEnabled,
|
||||
compassEnabled: widget.compassEnabled,
|
||||
initialCameraPosition: widget.currentLocation,
|
||||
onCameraMove: (value) => widget.onCameraMoved(value),
|
||||
onMapCreated: (HuaweiMapController controller) {
|
||||
_controller.complete(controller);
|
||||
},
|
||||
);
|
||||
Stack(
|
||||
children: [
|
||||
HuaweiMap(
|
||||
mapType: widget.mapType,
|
||||
zoomControlsEnabled: false,
|
||||
myLocationEnabled: widget.myLocationEnabled,
|
||||
myLocationButtonEnabled: false,
|
||||
compassEnabled: widget.compassEnabled,
|
||||
onCameraIdle:()=> widget.onCameraIdle(),
|
||||
initialCameraPosition: widget.currentLocation,
|
||||
onCameraMove: (value) => widget.onCameraMoved(value),
|
||||
onMapCreated: (HuaweiMapController controller) {
|
||||
this.controller?.complete(controller);
|
||||
},
|
||||
),
|
||||
Visibility(
|
||||
visible: widget.showCenterMarker,
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Utils.buildSvgWithAssets(icon: AppAssets.pin_location, width: 24.w, height: 36.h),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue