services
This commit is contained in:
@@ -1,17 +1,25 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:injector/injector.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:professional_repository/professional_repository.dart';
|
||||
import 'package:prosappco/blocs/my_user_bloc/my_user_bloc.dart';
|
||||
import 'package:prosappco/blocs/professional_list_bloc/professional_list_bloc.dart';
|
||||
import 'package:prosappco/blocs/service_bloc/service_bloc.dart';
|
||||
import 'package:prosappco/constansts.dart';
|
||||
import 'package:prosappco/screens/lists/city_list_screen.dart';
|
||||
import 'package:prosappco/screens/lists/professional_list_screen.dart';
|
||||
import 'package:prosappco/screens/user/user_service_screen.dart';
|
||||
import 'package:prosappco/screens/web/web_view_screen.dart';
|
||||
import 'package:prosappco/utils/time_of_day_extension.dart';
|
||||
import 'package:service_repository/service_repository.dart';
|
||||
import 'package:setting_repository/setting_repository.dart';
|
||||
@@ -42,13 +50,42 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
ServiceLocationPreferences? serviceLocationPreference;
|
||||
UserProfessional? profesionalSeleccionado;
|
||||
|
||||
Map<PolylineId, Polyline> polylines = {};
|
||||
|
||||
bool isClearButtonVisible = false;
|
||||
|
||||
bool isLoading = false;
|
||||
|
||||
Set<Marker> markers = {};
|
||||
BitmapDescriptor? _markerIcon;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_loadSettings();
|
||||
|
||||
getLocation();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
BitmapDescriptor.fromAssetImage(
|
||||
const ImageConfiguration(size: Size(2, 2)),
|
||||
'images/pro_marke_android.png',
|
||||
).then((icon) {
|
||||
setState(() {
|
||||
_markerIcon = icon;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
BitmapDescriptor.fromAssetImage(
|
||||
const ImageConfiguration(size: Size(1, 1)),
|
||||
'images/pro_marke.png',
|
||||
).then((icon) {
|
||||
setState(() {
|
||||
_markerIcon = icon;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _loadSettings() {
|
||||
@@ -63,115 +100,143 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<ServiceBloc>(
|
||||
create: (context) => Injector.appInstance.get<ServiceBloc>(),
|
||||
child: BlocBuilder<MyUserBloc, MyUserState>(
|
||||
child: BlocConsumer<ServiceBloc, ServiceState>(
|
||||
listener: (context, serviceState) {
|
||||
if (serviceState is CreateServiceLoading) {
|
||||
isLoading = true;
|
||||
}
|
||||
if (serviceState is CreateServiceFailure) {
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
if (serviceState is CreateServiceSuccess) {
|
||||
isLoading = false;
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return UserServiceScreen(serviceId: serviceState.serviceId);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
GoogleMap(
|
||||
myLocationEnabled: true,
|
||||
// polylines: Set<Polyline>.of(polylines.values),
|
||||
onMapCreated: (GoogleMapController controller) {
|
||||
_mapController.complete(controller);
|
||||
},
|
||||
onCameraIdle: () {
|
||||
getLocationName(
|
||||
coordenadas.latitude, coordenadas.longitude)
|
||||
.then((value) => setState(() {
|
||||
_addressController.text = value;
|
||||
}));
|
||||
},
|
||||
onCameraMove: (position) {
|
||||
if (serviceLocationPreference !=
|
||||
ServiceLocationPreferences.office) {
|
||||
coordenadas = position.target;
|
||||
}
|
||||
},
|
||||
initialCameraPosition: const CameraPosition(
|
||||
target: LatLng(7.1253900, -73.1198000),
|
||||
zoom: 16,
|
||||
),
|
||||
myLocationButtonEnabled: false,
|
||||
),
|
||||
Positioned(
|
||||
top: 10,
|
||||
left: 0,
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.white,
|
||||
shape: const CircleBorder(),
|
||||
elevation: 3,
|
||||
minimumSize: const Size(50, 50),
|
||||
return BlocBuilder<MyUserBloc, MyUserState>(
|
||||
builder: (context, myUserState) {
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
GoogleMap(
|
||||
myLocationEnabled: true,
|
||||
polylines: Set<Polyline>.of(polylines.values),
|
||||
onMapCreated: (GoogleMapController controller) {
|
||||
_mapController.complete(controller);
|
||||
},
|
||||
markers: {
|
||||
...markers,
|
||||
Marker(
|
||||
markerId: const MarkerId('currentLocation'),
|
||||
position: _currentP ?? const LatLng(0, 0),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.black,
|
||||
size: 35,
|
||||
),
|
||||
onPressed: () {
|
||||
Scaffold.of(context).openDrawer();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const Positioned(
|
||||
bottom: 30,
|
||||
right: 0,
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Icon(
|
||||
Icons.location_on,
|
||||
size: 40,
|
||||
color: Color(0xFFFF0000),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 10,
|
||||
right: 10,
|
||||
child: FloatingActionButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
Position position = await _determinePosition();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_currentP = LatLng(
|
||||
position.latitude,
|
||||
position.longitude,
|
||||
);
|
||||
});
|
||||
|
||||
_animateCameraToPosition(_currentP!);
|
||||
},
|
||||
onCameraIdle: () {
|
||||
getLocationName(
|
||||
coordenadas.latitude, coordenadas.longitude)
|
||||
.then((value) => setState(() {
|
||||
_addressController.text = value;
|
||||
}));
|
||||
},
|
||||
onCameraMove: (position) {
|
||||
if (serviceLocationPreference !=
|
||||
ServiceLocationPreferences.office) {
|
||||
coordenadas = position.target;
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).clearSnackBars();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Por favor activa la ubicacion'),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
elevation: 0,
|
||||
child: const Icon(
|
||||
Icons.gps_fixed,
|
||||
size: 30,
|
||||
},
|
||||
initialCameraPosition: const CameraPosition(
|
||||
target: LatLng(7.1253900, -73.1198000),
|
||||
zoom: 16,
|
||||
),
|
||||
myLocationButtonEnabled: false,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 10,
|
||||
left: 0,
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.white,
|
||||
shape: const CircleBorder(),
|
||||
elevation: 3,
|
||||
minimumSize: const Size(50, 50),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.black,
|
||||
size: 35,
|
||||
),
|
||||
onPressed: () {
|
||||
Scaffold.of(context).openDrawer();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const Positioned(
|
||||
bottom: 30,
|
||||
right: 0,
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Icon(
|
||||
Icons.location_on,
|
||||
size: 40,
|
||||
color: Color(0xFFFF0000),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 10,
|
||||
right: 10,
|
||||
child: FloatingActionButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
Position position = await _determinePosition();
|
||||
|
||||
setState(() {
|
||||
_currentP = LatLng(
|
||||
position.latitude,
|
||||
position.longitude,
|
||||
);
|
||||
});
|
||||
|
||||
_animateCameraToPosition(_currentP!);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).clearSnackBars();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content:
|
||||
Text('Por favor activa la ubicacion'),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
elevation: 0,
|
||||
child: const Icon(
|
||||
Icons.gps_fixed,
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
BlocListener<ServiceBloc, ServiceState>(
|
||||
listener: (context, state) {},
|
||||
child: buildBottom(context, state),
|
||||
),
|
||||
],
|
||||
),
|
||||
buildBottom(context, myUserState),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -199,6 +264,8 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
}));
|
||||
|
||||
if (datos != null) {
|
||||
polylines.clear();
|
||||
|
||||
fechaSeleccionada = datos[0];
|
||||
horaSeleccionada = datos[1];
|
||||
serviceLocationPreference = datos[2];
|
||||
@@ -220,6 +287,31 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
profesionalSeleccionado!.professionalInfo.latitude,
|
||||
profesionalSeleccionado!.professionalInfo.longitude,
|
||||
);
|
||||
|
||||
if (_currentP != null) {
|
||||
getPolylinePoints(
|
||||
_currentP!,
|
||||
LatLng(
|
||||
profesionalSeleccionado!.professionalInfo.latitude,
|
||||
profesionalSeleccionado!.professionalInfo.longitude,
|
||||
)).then(
|
||||
(coordinates) => {
|
||||
generatePolyLineFromPoints(coordinates),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
markers.add(
|
||||
Marker(
|
||||
icon: _markerIcon!,
|
||||
markerId: MarkerId(
|
||||
profesionalSeleccionado!.professionalInfo.id),
|
||||
position: LatLng(
|
||||
profesionalSeleccionado!.professionalInfo.latitude,
|
||||
profesionalSeleccionado!.professionalInfo.longitude,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {}
|
||||
|
||||
isClearButtonVisible = true;
|
||||
@@ -267,7 +359,7 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
controller: TextEditingController(
|
||||
text: horaSeleccionada == null
|
||||
? ''
|
||||
: horaSeleccionada!.format(context),
|
||||
: ScheduleEntity.getFormatTime(horaSeleccionada),
|
||||
),
|
||||
decoration: const InputDecoration(
|
||||
prefixIcon: Icon(Icons.watch_later_outlined),
|
||||
@@ -278,9 +370,9 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const TextField(
|
||||
// controller: _observacionController,
|
||||
decoration: InputDecoration(
|
||||
TextField(
|
||||
controller: _observationController,
|
||||
decoration: const InputDecoration(
|
||||
prefixIcon: Icon(Icons.message_outlined),
|
||||
hintText: 'Observaciones',
|
||||
),
|
||||
@@ -293,37 +385,39 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: () {
|
||||
if (serviceLocationPreference ==
|
||||
ServiceLocationPreferences.office) {
|
||||
context.read<ServiceBloc>().add(
|
||||
CreateService(
|
||||
professionalId:
|
||||
profesionalSeleccionado!.professionalInfo.id,
|
||||
userId: state.user!.id,
|
||||
address: profesionalSeleccionado!
|
||||
.professionalInfo.address,
|
||||
aditionalAddress: profesionalSeleccionado!
|
||||
.professionalInfo.address,
|
||||
latitude: profesionalSeleccionado!
|
||||
.professionalInfo.latitude,
|
||||
longitude: profesionalSeleccionado!
|
||||
.professionalInfo.longitude,
|
||||
day: fechaSeleccionada.toString(),
|
||||
createdAt: Timestamp.now(),
|
||||
description: _observationController.text,
|
||||
range1Hour1: horaSeleccionada!,
|
||||
range1Hour2: horaSeleccionada!.add(hour: 2),
|
||||
rate: '0',
|
||||
location: serviceLocationPreference!,
|
||||
),
|
||||
);
|
||||
} else if (serviceLocationPreference ==
|
||||
ServiceLocationPreferences.delivery) {
|
||||
} else {
|
||||
// TODO: error inesperado
|
||||
}
|
||||
},
|
||||
onPressed: isLoading
|
||||
? null
|
||||
: () {
|
||||
if (serviceLocationPreference ==
|
||||
ServiceLocationPreferences.office) {
|
||||
context.read<ServiceBloc>().add(
|
||||
CreateService(
|
||||
professionalId: profesionalSeleccionado!
|
||||
.professionalInfo.id,
|
||||
userId: state.user!.id,
|
||||
address: profesionalSeleccionado!
|
||||
.professionalInfo.address,
|
||||
aditionalAddress: profesionalSeleccionado!
|
||||
.professionalInfo.aditionalAddress,
|
||||
latitude: profesionalSeleccionado!
|
||||
.professionalInfo.latitude,
|
||||
longitude: profesionalSeleccionado!
|
||||
.professionalInfo.longitude,
|
||||
day: fechaSeleccionada.toString(),
|
||||
createdAt: Timestamp.now(),
|
||||
description: _observationController.text,
|
||||
range1Hour1: horaSeleccionada!,
|
||||
range1Hour2: horaSeleccionada!.add(hour: 2),
|
||||
rate: '0',
|
||||
location: serviceLocationPreference!,
|
||||
),
|
||||
);
|
||||
} else if (serviceLocationPreference ==
|
||||
ServiceLocationPreferences.delivery) {
|
||||
} else {
|
||||
// TODO: error inesperado
|
||||
}
|
||||
},
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
padding: const EdgeInsets.symmetric(vertical: 15),
|
||||
@@ -351,6 +445,9 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
isClearButtonVisible = false;
|
||||
_observationController.text = '';
|
||||
serviceLocationPreference = null;
|
||||
|
||||
polylines.clear();
|
||||
markers.clear();
|
||||
setState(() {});
|
||||
},
|
||||
style: FilledButton.styleFrom(
|
||||
@@ -387,6 +484,56 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<LatLng>> getPolylinePoints(
|
||||
LatLng originP, LatLng destinationP) async {
|
||||
List<LatLng> polylineCoordinates = [];
|
||||
PolylinePoints polylinePoints = PolylinePoints();
|
||||
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
|
||||
GOOGLE_MAPS_API_KEY,
|
||||
PointLatLng(originP.latitude, originP.longitude),
|
||||
PointLatLng(destinationP.latitude, destinationP.longitude),
|
||||
travelMode: TravelMode.driving,
|
||||
);
|
||||
if (result.points.isNotEmpty) {
|
||||
for (var point in result.points) {
|
||||
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
|
||||
}
|
||||
} else {
|
||||
print(result.errorMessage);
|
||||
}
|
||||
return polylineCoordinates;
|
||||
}
|
||||
|
||||
void getLocation() async {
|
||||
try {
|
||||
Position position = await _determinePosition();
|
||||
|
||||
setState(() {
|
||||
_currentP = LatLng(
|
||||
position.latitude,
|
||||
position.longitude,
|
||||
);
|
||||
});
|
||||
|
||||
_animateCameraToPosition(_currentP!);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void generatePolyLineFromPoints(List<LatLng> polylineCoordinates) async {
|
||||
PolylineId id = const PolylineId("poly");
|
||||
Polyline polyline = Polyline(
|
||||
polylineId: id,
|
||||
color: Colors.blue,
|
||||
points: polylineCoordinates,
|
||||
width: 6,
|
||||
);
|
||||
setState(() {
|
||||
polylines[id] = polyline;
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> getLocationName(double latitude, double longitude) async {
|
||||
String address;
|
||||
List<Placemark> placemarks =
|
||||
|
||||
Reference in New Issue
Block a user