Files
prosappweb/lib/src/presentation/screens/map/service.dart
T
2023-12-21 15:54:22 -05:00

1182 lines
42 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:geocoding/geocoding.dart' as geocoding;
import 'package:http/http.dart' as http;
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:intl/intl.dart';
import 'package:location/location.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:prosappco/constansts.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/network_utility.dart';
import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/models/setting_model.dart';
import 'package:prosappco/src/models/user_model.dart';
import 'package:prosappco/src/presentation/screens/professional.dart';
import 'package:prosappco/src/presentation/screens/profile/profile.dart';
import 'package:prosappco/src/presentation/screens/service_after.dart';
import 'package:prosappco/src/presentation/screens/service_type.dart';
import 'package:prosappco/src/presentation/widgets/shared/drawer_menu.dart';
import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart';
import 'package:prosappco/src/presentation/widgets/shared/warning_snackbar.dart';
import 'package:prosappco/src/providers/user_provider.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
class ServiceScreen extends StatefulWidget {
const ServiceScreen({super.key});
@override
State<ServiceScreen> createState() => _ServiceScreenState();
}
class _ServiceScreenState extends State<ServiceScreen> {
late String appVersion;
final Uri _url = Uri.parse(
'https://play.google.com/store/apps/details?id=com.prosapp.prosapp');
final Uri _urlIos =
Uri.parse('https://apps.apple.com/co/app/prosapp/id6469028900');
final Location _locationController = Location();
final Completer<GoogleMapController> _mapController =
Completer<GoogleMapController>();
static const LatLng _pGooglePlex = LatLng(7.080486, -73.087447);
LatLng? _currentP;
Map<PolylineId, Polyline> polylines = {};
final TextEditingController _locacionController = TextEditingController();
final TextEditingController _ubicationController = TextEditingController();
final TextEditingController _profesionalController = TextEditingController();
final TextEditingController _serviceTypeController = TextEditingController();
final TextEditingController _observacionController = TextEditingController();
final DateTime now = DateTime.now();
EventoService eventoService = EventoService();
String _serviceType = 'Servicio';
String ubicacion = '';
String professionalId = '';
String professionalToken = '';
String professionalAddress = '';
String professionalUbicacion = '';
int? professionalTarifa;
double? professionalLatitude;
double? professionalLongitude;
DateTime? _selectedDate;
String _ciudad = '...';
TimeOfDay? _selectedTime;
final DateFormat formatter = DateFormat('dd/MM/yyyy');
dynamic coordinates;
Set<Marker> markers = {};
BitmapDescriptor? _markerIcon;
List<dynamic> _placesList = [];
String _coordsOfCity = '0.0,0.0';
final uid = AuthenticationRepository.instance.getCurrentUserUid();
String? settings;
late final FirebaseAuth _auth;
final _nameController = TextEditingController();
@override
void initState() {
super.initState();
_getAppVersion();
getLocationUpdates();
_auth = FirebaseAuth.instance;
final currentUser = _auth.currentUser;
if (currentUser != null && currentUser.displayName != null) {
_nameController.text = currentUser.displayName!;
}
if (settings == null) {
SettingModel.getSettings().then(
(SettingModel value) => (value) {
if (mounted) {
setState(() {
settings = value.version;
_getAppVersion();
});
}
},
);
}
if (_ciudad == '...') {
AuthenticationRepository.instance
.getCity(uid.toString())
.then((String s) {
if (s.isEmpty) {
FirebaseFirestore.instance.collection('users').doc(uid).set({
'city': 'Cúcuta',
}).then((_) {
if (mounted) {
setState(() {
_ciudad = 'Cúcuta';
});
}
});
} else {
if (mounted) {
setState(() {
_ciudad = s;
});
}
}
});
}
if (_coordsOfCity == '0.0,0.0') {
AuthenticationRepository.instance
.getCoordsOfCity(uid.toString())
.then((String s) {
if (mounted) {
setState(() {
_coordsOfCity = s;
_animateInitialCameraToPosition(_coordsOfCity);
});
}
});
}
_saveToken();
if (Platform.isAndroid) {
BitmapDescriptor.fromAssetImage(
const ImageConfiguration(size: Size(2, 2)),
'images/pro_marke_android.png',
).then((icon) {
if (mounted) {
setState(() {
_markerIcon = icon;
});
}
});
} else {
BitmapDescriptor.fromAssetImage(
const ImageConfiguration(size: Size(1, 1)),
'images/pro_marke.png',
).then((icon) {
if (mounted) {
setState(() {
_markerIcon = icon;
});
}
});
}
updateMarkersForServiceType(_serviceType);
}
@override
void dispose() {
_locacionController.dispose();
_ubicationController.dispose();
_profesionalController.dispose();
_serviceTypeController.dispose();
_observacionController.dispose();
_locationController.onLocationChanged.listen((_) {}).cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
UserModel? user = userProvider.user;
dynamic datos;
return SafeArea(
child: Scaffold(
drawer: DrawerMenu(),
body: Column(
children: [
Expanded(
child: Stack(
children: [
GoogleMap(
onMapCreated: ((GoogleMapController controller) {
_mapController.complete(controller);
_applyMapStyle(controller);
}),
initialCameraPosition: const CameraPosition(
target: _pGooglePlex,
zoom: 15,
),
markers: {
...markers,
if (_currentP != null)
Marker(
markerId: const MarkerId("_currentLocation"),
icon: BitmapDescriptor.defaultMarker,
position: _currentP!,
),
},
polylines: Set<Polyline>.of(polylines.values),
onCameraIdle: () {
if (professionalAddress == '') {
if (coordinates != null) {
getLocationName(
coordinates.latitude, coordinates.longitude)
.then((locationName) {
if (mounted) {
setState(() {
_locacionController.text = locationName;
});
}
});
}
}
},
onCameraMove: (position) {
if (mounted) {
setState(() {
coordinates = position.target;
});
}
},
),
Positioned(
top: 10,
left: 10,
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: 25,
right: 0,
left: 0,
top: 0,
child: Icon(
Icons.location_on,
size: 40,
color: Color(0xFFFF0000),
),
),
Positioned(
top: 10,
right: 20,
child: FloatingActionButton(
onPressed: () async {
try {
Position position = await _determinePosition();
if (mounted) {
setState(() {
_currentP = LatLng(
position.latitude,
position.longitude,
);
});
_animateCameraToPosition(_currentP!);
}
} catch (e) {
WarningSnackbar.show(
title: 'Ubicación desactivada',
message:
'Por favor activa la ubicacion de tu telefono.',
);
}
},
elevation: 0,
child: const Icon(
Icons.gps_fixed,
size: 30,
),
),
),
],
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
color: Colors.white,
child: Form(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: _serviceTypeController,
readOnly: true,
onTap: () async {
if (_nameController.text == '') {
WarningSnackbar.show(
title: 'Completa tu perfil',
message:
'Asegurate de llenar todos los campos de tu perfil antes de seleccionar un tipo de servicio.',
);
return;
}
final String? serviceType = await Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return const ServiceTypeScreen();
},
),
) as String?;
if (serviceType != null) {
if (mounted) {
setState(() {
_serviceType = serviceType;
_serviceTypeController.text = _serviceType;
updateMarkersForServiceType(_serviceType);
});
datos = await Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return ProfessionalScreen(
profession: _serviceTypeController.text,
);
},
),
);
if (datos != null) {
Professional? profesional = datos[0];
ubicacion = datos[1];
if (profesional != null) {
if (mounted) {
setState(() {
_profesionalController.text =
profesional.name.toString();
professionalId = profesional.id;
if (profesional.token != '') {
professionalToken = profesional.token!;
}
professionalTarifa =
profesional.tarifa ?? 0;
professionalUbicacion =
profesional.ubicacion;
professionalLatitude = profesional.latitude;
professionalLongitude =
profesional.longitude;
if (ubicacion == 'sitio') {
professionalAddress =
profesional.realAddress;
_locacionController.text =
profesional.realAddress;
LatLng professionalCoordinates = LatLng(
professionalLatitude!,
professionalLongitude!);
if (professionalLatitude != null &&
professionalLatitude != 0 &&
professionalLongitude != null &&
professionalLongitude != 0) {
_animateCameraToPosition(
LatLng(professionalLatitude!,
professionalLongitude!),
);
getPolylinePoints(_currentP!,
professionalCoordinates)
.then(
(coordinates) => {
generatePolyLineFromPoints(
coordinates),
},
);
}
} else {
polylines.clear();
}
});
}
}
}
}
}
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.room_service_rounded),
suffixIcon: Icon(Icons.arrow_drop_down),
hintText: 'Tipo de Servicio',
),
),
const SizedBox(height: 15),
TextFormField(
controller: _profesionalController,
readOnly: true,
onTap: () async {
if (_currentP == null) {
try {
Position position = await _determinePosition();
if (mounted) {
setState(() {
_currentP = LatLng(
position.latitude,
position.longitude,
);
});
_animateCameraToPosition(_currentP!);
}
} catch (e) {
WarningSnackbar.show(
title: 'Ubicación desactivada',
message:
'Por favor activa la ubicacion de tu telefono para solicitar un servicio.',
);
}
return;
}
if (_nameController.text == '') {
WarningSnackbar.show(
title: 'Completa tu perfil',
message:
'Asegurate de llenar todos los campos de tu perfil antes de seleccionar un profesional.',
);
return;
}
datos = await Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return ProfessionalScreen(
profession: _serviceTypeController.text,
);
},
),
);
if (datos != null) {
Professional? profesional = datos[0];
ubicacion = datos[1];
if (profesional != null) {
if (mounted) {
setState(() {
_profesionalController.text =
profesional.name.toString();
professionalId = profesional.id;
if (profesional.token != '') {
professionalToken = profesional.token!;
}
professionalTarifa = profesional.tarifa ?? 0;
professionalUbicacion = profesional.ubicacion;
professionalLatitude = profesional.latitude;
professionalLongitude = profesional.longitude;
if (ubicacion == 'sitio') {
professionalAddress = profesional.realAddress;
_locacionController.text =
profesional.realAddress;
LatLng professionalCoordinates = LatLng(
professionalLatitude!,
professionalLongitude!);
if (professionalLatitude != null &&
professionalLatitude != 0 &&
professionalLongitude != null &&
professionalLongitude != 0) {
_animateCameraToPosition(
LatLng(professionalLatitude!,
professionalLongitude!),
);
getPolylinePoints(
_currentP!, professionalCoordinates)
.then(
(coordinates) => {
generatePolyLineFromPoints(coordinates),
},
);
}
} else {
polylines.clear();
}
});
}
}
}
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.assignment_ind_rounded),
suffixIcon: Icon(Icons.arrow_drop_down),
hintText: 'Seleccionar profesional',
),
),
const SizedBox(height: 15),
TextFormField(
controller: _locacionController,
readOnly: ubicacion == 'sitio' ? true : false,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.near_me),
hintText: 'Dirección',
),
onChanged: (value) {
String modifiedValue = value.replaceAll(' ', '_');
placeAutoComplete(modifiedValue);
},
),
ubicacion == 'sitio'
? const SizedBox()
: SizedBox(
height: _placesList.isNotEmpty ? 200 : 0,
child: ListView.builder(
itemCount: _placesList.length,
itemBuilder: (context, index) {
return ListTile(
onTap: () {
final selectedAddress =
_placesList[index]['formatted_address'];
final selectedLatitude = _placesList[index]
['geometry']['location']['lat'];
final selectedLongitude = _placesList[index]
['geometry']['location']['lng'];
_locacionController.text = selectedAddress;
_animateCameraToPosition(LatLng(
selectedLatitude,
selectedLongitude,
));
if (mounted) {
setState(() {
_placesList = [];
});
}
},
title: Text(
_placesList[index]['formatted_address']),
);
},
),
),
const SizedBox(height: 15),
Row(
children: [
Expanded(
child: TextFormField(
readOnly: true,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.calendar_month),
suffixIcon: _selectedDate == null
? const Icon(Icons.arrow_drop_down)
: null,
hintText: 'Fecha',
),
controller: TextEditingController(
text: _selectedDate == null
? ''
: formatter.format(_selectedDate!),
),
onTap: () {
if (_profesionalController.text.isNotEmpty) {
_selectDateAndTime(context);
} else {
WarningSnackbar.show(
title: 'Selecciona un profesional',
message:
'Selecciona un profesional antes de elegir la fecha y la hora de la cita.',
backgroundColor: Colors.orange,
);
}
},
),
),
Expanded(
child: TextFormField(
onTap: () {
if (_profesionalController.text.isNotEmpty) {
_selectDateAndTime(context);
} else {
WarningSnackbar.show(
title: 'Selecciona un profesional',
message:
'Selecciona un profesional antes de elegir la fecha y la hora de la cita.',
backgroundColor: Colors.orange);
}
},
readOnly: true,
decoration: const InputDecoration(
suffixIcon: Icon(Icons.arrow_drop_down),
hintText: 'Hora',
),
controller: TextEditingController(
text: _selectedTime == null
? ''
: ' ${_selectedTime!.format(context)}',
),
))
],
),
const SizedBox(height: 15),
TextFormField(
controller: _observacionController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.message_outlined),
hintText: 'Observaciones',
),
),
const SizedBox(height: 20),
Center(
child: PrimaryButton(
onPressed: () {
if (user?.name == null ||
user?.name == '' ||
user?.phoneNumber == null ||
user?.phoneNumber == '') {
WarningSnackbar.show(
title: 'Completa tu perfil',
message:
'Diligencia la información de tu perfil antes de solicitar un servicio.',
);
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return const ProfileScreen();
},
),
);
} else {
try {
final DateTime combinedDate = DateTime(
_selectedDate!.year,
_selectedDate!.month,
_selectedDate!.day,
_selectedTime!.hour,
_selectedTime!.minute,
);
DateTime time2 = combinedDate.add(
const Duration(hours: 2),
);
UserModel.getUser(uid.toString()).then((value) {
eventoService
.createEvent(
value.name,
_observacionController.text,
'$_selectedDate',
'$combinedDate',
'$time2',
professionalId,
ubicacion,
_locacionController.text,
ubicacion != 'sitio'
? coordinates.latitude
: professionalLatitude,
ubicacion != 'sitio'
? coordinates.longitude
: professionalLongitude,
'pendiente',
professionalTarifa == 0
? 0
: professionalTarifa,
false,
false,
)
.then((value) {
if (professionalToken != '') {
sendPushNotification(professionalToken);
}
Navigator.pushReplacement(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return ServiceAfterScreen(
eventoId: value,
);
},
),
);
});
});
} catch (e) {
WarningSnackbar.show(
title: 'Llena todos los campos',
message:
'Asegurate de llenar todos los campos antes de solicitar un servicio.',
);
}
}
},
text: 'Solicitar servicio',
minWidth: 230,
),
),
],
),
),
)
],
),
),
);
}
Future<void> getLocationUpdates() async {
bool _serviceEnabled;
PermissionStatus _permissionGranted;
_serviceEnabled = await _locationController.serviceEnabled();
if (_serviceEnabled) {
_serviceEnabled = await _locationController.requestService();
} else {
return;
}
_permissionGranted = await _locationController.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await _locationController.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
_locationController.onLocationChanged
.listen((LocationData currentLocation) {
if (currentLocation.latitude != null &&
currentLocation.longitude != null) {
if (mounted) {
setState(() {
_currentP = LatLng(
currentLocation.latitude!,
currentLocation.longitude!,
);
});
}
}
});
}
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) {
result.points.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
} else {
print(result.errorMessage);
}
return polylineCoordinates;
}
void generatePolyLineFromPoints(List<LatLng> polylineCoordinates) async {
PolylineId id = const PolylineId("poly");
Polyline polyline = Polyline(
polylineId: id,
color: Colors.blue,
points: polylineCoordinates,
width: 6,
);
if (mounted) {
setState(() {
polylines[id] = polyline;
});
}
}
void _applyMapStyle(GoogleMapController controller) {
controller.setMapStyle(MAP_STYLE);
}
Future<void> _animateCameraToPosition(LatLng position) async {
final GoogleMapController controller = await _mapController.future;
controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: position,
zoom: 17.5,
),
),
);
}
Future<void> _animateInitialCameraToPosition(String coordsOfCity) async {
List<String> coords = coordsOfCity.split(',');
double lat = double.parse(coords[0]);
double lng = double.parse(coords[1]);
_animateCameraToPosition(LatLng(lat, lng));
try {
Position position = await _determinePosition();
_animateCameraToPosition(LatLng(position.latitude, position.longitude));
if (mounted) {
setState(() {});
}
} catch (e) {
print('Error: $e');
}
}
void updateMarkersForServiceType(String serviceType) {
getUsersWithActiveStatus(serviceType).then((value) {
markers.clear();
for (var doc in value) {
final element = doc.data()!;
if (element['latitude'] != null && element['longitude'] != null) {
markers.add(
Marker(
icon: _markerIcon!,
markerId: MarkerId(doc.id),
position: LatLng(
element['latitude'],
element['longitude'],
),
),
);
}
}
}).catchError((e) {
print('Error al actualizar los marcadores: $e');
});
}
Future<Position> _determinePosition() async {
bool serviceEnabled;
LocationPermission permission;
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
return Future.error('Location services are disabled');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
return Future.error('Location permission denied');
}
}
if (permission == LocationPermission.deniedForever) {
return Future.error('Location permissions are permanently denied');
}
Position position = await Geolocator.getCurrentPosition();
return position;
}
Future<String> getLocationName(double latitude, double longitude) async {
String address;
try {
List<geocoding.Placemark> placemarks =
await geocoding.placemarkFromCoordinates(latitude, longitude);
geocoding.Placemark place = placemarks[0];
if (place.thoroughfare != '' || place.subThoroughfare != '') {
address =
"${place.thoroughfare} ${place.subThoroughfare} ${place.subLocality}, ${place.locality}, ${place.administrativeArea}";
} else {
address = '';
}
} catch (e) {
address = '';
}
return address;
}
void placeAutoComplete(String query) async {
Uri uri = Uri.https("admin.prosapp.co", "/autocomplete", {
"input": query,
"location": _coordsOfCity,
});
String? response = await NetworkUtility.fetchUrl(uri);
if (response != null) {
if (mounted) {
setState(() {
_placesList = jsonDecode(response.toString())['results'];
});
}
}
}
Future<void> _selectDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: now,
firstDate: now,
lastDate: DateTime(now.year + 1),
);
if (picked != null && picked != _selectedDate) {
if (mounted) {
setState(() {
_selectedDate = picked;
});
}
}
}
Future<void> _selectTime(BuildContext context) async {
final TimeOfDay? pickedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (pickedTime != null) {
if (mounted) {
setState(() {
_selectedTime = pickedTime;
});
}
}
}
Future<List<DocumentSnapshot<Map<String, dynamic>>>> getUsersWithActiveStatus(
String serviceType) async {
dynamic querySnapshot;
if (serviceType != "Servicio") {
querySnapshot = await FirebaseFirestore.instance
.collection('users')
.where('estado', isEqualTo: 'activo')
.where('profesion', isEqualTo: serviceType)
.get();
} else {
querySnapshot = await FirebaseFirestore.instance
.collection('users')
.where('estado', isEqualTo: 'activo')
.get();
}
return querySnapshot.docs;
}
void _saveToken() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
final token = await messaging.getToken();
try {
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.update({'token': token});
} catch (e) {
print(e);
}
}
Future<void> _getAppVersion() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String version = packageInfo.version;
print('App version: $version');
if (mounted) {
setState(() {
appVersion = version;
});
}
print('App version: $settings');
if (settings != null) {
_checkForUpdate(settings);
}
}
void _checkForUpdate(String? settings) {
if (appVersion == settings) {
showDialog(
context: context,
builder: (context) {
return WillPopScope(
onWillPop: () async {
return false;
},
child: Center(
child: AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
title: const Text(
"Debes Actualizar la Aplicación",
style: TextStyle(fontWeight: FontWeight.bold),
),
content: const Text(
"Tienes una versión desactualizada de nuestra aplicación. Te recomendamos actualizarla para disfrutar de las últimas características y mejoras.",
),
actions: [
TextButton(
child: const Text(
"Actualizar",
style:
TextStyle(fontWeight: FontWeight.w600, fontSize: 20),
),
onPressed: () {
if (Platform.isAndroid) {
launchUrl(_url);
} else {
launchUrl(_urlIos);
}
},
),
],
),
),
);
},
);
}
}
Future<void> _selectDateAndTime(BuildContext context) async {
final DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: now,
firstDate: now,
lastDate: DateTime(now.year + 1),
);
if (pickedDate == null) {
return;
}
final TimeOfDay? pickedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (pickedTime != null) {
final DateTime selectedDateTime = DateTime(
pickedDate.year,
pickedDate.month,
pickedDate.day,
pickedTime.hour,
pickedTime.minute,
);
if (selectedDateTime.isBefore(DateTime.now())) {
WarningSnackbar.show(
title: 'Hora inválida',
message:
'La hora seleccionada no es valida porque es anterior a la hora actual.',
);
return;
}
if (mounted) {
setState(() {
_selectedDate = pickedDate;
_selectedTime = pickedTime;
});
}
}
}
Future<void> sendPushNotification(String pro) async {
try {
http.Response response = await http.post(
Uri.parse('https://fcm.googleapis.com/fcm/send'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization':
'key=AAAAORdR-xU:APA91bF_wblg86jHAC-uexrXPHavYRlk5wge1Gf46m56V4J2D2L37Cp_hf46JZUzpvsWPSpqc5ewHelKI9LTifUG_s2mciMI6e5VLKo7E1R8btbNo7iaM9do2ctoyHKUm1atlZBdKaN2',
},
body: jsonEncode(
<String, dynamic>{
'notification': <String, dynamic>{
'body': 'alguien a solicitado tus servicios',
'title': 'Nueva solicitud',
},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done',
'screen': 'solicitud'
},
'to': pro
},
),
);
response;
} catch (e) {
print('error al enviar notificacion $e');
}
}
}