This commit is contained in:
Felipe
2023-11-10 15:34:13 -05:00
parent b3d1740649
commit f732d461d0
14 changed files with 613 additions and 235 deletions
@@ -187,6 +187,34 @@ class AuthenticationRepository extends GetxController {
return city; return city;
} }
Future<String> getGender(String uid) async {
String gender = '';
try {
final snapshot =
await FirebaseFirestore.instance.collection('users').doc(uid).get();
final Map<String, dynamic>? data = snapshot.data();
gender = data?['gender'] ?? '';
} catch (e) {
print('Error getting gender: $e');
}
return gender;
}
Future<String> getBirthday(String uid) async {
String birthDate = '';
try {
final snapshot =
await FirebaseFirestore.instance.collection('users').doc(uid).get();
final Map<String, dynamic>? data = snapshot.data();
birthDate = data?['birth_date'] ?? '';
print('nada $birthDate');
} catch (e) {
print('Error getting birthDate: $e');
}
return birthDate;
}
Future<String> getCoordsOfCity(String uid) async { Future<String> getCoordsOfCity(String uid) async {
String coords = ''; String coords = '';
try { try {
+13 -9
View File
@@ -30,9 +30,11 @@ class _LoginScreenState extends State<LoginScreen> {
SettingModel? settings; SettingModel? settings;
void _clearPhoneNumber() { void _clearPhoneNumber() {
setState(() { if (mounted) {
controller.phoneNo.text = ''; setState(() {
}); controller.phoneNo.text = '';
});
}
} }
void _launchURL(String url) async { void _launchURL(String url) async {
@@ -47,11 +49,13 @@ class _LoginScreenState extends State<LoginScreen> {
void initState() { void initState() {
super.initState(); super.initState();
if (settings == null) { if (settings == null) {
SettingModel.getSettings().then( SettingModel.getSettings().then((SettingModel value) {
(SettingModel value) => setState(() { if (mounted) {
settings = value; setState(() {
}), settings = value;
); });
}
});
} }
} }
@@ -182,12 +186,12 @@ class _LoginScreenState extends State<LoginScreen> {
PhoneAuthController.instance.phoneAuthentication( PhoneAuthController.instance.phoneAuthentication(
completePhoneNumber.trim(), completePhoneNumber.trim(),
); );
_clearPhoneNumber();
await Get.to( await Get.to(
() => CodeValidationScreen( () => CodeValidationScreen(
phoneNumber: completePhoneNumber.trim(), phoneNumber: completePhoneNumber.trim(),
), ),
); );
_clearPhoneNumber();
Provider.of<UserProvider>(context, listen: false) Provider.of<UserProvider>(context, listen: false)
.initUserProvider(); .initUserProvider();
} }
+38 -9
View File
@@ -9,6 +9,7 @@ import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/models/event_model.dart'; import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/models/scores_model.dart'; import 'package:prosappco/src/models/scores_model.dart';
import 'package:prosappco/src/presentation/screens/cita.dart'; import 'package:prosappco/src/presentation/screens/cita.dart';
import 'package:prosappco/src/presentation/screens/score.dart';
class MyServicesScreen extends StatelessWidget { class MyServicesScreen extends StatelessWidget {
MyServicesScreen({super.key}); MyServicesScreen({super.key});
@@ -54,6 +55,7 @@ class MyServicesScreen extends StatelessWidget {
.asyncMap((snapshot) async { .asyncMap((snapshot) async {
try { try {
List<Event> eventos = []; List<Event> eventos = [];
for (var element in snapshot.docs) { for (var element in snapshot.docs) {
final event = Event.fromJson(element.data()); final event = Event.fromJson(element.data());
event.scoresModel = event.scoresModel =
@@ -79,8 +81,10 @@ class MyServicesScreen extends StatelessWidget {
try { try {
eventos.addAll(snapshot.data!); eventos.addAll(snapshot.data!);
eventos.sort((a, b) => a.timeStamp!.compareTo(b.timeStamp!)); eventos.sort((a, b) => a.timeStamp!.compareTo(b.timeStamp!));
print('snapshot mi b ${eventos}');
} catch (e) { } catch (e) {
print("Error" + e.toString()); print("Error snapshot" + e.toString());
} }
if (eventos.isEmpty) { if (eventos.isEmpty) {
@@ -122,14 +126,39 @@ class MyServicesScreen extends StatelessWidget {
? Colors.red[100] ? Colors.red[100]
: Colors.blue[100], : Colors.blue[100],
onTap: () { onTap: () {
Navigator.push( if (event.status == 'terminado') {
context, if (event.userId == uid) {
CupertinoPageRoute( if (event.userScored) {
builder: (BuildContext context) { Navigator.push(
return CitaScreen(evento: event); context,
}, CupertinoPageRoute(
), builder: (BuildContext context) {
); return CitaScreen(evento: event);
},
),
);
} else {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return ScoreScreen(
evento: event, pro: false);
},
),
);
}
}
} else {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return CitaScreen(evento: event);
},
),
);
}
}, },
leading: event.status == 'aprobado' leading: event.status == 'aprobado'
? const Column( ? const Column(
@@ -9,6 +9,7 @@ import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/models/event_model.dart'; import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/models/scores_model.dart'; import 'package:prosappco/src/models/scores_model.dart';
import 'package:prosappco/src/presentation/screens/cita.dart'; import 'package:prosappco/src/presentation/screens/cita.dart';
import 'package:prosappco/src/presentation/screens/score.dart';
class MyServicesProScreen extends StatelessWidget { class MyServicesProScreen extends StatelessWidget {
MyServicesProScreen({super.key}); MyServicesProScreen({super.key});
@@ -98,14 +99,38 @@ class MyServicesProScreen extends StatelessWidget {
? Colors.red[100] ? Colors.red[100]
: Colors.blue[100], : Colors.blue[100],
onTap: () { onTap: () {
Navigator.push( if (event.status == 'terminado') {
context, if (event.professionalId == uid) {
CupertinoPageRoute( if (event.professionalScored) {
builder: (BuildContext context) { Navigator.push(
return CitaScreen(evento: event); context,
}, CupertinoPageRoute(
), builder: (BuildContext context) {
); return CitaScreen(evento: event);
},
),
);
} else {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return ScoreScreen(evento: event, pro: true);
},
),
);
}
}
} else {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return CitaScreen(evento: event);
},
),
);
}
}, },
leading: event.status == 'aprobado' leading: event.status == 'aprobado'
? const Column( ? const Column(
@@ -4,7 +4,6 @@ import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/presentation/screens/support.dart';
final CollectionReference professionsCollection = final CollectionReference professionsCollection =
FirebaseFirestore.instance.collection('professions'); FirebaseFirestore.instance.collection('professions');
@@ -1,3 +1,4 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart';
@@ -38,6 +39,33 @@ class _ProfessionalInfoScreenState extends State<ProfessionalInfoScreen> {
}), }),
); );
} }
loadPaymentMethods();
}
Map<String, bool> paymentMethods = {};
String _formatPaymentMethods(Map<String, bool> paymentMethods) {
List<String> enabledMethods = paymentMethods.entries
.where((entry) => entry.value)
.map((entry) => entry.key)
.toList();
return enabledMethods.join(', ');
}
void loadPaymentMethods() {
FirebaseFirestore.instance
.collection('users')
.doc(widget.professional.id)
.get()
.then((doc) {
if (doc.exists) {
setState(() {
paymentMethods = Map<String, bool>.from(doc['paymentMethods'] ?? {});
});
}
});
} }
@override @override
@@ -156,7 +184,38 @@ class _ProfessionalInfoScreenState extends State<ProfessionalInfoScreen> {
), ),
) )
: const SizedBox(), : const SizedBox(),
const SizedBox(height: 10), const SizedBox(height: 5),
paymentMethods.containsValue(true)
? Container(
width: MediaQuery.of(context).size.width * 0.8,
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: RichText(
text: TextSpan(
style: const TextStyle(
fontSize: 12,
color: Colors.blue,
),
children: [
const TextSpan(
text: 'Métodos de pago recibidos: ',
style:
TextStyle(fontWeight: FontWeight.normal),
),
TextSpan(
text: _formatPaymentMethods(paymentMethods),
style: const TextStyle(
fontWeight: FontWeight.bold),
),
],
),
))
: const SizedBox(),
const SizedBox(height: 5),
const Text( const Text(
'Se unió el 02 de abril del 2023', 'Se unió el 02 de abril del 2023',
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
@@ -1,6 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -25,7 +24,6 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
File? image_cedula; File? image_cedula;
File? image_certificado; File? image_certificado;
late final FirebaseAuth _auth;
final FirebaseStorage storage = FirebaseStorage.instance; final FirebaseStorage storage = FirebaseStorage.instance;
final uid = AuthenticationRepository.instance.getCurrentUserUid(); final uid = AuthenticationRepository.instance.getCurrentUserUid();
@@ -44,7 +42,6 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_auth = FirebaseAuth.instance;
if (_photo == '...') { if (_photo == '...') {
AuthenticationRepository.instance AuthenticationRepository.instance
.getPhoto(uid.toString()) .getPhoto(uid.toString())
@@ -43,13 +43,14 @@ class _ProfileScreenState extends State<ProfileScreen> {
var _photo = '...'; var _photo = '...';
String? _email = ''; String? _email = '';
String gender = ''; String gender = '';
String genderDb = '';
DateTime? birthDate; DateTime? birthDate;
String birthDateDb = '';
@override @override
void initState() { void initState() {
super.initState(); super.initState();
final uid = AuthenticationRepository.instance.getCurrentUserUid();
_auth = FirebaseAuth.instance; _auth = FirebaseAuth.instance;
final currentUser = _auth.currentUser; final currentUser = _auth.currentUser;
@@ -65,22 +66,40 @@ class _ProfileScreenState extends State<ProfileScreen> {
_emailController.text = currentUser.email!; _emailController.text = currentUser.email!;
} }
if (gender.isEmpty) {
AuthenticationRepository.instance.getGender(uid.toString()).then(
(String s) => setState(() {
genderDb = s;
}),
);
}
if (birthDate == null) {
AuthenticationRepository.instance.getBirthday(uid.toString()).then(
(String s) => setState(() {
if (s.isNotEmpty) {
birthDateDb = s;
}
}),
);
}
_email = currentUser?.email; _email = currentUser?.email;
if (_ciudad == '...') { if (_ciudad == '...') {
AuthenticationRepository.instance AuthenticationRepository.instance.getCity(uid.toString()).then(
.getCity(uid.toString()) (String s) => setState(() {
.then((String s) => setState(() { _ciudad = s;
_ciudad = s; }),
})); );
} }
if (_photo == '...') { if (_photo == '...') {
AuthenticationRepository.instance AuthenticationRepository.instance.getPhoto(uid.toString()).then(
.getPhoto(uid.toString()) (String s) => setState(() {
.then((String s) => setState(() { _photo = s;
_photo = s; }),
})); );
} }
} }
@@ -221,6 +240,32 @@ class _ProfileScreenState extends State<ProfileScreen> {
String newEmail = _emailController.text.trim(); String newEmail = _emailController.text.trim();
String newPassword = _passwordController.text.trim(); String newPassword = _passwordController.text.trim();
if (gender.isNotEmpty) {
try {
await FirebaseFirestore.instance.collection('users').doc(uid).set({
'gender': gender,
}, SetOptions(merge: true));
genderDb = gender;
} catch (e) {
print('Error al actualizar el genero: $e');
}
}
if (birthDate != null) {
try {
await FirebaseFirestore.instance.collection('users').doc(uid).set({
'birth_date': birthDate.toString(),
}, SetOptions(merge: true));
birthDateDb = birthDate.toString();
} catch (e) {
print('Error al actualizar la fecha de nacimiento: $e');
}
}
setState(() {});
if (newName.isEmpty) { if (newName.isEmpty) {
Get.snackbar( Get.snackbar(
'Nombre Invalido', 'Nombre Invalido',
@@ -281,7 +326,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
.doc(uid) .doc(uid)
.update({'email': newEmail}); .update({'email': newEmail});
} catch (e) { } catch (e) {
print('e'); print('Error al actualizar la imagen de perfil $e');
} }
try { try {
@@ -296,7 +341,11 @@ class _ProfileScreenState extends State<ProfileScreen> {
print('Error al actualizar la imagen de perfil $e'); print('Error al actualizar la imagen de perfil $e');
} }
// notifyListeners(); Get.snackbar(
'Informacion actualizada',
'Tu informacion ha sido actualizada con exito.',
snackPosition: SnackPosition.BOTTOM,
);
} }
Future<void> _updateEmailAndPassword( Future<void> _updateEmailAndPassword(
@@ -435,7 +484,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
'Inicia sesión para asegurarnos de que seas tú.', 'Inicia sesión para asegurarnos de que seas tú.',
snackPosition: SnackPosition.BOTTOM, snackPosition: SnackPosition.BOTTOM,
); );
AuthenticationRepository.instance.logout(uid!); // AuthenticationRepository.instance.logout(uid!);
} }
} }
} }
@@ -644,26 +693,32 @@ class _ProfileScreenState extends State<ProfileScreen> {
), ),
), ),
const SizedBox(height: 20.0), const SizedBox(height: 20.0),
GenderDropdown( genderDb == ''
onChanged: (selectedGender) { ? GenderDropdown(
setState(() { onChanged: (selectedGender) {
gender = selectedGender; setState(() {
}); gender = selectedGender;
}, });
), },
const SizedBox(height: 20.0), )
BirthDatePicker( : const SizedBox(),
onDateSelected: (birthDay) { genderDb == ''
setState(() { ? const SizedBox(height: 20.0)
birthDate = birthDay; : const SizedBox(),
}); birthDateDb == ''
}, ? BirthDatePicker(
controller: TextEditingController( onDateSelected: (birthDay) {
text: birthDate == null setState(() {
? '' birthDate = birthDay;
: formatter.format(birthDate!), });
), },
), controller: TextEditingController(
text: birthDate == null
? ''
: formatter.format(birthDate!),
),
)
: const SizedBox(),
], ],
), ),
), ),
@@ -9,12 +9,13 @@ import 'package:get/get.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/banner_photo.dart'; import 'package:prosappco/src/components/banner_photo.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/components/primary_btn.dart';
import 'package:prosappco/src/components/schedule_picker.dart'; import 'package:prosappco/src/components/schedule_picker.dart';
import 'package:prosappco/src/models/setting_model.dart'; import 'package:prosappco/src/models/setting_model.dart';
import 'package:prosappco/src/presentation/screens/horario.dart'; import 'package:prosappco/src/presentation/screens/horario.dart';
import 'package:prosappco/src/presentation/screens/professional.dart'; import 'package:prosappco/src/presentation/screens/professional.dart';
import 'package:prosappco/src/presentation/screens/professional_direccion.dart'; import 'package:prosappco/src/presentation/screens/professional_direccion.dart';
import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart';
import 'package:prosappco/src/presentation/widgets/shared/primary_checkbox.dart';
import 'package:prosappco/src/services/select_image_profile.dart'; import 'package:prosappco/src/services/select_image_profile.dart';
class ProfileProScreen extends StatefulWidget { class ProfileProScreen extends StatefulWidget {
@@ -47,8 +48,18 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
int _tarifa = 0; int _tarifa = 0;
SettingModel? settings; SettingModel? settings;
bool nequiValue = false;
bool banktransferValue = false;
bool datafoneValue = false;
Map<String, Schedule>? _horarios; Map<String, Schedule>? _horarios;
Map<String, bool> paymentMethods = {
'Nequi': false,
'Transferencia Bancaria': false,
'Datafono': false,
};
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -131,6 +142,8 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
), ),
); );
} }
loadPaymentMethods();
} }
void createSchedules() async { void createSchedules() async {
@@ -276,6 +289,8 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
print('Error al actualizar la imagen de perfil $e'); print('Error al actualizar la imagen de perfil $e');
} }
updatePaymentMethods();
Get.snackbar( Get.snackbar(
'Información actualizada', 'Información actualizada',
'Tu información ha sido actualizada con éxito.', 'Tu información ha sido actualizada con éxito.',
@@ -405,6 +420,22 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
}); });
} }
void updatePaymentMethods() {
FirebaseFirestore.instance.collection('users').doc(uid).update({
'paymentMethods': paymentMethods,
});
}
void loadPaymentMethods() {
FirebaseFirestore.instance.collection('users').doc(uid).get().then((doc) {
if (doc.exists) {
setState(() {
paymentMethods = Map<String, bool>.from(doc['paymentMethods'] ?? {});
});
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
String address = _direccion.toString(); String address = _direccion.toString();
@@ -522,6 +553,33 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
) )
: const SizedBox(), : const SizedBox(),
const Divider(), const Divider(),
Padding(
padding: const EdgeInsets.only(left: 30, right: 30, bottom: 30),
child: SizedBox(
width: double.infinity,
child: Column(
children: [
const Text(
'Metodos de pago',
style: TextStyle(
color: Colors.black,
fontSize: 17,
),
),
for (var entry in paymentMethods.entries)
PrimaryCheckbox(
text: entry.key,
initialValue: entry.value,
onChanged: (value) {
setState(() {
paymentMethods[entry.key] = value;
});
},
),
],
),
),
),
const Padding( const Padding(
padding: EdgeInsets.symmetric(horizontal: 30), padding: EdgeInsets.symmetric(horizontal: 30),
child: SizedBox( child: SizedBox(
@@ -530,7 +588,7 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
'Horario estandar', 'Horario estandar',
style: TextStyle( style: TextStyle(
color: Colors.black, color: Colors.black,
fontSize: 15, fontSize: 17,
), ),
), ),
), ),
@@ -666,15 +724,14 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
), ),
), ),
), ),
PrimaryButtom( const SizedBox(height: 10),
onPressed: () { PrimaryButton(
updateInfo(); onPressed: () {
// name(); updateInfo();
}, },
label: 'Guardar'), text: 'Guardar',
const SizedBox( ),
height: 20, const SizedBox(height: 20),
)
], ],
), ),
), ),
+185 -141
View File
@@ -26,6 +26,8 @@ import 'package:prosappco/src/presentation/screens/ubicacion.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:prosappco/src/components/network_utility.dart'; import 'package:prosappco/src/components/network_utility.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart';
import 'package:prosappco/src/presentation/widgets/shared/warning_snackbar.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class ServiceScreen extends StatefulWidget { class ServiceScreen extends StatefulWidget {
@@ -178,9 +180,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
); );
if (picked != null && picked != _selectedDate) { if (picked != null && picked != _selectedDate) {
setState(() { if (mounted) {
_selectedDate = picked; setState(() {
}); _selectedDate = picked;
});
}
} }
} }
@@ -191,9 +195,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
); );
if (pickedTime != null) { if (pickedTime != null) {
setState(() { if (mounted) {
_selectedTime = pickedTime; setState(() {
}); _selectedTime = pickedTime;
});
}
} }
} }
@@ -252,13 +258,25 @@ class _ServiceScreenState extends State<ServiceScreen> {
), ),
), ),
); );
if (mounted) {
setState(() {}); setState(() {});
}
} catch (e) { } catch (e) {
print('Error: $e'); print('Error: $e');
} }
} }
@override
void dispose() {
_locationController.dispose();
_ubicationController.dispose();
_profesionalController.dispose();
_serviceTypeController.dispose();
_observacionController.dispose();
super.dispose();
}
void updateMarkersForServiceType(String serviceType) { void updateMarkersForServiceType(String serviceType) {
getUsersWithActiveStatus(serviceType).then((value) { getUsersWithActiveStatus(serviceType).then((value) {
markers.clear(); markers.clear();
@@ -287,9 +305,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
PackageInfo packageInfo = await PackageInfo.fromPlatform(); PackageInfo packageInfo = await PackageInfo.fromPlatform();
String version = packageInfo.version; String version = packageInfo.version;
setState(() { if (mounted) {
appVersion = version; setState(() {
}); appVersion = version;
});
}
if (settings != null) { if (settings != null) {
_checkForUpdate(settings); _checkForUpdate(settings);
@@ -348,12 +368,14 @@ class _ServiceScreenState extends State<ServiceScreen> {
} }
if (settings == null) { if (settings == null) {
SettingModel.getSettings().then( SettingModel.getSettings().then((SettingModel value) => (value) {
(SettingModel value) => setState(() { if (mounted) {
settings = value.version; setState(() {
_getAppVersion(); settings = value.version;
}), _getAppVersion();
); });
}
});
} }
if (_ciudad == '...') { if (_ciudad == '...') {
@@ -364,14 +386,18 @@ class _ServiceScreenState extends State<ServiceScreen> {
FirebaseFirestore.instance.collection('users').doc(uid).set({ FirebaseFirestore.instance.collection('users').doc(uid).set({
'city': 'Cúcuta', 'city': 'Cúcuta',
}).then((_) { }).then((_) {
setState(() { if (mounted) {
_ciudad = 'Cúcuta'; setState(() {
}); _ciudad = 'Cúcuta';
});
}
}); });
} else { } else {
setState(() { if (mounted) {
_ciudad = s; setState(() {
}); _ciudad = s;
});
}
} }
}); });
} }
@@ -380,27 +406,33 @@ class _ServiceScreenState extends State<ServiceScreen> {
AuthenticationRepository.instance AuthenticationRepository.instance
.getCoordsOfCity(uid.toString()) .getCoordsOfCity(uid.toString())
.then((String s) { .then((String s) {
setState(() { if (mounted) {
_coordsOfCity = s; setState(() {
_setInitialCameraPosition(_coordsOfCity); _coordsOfCity = s;
}); _setInitialCameraPosition(_coordsOfCity);
});
}
}); });
} }
_saveToken(); _saveToken();
if (user == null) { if (user == null) {
UserModel.getUser(uid.toString()).then( UserModel.getUser(uid.toString()).then((UserModel s) => (value) {
(UserModel s) => setState(() => user = s), if (mounted) {
); setState(() => user = s);
}
});
} }
BitmapDescriptor.fromAssetImage( BitmapDescriptor.fromAssetImage(
const ImageConfiguration(size: Size(6, 6)), 'images/pro_marke.png') const ImageConfiguration(size: Size(6, 6)), 'images/pro_marke.png')
.then((icon) { .then((icon) {
setState(() { if (mounted) {
_markerIcon = icon; setState(() {
}); _markerIcon = icon;
});
}
}); });
updateMarkersForServiceType(_serviceType); updateMarkersForServiceType(_serviceType);
@@ -456,9 +488,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
String? response = await NetworkUtility.fetchUrl(uri); String? response = await NetworkUtility.fetchUrl(uri);
if (response != null) { if (response != null) {
setState(() { if (mounted) {
_placesList = jsonDecode(response.toString())['results']; setState(() {
}); _placesList = jsonDecode(response.toString())['results'];
});
}
} }
} }
@@ -511,26 +545,28 @@ class _ServiceScreenState extends State<ServiceScreen> {
ubicacion = datos[1]; ubicacion = datos[1];
if (profesional != null) { if (profesional != null) {
setState(() { if (mounted) {
_profesionalController.text = setState(() {
profesional.name.toString(); _profesionalController.text =
professionalId = profesional.id; profesional.name.toString();
professionalTarifa = profesional.tarifa ?? 0; professionalId = profesional.id;
professionalUbicacion = profesional.ubicacion; professionalTarifa = profesional.tarifa ?? 0;
professionalAddress = _ubicationController.text; professionalUbicacion = profesional.ubicacion;
if (profesional.token != '') { professionalAddress = _ubicationController.text;
professionalToken = profesional.token!; if (profesional.token != '') {
print(professionalToken); professionalToken = profesional.token!;
} print(professionalToken);
}
if (ubicacion == 'sitio') { if (ubicacion == 'sitio') {
professionalAddress = profesional.realAddress; professionalAddress = profesional.realAddress;
_ubicationController.text = _ubicationController.text =
profesional.realAddress; profesional.realAddress;
latUser = profesional.latitude; latUser = profesional.latitude;
lngUser = profesional.longitude; lngUser = profesional.longitude;
} }
}); });
}
} }
} }
}, },
@@ -558,11 +594,13 @@ class _ServiceScreenState extends State<ServiceScreen> {
final lat = datos[1]; final lat = datos[1];
final lng = datos[2]; final lng = datos[2];
setState(() { if (mounted) {
_ubicationController.text = formattedAddress; setState(() {
latUser = lat; _ubicationController.text = formattedAddress;
lngUser = lng; latUser = lat;
}); lngUser = lng;
});
}
} }
}, },
decoration: const InputDecoration( decoration: const InputDecoration(
@@ -826,17 +864,21 @@ class _ServiceScreenState extends State<ServiceScreen> {
getLocationName( getLocationName(
coordinates.latitude, coordinates.longitude) coordinates.latitude, coordinates.longitude)
.then((locationName) { .then((locationName) {
setState(() { if (mounted) {
_locationController.text = locationName; setState(() {
}); _locationController.text = locationName;
});
}
}); });
} }
} }
}, },
onCameraMove: (position) { onCameraMove: (position) {
setState(() { if (mounted) {
coordinates = position.target; setState(() {
}); coordinates = position.target;
});
}
}, },
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>( Factory<OneSequenceGestureRecognizer>(
@@ -874,7 +916,9 @@ class _ServiceScreenState extends State<ServiceScreen> {
zoom: 17), zoom: 17),
), ),
); );
setState(() {}); if (mounted) {
setState(() {});
}
} catch (e) { } catch (e) {
Get.snackbar( Get.snackbar(
'ubicación desactivada', 'ubicación desactivada',
@@ -945,13 +989,16 @@ class _ServiceScreenState extends State<ServiceScreen> {
) as String?; ) as String?;
if (serviceType != null) { if (serviceType != null) {
setState(() { if (mounted) {
_serviceType = serviceType; setState(() {
_serviceTypeController.text = _serviceType = serviceType;
_serviceType; _serviceTypeController.text =
_serviceType;
updateMarkersForServiceType(_serviceType); updateMarkersForServiceType(
}); _serviceType);
});
}
} }
}, },
decoration: const InputDecoration( decoration: const InputDecoration(
@@ -984,56 +1031,59 @@ class _ServiceScreenState extends State<ServiceScreen> {
ubicacion = datos[1]; ubicacion = datos[1];
if (profesional != null) { if (profesional != null) {
setState(() { if (mounted) {
_profesionalController.text = setState(() {
profesional.name.toString(); _profesionalController.text =
profesional.name.toString();
professionalId = profesional.id; professionalId = profesional.id;
if (profesional.token != '') { if (profesional.token != '') {
professionalToken = professionalToken =
profesional.token!; profesional.token!;
}
professionalTarifa =
profesional.tarifa ?? 0;
professionalUbicacion =
profesional.ubicacion;
professionalLatitude =
profesional.latitude;
professionalLongitude =
profesional.longitude;
if (ubicacion == 'sitio') {
professionalAddress =
profesional.realAddress;
_locationController.text =
profesional.realAddress;
if (professionalLatitude !=
null &&
professionalLatitude != 0 &&
professionalLongitude !=
null &&
professionalLongitude != 0) {
googleMapController
?.animateCamera(
CameraUpdate
.newCameraPosition(
CameraPosition(
target: LatLng(
professionalLatitude!,
professionalLongitude!,
),
zoom: 17),
),
);
} }
}
}); professionalTarifa =
profesional.tarifa ?? 0;
professionalUbicacion =
profesional.ubicacion;
professionalLatitude =
profesional.latitude;
professionalLongitude =
profesional.longitude;
if (ubicacion == 'sitio') {
professionalAddress =
profesional.realAddress;
_locationController.text =
profesional.realAddress;
if (professionalLatitude !=
null &&
professionalLatitude != 0 &&
professionalLongitude !=
null &&
professionalLongitude !=
0) {
googleMapController
?.animateCamera(
CameraUpdate
.newCameraPosition(
CameraPosition(
target: LatLng(
professionalLatitude!,
professionalLongitude!,
),
zoom: 17),
),
);
}
}
});
}
} }
} }
}, },
@@ -1090,9 +1140,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
newCoordinates), newCoordinates),
); );
setState(() { if (mounted) {
_placesList = []; setState(() {
}); _placesList = [];
});
}
}, },
title: Text(_placesList[index] title: Text(_placesList[index]
['formatted_address']), ['formatted_address']),
@@ -1170,12 +1222,18 @@ class _ServiceScreenState extends State<ServiceScreen> {
hintText: 'Observaciones'), hintText: 'Observaciones'),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
ElevatedButton( PrimaryButton(
onPressed: () { onPressed: () {
if (user?.name == null || if (user?.name == null ||
user?.name == '' || user?.name == '' ||
user?.phoneNumber == null || user?.phoneNumber == null ||
user?.phoneNumber == '') { user?.phoneNumber == '') {
WarningSnackbar.show(
title: 'Completa tu perfil',
message:
'Diligencia la información de tu perfil antes de solicitar un servicio.',
);
Navigator.push( Navigator.push(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
@@ -1247,23 +1305,9 @@ class _ServiceScreenState extends State<ServiceScreen> {
} }
} }
}, },
style: ElevatedButton.styleFrom( text: 'Solicitar servicio',
backgroundColor: const Color(0xFF2BA4EC), minWidth: 230,
shape: RoundedRectangleBorder( )
borderRadius: BorderRadius.circular(50),
),
elevation: 0,
minimumSize: const Size(230, 50),
),
child: const Text(
'Solicitar servicio',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
], ],
), ),
), ),
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
class PrimaryCheckbox extends StatelessWidget {
final String text;
final bool initialValue;
final Function(bool) onChanged;
const PrimaryCheckbox({
Key? key,
required this.text,
required this.initialValue,
required this.onChanged,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return CheckboxListTile(
title: Text(
text,
style: const TextStyle(fontSize: 15),
),
value: initialValue,
onChanged: (value) {
onChanged(value!);
},
);
}
}
@@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class WarningSnackbar {
static void show({
required String title,
required String message,
SnackPosition position = SnackPosition.TOP,
Duration duration = const Duration(seconds: 4),
Color backgroundColor = Colors.red,
Color textColor = Colors.white,
double borderRadius = 10.0,
EdgeInsets margin = const EdgeInsets.all(10.0),
SnackStyle snackStyle = SnackStyle.FLOATING,
Duration animationDuration = const Duration(milliseconds: 800),
bool isDismissible = true,
DismissDirection dismissDirection = DismissDirection.horizontal,
Curve forwardAnimationCurve = Curves.easeOutBack,
Curve reverseAnimationCurve = Curves.easeInBack,
Icon icon = const Icon(Icons.warning, color: Colors.white),
bool shouldIconPulse = true,
}) {
Get.snackbar(
title,
message,
snackPosition: position,
duration: duration,
backgroundColor: backgroundColor,
colorText: textColor,
borderRadius: borderRadius,
margin: margin,
snackStyle: snackStyle,
animationDuration: animationDuration,
isDismissible: isDismissible,
dismissDirection: dismissDirection,
forwardAnimationCurve: forwardAnimationCurve,
reverseAnimationCurve: reverseAnimationCurve,
icon: icon,
shouldIconPulse: shouldIconPulse,
titleText: Text(
title,
style: const TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold, color: Colors.white),
),
messageText: Text(
message,
style: const TextStyle(fontSize: 16.0, color: Colors.white),
),
);
}
}
+19 -17
View File
@@ -1,7 +1,6 @@
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
class FirebaseMessagingService { class FirebaseMessagingService {
FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
@@ -21,32 +20,35 @@ class FirebaseMessagingService {
print('Token FCM: $token'); print('Token FCM: $token');
FirebaseMessaging.onMessage.listen((RemoteMessage message) { FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Mensaje FCM recibido: ${message.notification?.title} - ${message.notification?.body}'); print(
'Mensaje FCM recibido: ${message.notification?.title} - ${message.notification?.body}');
// Obtener el valor de la clave "screen" de los datos de la notificación // Obtener el valor de la clave "screen" de los datos de la notificación
String? notificationScreen = message.data['screen']; String? notificationScreen = message.data['screen'];
// Navegar a la pantalla correspondiente según el valor de la clave "screen"
if (notificationScreen == "misservicios") {
// Navegar a MyServicesScreen
Get.offNamed('/misservicios');
} else if (notificationScreen == "solicitud") {
// Navegar a SolicitudScreen
Get.offNamed('/solicitud');
}
});
// Navegar a la pantalla correspondiente según el valor de la clave "screen"
if (notificationScreen == "misservicios") {
// Navegar a MyServicesScreen
Get.offNamed('/misservicios');
} else if (notificationScreen == "solicitud") {
// Navegar a SolicitudScreen
Get.offNamed('/solicitud');
}
});
// Manejar la notificación cuando se toca y la aplicación está en primer plano (opcional) // Manejar la notificación cuando se toca y la aplicación está en primer plano (opcional)
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('Mensaje FCM abierto desde la aplicación en primer plano: ${message.notification?.title} - ${message.notification?.body}'); print(
'Mensaje FCM abierto desde la aplicación en primer plano: ${message.notification?.title} - ${message.notification?.body}');
// Aquí puedes redirigir al usuario a una pantalla específica o realizar acciones según los datos recibidos // Aquí puedes redirigir al usuario a una pantalla específica o realizar acciones según los datos recibidos
}); });
// Manejar la notificación cuando se toca y la aplicación está cerrada (opcional) // Manejar la notificación cuando se toca y la aplicación está cerrada (opcional)
RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) { if (initialMessage != null) {
print('Mensaje FCM abierto desde la aplicación cerrada: ${initialMessage.notification?.title} - ${initialMessage.notification?.body}'); print(
'Mensaje FCM abierto desde la aplicación cerrada: ${initialMessage.notification?.title} - ${initialMessage.notification?.body}');
// Aquí puedes redirigir al usuario a una pantalla específica o realizar acciones según los datos recibidos // Aquí puedes redirigir al usuario a una pantalla específica o realizar acciones según los datos recibidos
} }
} }
+1 -1
View File
@@ -51,7 +51,7 @@ dependencies:
flutter_animate: flutter_animate:
flutter_rating_bar: flutter_rating_bar:
table_calendar: table_calendar:
google_maps_flutter: ^2.2.5 google_maps_flutter: ^2.5.0
flutter_polyline_points: ^2.0.0 flutter_polyline_points: ^2.0.0
http: ^1.1.0 http: ^1.1.0
geolocator: ^9.0.2 geolocator: ^9.0.2