update
This commit is contained in:
@@ -187,6 +187,34 @@ class AuthenticationRepository extends GetxController {
|
||||
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 {
|
||||
String coords = '';
|
||||
try {
|
||||
|
||||
@@ -30,9 +30,11 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
SettingModel? settings;
|
||||
|
||||
void _clearPhoneNumber() {
|
||||
setState(() {
|
||||
controller.phoneNo.text = '';
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
controller.phoneNo.text = '';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _launchURL(String url) async {
|
||||
@@ -47,11 +49,13 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (settings == null) {
|
||||
SettingModel.getSettings().then(
|
||||
(SettingModel value) => setState(() {
|
||||
settings = value;
|
||||
}),
|
||||
);
|
||||
SettingModel.getSettings().then((SettingModel value) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
settings = value;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,12 +186,12 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
PhoneAuthController.instance.phoneAuthentication(
|
||||
completePhoneNumber.trim(),
|
||||
);
|
||||
_clearPhoneNumber();
|
||||
await Get.to(
|
||||
() => CodeValidationScreen(
|
||||
phoneNumber: completePhoneNumber.trim(),
|
||||
),
|
||||
);
|
||||
_clearPhoneNumber();
|
||||
Provider.of<UserProvider>(context, listen: false)
|
||||
.initUserProvider();
|
||||
}
|
||||
|
||||
@@ -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/scores_model.dart';
|
||||
import 'package:prosappco/src/presentation/screens/cita.dart';
|
||||
import 'package:prosappco/src/presentation/screens/score.dart';
|
||||
|
||||
class MyServicesScreen extends StatelessWidget {
|
||||
MyServicesScreen({super.key});
|
||||
@@ -54,6 +55,7 @@ class MyServicesScreen extends StatelessWidget {
|
||||
.asyncMap((snapshot) async {
|
||||
try {
|
||||
List<Event> eventos = [];
|
||||
|
||||
for (var element in snapshot.docs) {
|
||||
final event = Event.fromJson(element.data());
|
||||
event.scoresModel =
|
||||
@@ -79,8 +81,10 @@ class MyServicesScreen extends StatelessWidget {
|
||||
try {
|
||||
eventos.addAll(snapshot.data!);
|
||||
eventos.sort((a, b) => a.timeStamp!.compareTo(b.timeStamp!));
|
||||
|
||||
print('snapshot mi b ${eventos}');
|
||||
} catch (e) {
|
||||
print("Error" + e.toString());
|
||||
print("Error snapshot" + e.toString());
|
||||
}
|
||||
|
||||
if (eventos.isEmpty) {
|
||||
@@ -122,14 +126,39 @@ class MyServicesScreen extends StatelessWidget {
|
||||
? Colors.red[100]
|
||||
: Colors.blue[100],
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return CitaScreen(evento: event);
|
||||
},
|
||||
),
|
||||
);
|
||||
if (event.status == 'terminado') {
|
||||
if (event.userId == uid) {
|
||||
if (event.userScored) {
|
||||
Navigator.push(
|
||||
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'
|
||||
? 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/scores_model.dart';
|
||||
import 'package:prosappco/src/presentation/screens/cita.dart';
|
||||
import 'package:prosappco/src/presentation/screens/score.dart';
|
||||
|
||||
class MyServicesProScreen extends StatelessWidget {
|
||||
MyServicesProScreen({super.key});
|
||||
@@ -98,14 +99,38 @@ class MyServicesProScreen extends StatelessWidget {
|
||||
? Colors.red[100]
|
||||
: Colors.blue[100],
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return CitaScreen(evento: event);
|
||||
},
|
||||
),
|
||||
);
|
||||
if (event.status == 'terminado') {
|
||||
if (event.professionalId == uid) {
|
||||
if (event.professionalScored) {
|
||||
Navigator.push(
|
||||
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'
|
||||
? const Column(
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
import 'package:prosappco/src/presentation/screens/support.dart';
|
||||
|
||||
final CollectionReference professionsCollection =
|
||||
FirebaseFirestore.instance.collection('professions');
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.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
|
||||
@@ -156,7 +184,38 @@ class _ProfessionalInfoScreenState extends State<ProfessionalInfoScreen> {
|
||||
),
|
||||
)
|
||||
: 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(
|
||||
'Se unió el 02 de abril del 2023',
|
||||
style: TextStyle(fontSize: 12),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_storage/firebase_storage.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -25,7 +24,6 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
||||
File? image_cedula;
|
||||
File? image_certificado;
|
||||
|
||||
late final FirebaseAuth _auth;
|
||||
final FirebaseStorage storage = FirebaseStorage.instance;
|
||||
|
||||
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||
@@ -44,7 +42,6 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_auth = FirebaseAuth.instance;
|
||||
if (_photo == '...') {
|
||||
AuthenticationRepository.instance
|
||||
.getPhoto(uid.toString())
|
||||
|
||||
@@ -43,13 +43,14 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
var _photo = '...';
|
||||
String? _email = '';
|
||||
String gender = '';
|
||||
String genderDb = '';
|
||||
DateTime? birthDate;
|
||||
String birthDateDb = '';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||
_auth = FirebaseAuth.instance;
|
||||
|
||||
final currentUser = _auth.currentUser;
|
||||
@@ -65,22 +66,40 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
_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;
|
||||
|
||||
if (_ciudad == '...') {
|
||||
AuthenticationRepository.instance
|
||||
.getCity(uid.toString())
|
||||
.then((String s) => setState(() {
|
||||
_ciudad = s;
|
||||
}));
|
||||
AuthenticationRepository.instance.getCity(uid.toString()).then(
|
||||
(String s) => setState(() {
|
||||
_ciudad = s;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (_photo == '...') {
|
||||
AuthenticationRepository.instance
|
||||
.getPhoto(uid.toString())
|
||||
.then((String s) => setState(() {
|
||||
_photo = s;
|
||||
}));
|
||||
AuthenticationRepository.instance.getPhoto(uid.toString()).then(
|
||||
(String s) => setState(() {
|
||||
_photo = s;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +240,32 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
String newEmail = _emailController.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) {
|
||||
Get.snackbar(
|
||||
'Nombre Invalido',
|
||||
@@ -281,7 +326,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
.doc(uid)
|
||||
.update({'email': newEmail});
|
||||
} catch (e) {
|
||||
print('e');
|
||||
print('Error al actualizar la imagen de perfil $e');
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -296,7 +341,11 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
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(
|
||||
@@ -435,7 +484,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
'Inicia sesión para asegurarnos de que seas tú.',
|
||||
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),
|
||||
GenderDropdown(
|
||||
onChanged: (selectedGender) {
|
||||
setState(() {
|
||||
gender = selectedGender;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
BirthDatePicker(
|
||||
onDateSelected: (birthDay) {
|
||||
setState(() {
|
||||
birthDate = birthDay;
|
||||
});
|
||||
},
|
||||
controller: TextEditingController(
|
||||
text: birthDate == null
|
||||
? ''
|
||||
: formatter.format(birthDate!),
|
||||
),
|
||||
),
|
||||
genderDb == ''
|
||||
? GenderDropdown(
|
||||
onChanged: (selectedGender) {
|
||||
setState(() {
|
||||
gender = selectedGender;
|
||||
});
|
||||
},
|
||||
)
|
||||
: const SizedBox(),
|
||||
genderDb == ''
|
||||
? const SizedBox(height: 20.0)
|
||||
: const SizedBox(),
|
||||
birthDateDb == ''
|
||||
? BirthDatePicker(
|
||||
onDateSelected: (birthDay) {
|
||||
setState(() {
|
||||
birthDate = birthDay;
|
||||
});
|
||||
},
|
||||
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/components/banner_photo.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/models/setting_model.dart';
|
||||
import 'package:prosappco/src/presentation/screens/horario.dart';
|
||||
import 'package:prosappco/src/presentation/screens/professional.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';
|
||||
|
||||
class ProfileProScreen extends StatefulWidget {
|
||||
@@ -47,8 +48,18 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
int _tarifa = 0;
|
||||
SettingModel? settings;
|
||||
|
||||
bool nequiValue = false;
|
||||
bool banktransferValue = false;
|
||||
bool datafoneValue = false;
|
||||
|
||||
Map<String, Schedule>? _horarios;
|
||||
|
||||
Map<String, bool> paymentMethods = {
|
||||
'Nequi': false,
|
||||
'Transferencia Bancaria': false,
|
||||
'Datafono': false,
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -131,6 +142,8 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
loadPaymentMethods();
|
||||
}
|
||||
|
||||
void createSchedules() async {
|
||||
@@ -276,6 +289,8 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
print('Error al actualizar la imagen de perfil $e');
|
||||
}
|
||||
|
||||
updatePaymentMethods();
|
||||
|
||||
Get.snackbar(
|
||||
'Información actualizada',
|
||||
'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
|
||||
Widget build(BuildContext context) {
|
||||
String address = _direccion.toString();
|
||||
@@ -522,6 +553,33 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
)
|
||||
: const SizedBox(),
|
||||
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(
|
||||
padding: EdgeInsets.symmetric(horizontal: 30),
|
||||
child: SizedBox(
|
||||
@@ -530,7 +588,7 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
'Horario estandar',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 15,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -666,15 +724,14 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
PrimaryButtom(
|
||||
onPressed: () {
|
||||
updateInfo();
|
||||
// name();
|
||||
},
|
||||
label: 'Guardar'),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
)
|
||||
const SizedBox(height: 10),
|
||||
PrimaryButton(
|
||||
onPressed: () {
|
||||
updateInfo();
|
||||
},
|
||||
text: 'Guardar',
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -26,6 +26,8 @@ import 'package:prosappco/src/presentation/screens/ubicacion.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:prosappco/src/components/network_utility.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';
|
||||
|
||||
class ServiceScreen extends StatefulWidget {
|
||||
@@ -178,9 +180,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
);
|
||||
|
||||
if (picked != null && picked != _selectedDate) {
|
||||
setState(() {
|
||||
_selectedDate = picked;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_selectedDate = picked;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,9 +195,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
);
|
||||
|
||||
if (pickedTime != null) {
|
||||
setState(() {
|
||||
_selectedTime = pickedTime;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_selectedTime = pickedTime;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,13 +258,25 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
setState(() {});
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_locationController.dispose();
|
||||
_ubicationController.dispose();
|
||||
_profesionalController.dispose();
|
||||
_serviceTypeController.dispose();
|
||||
_observacionController.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void updateMarkersForServiceType(String serviceType) {
|
||||
getUsersWithActiveStatus(serviceType).then((value) {
|
||||
markers.clear();
|
||||
@@ -287,9 +305,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
String version = packageInfo.version;
|
||||
|
||||
setState(() {
|
||||
appVersion = version;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
appVersion = version;
|
||||
});
|
||||
}
|
||||
|
||||
if (settings != null) {
|
||||
_checkForUpdate(settings);
|
||||
@@ -348,12 +368,14 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
}
|
||||
|
||||
if (settings == null) {
|
||||
SettingModel.getSettings().then(
|
||||
(SettingModel value) => setState(() {
|
||||
settings = value.version;
|
||||
_getAppVersion();
|
||||
}),
|
||||
);
|
||||
SettingModel.getSettings().then((SettingModel value) => (value) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
settings = value.version;
|
||||
_getAppVersion();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (_ciudad == '...') {
|
||||
@@ -364,14 +386,18 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
FirebaseFirestore.instance.collection('users').doc(uid).set({
|
||||
'city': 'Cúcuta',
|
||||
}).then((_) {
|
||||
setState(() {
|
||||
_ciudad = 'Cúcuta';
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_ciudad = 'Cúcuta';
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_ciudad = s;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_ciudad = s;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -380,27 +406,33 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
AuthenticationRepository.instance
|
||||
.getCoordsOfCity(uid.toString())
|
||||
.then((String s) {
|
||||
setState(() {
|
||||
_coordsOfCity = s;
|
||||
_setInitialCameraPosition(_coordsOfCity);
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_coordsOfCity = s;
|
||||
_setInitialCameraPosition(_coordsOfCity);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_saveToken();
|
||||
|
||||
if (user == null) {
|
||||
UserModel.getUser(uid.toString()).then(
|
||||
(UserModel s) => setState(() => user = s),
|
||||
);
|
||||
UserModel.getUser(uid.toString()).then((UserModel s) => (value) {
|
||||
if (mounted) {
|
||||
setState(() => user = s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
BitmapDescriptor.fromAssetImage(
|
||||
const ImageConfiguration(size: Size(6, 6)), 'images/pro_marke.png')
|
||||
.then((icon) {
|
||||
setState(() {
|
||||
_markerIcon = icon;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_markerIcon = icon;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
updateMarkersForServiceType(_serviceType);
|
||||
@@ -456,9 +488,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
String? response = await NetworkUtility.fetchUrl(uri);
|
||||
|
||||
if (response != null) {
|
||||
setState(() {
|
||||
_placesList = jsonDecode(response.toString())['results'];
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_placesList = jsonDecode(response.toString())['results'];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,26 +545,28 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
ubicacion = datos[1];
|
||||
|
||||
if (profesional != null) {
|
||||
setState(() {
|
||||
_profesionalController.text =
|
||||
profesional.name.toString();
|
||||
professionalId = profesional.id;
|
||||
professionalTarifa = profesional.tarifa ?? 0;
|
||||
professionalUbicacion = profesional.ubicacion;
|
||||
professionalAddress = _ubicationController.text;
|
||||
if (profesional.token != '') {
|
||||
professionalToken = profesional.token!;
|
||||
print(professionalToken);
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_profesionalController.text =
|
||||
profesional.name.toString();
|
||||
professionalId = profesional.id;
|
||||
professionalTarifa = profesional.tarifa ?? 0;
|
||||
professionalUbicacion = profesional.ubicacion;
|
||||
professionalAddress = _ubicationController.text;
|
||||
if (profesional.token != '') {
|
||||
professionalToken = profesional.token!;
|
||||
print(professionalToken);
|
||||
}
|
||||
|
||||
if (ubicacion == 'sitio') {
|
||||
professionalAddress = profesional.realAddress;
|
||||
_ubicationController.text =
|
||||
profesional.realAddress;
|
||||
latUser = profesional.latitude;
|
||||
lngUser = profesional.longitude;
|
||||
}
|
||||
});
|
||||
if (ubicacion == 'sitio') {
|
||||
professionalAddress = profesional.realAddress;
|
||||
_ubicationController.text =
|
||||
profesional.realAddress;
|
||||
latUser = profesional.latitude;
|
||||
lngUser = profesional.longitude;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -558,11 +594,13 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
final lat = datos[1];
|
||||
final lng = datos[2];
|
||||
|
||||
setState(() {
|
||||
_ubicationController.text = formattedAddress;
|
||||
latUser = lat;
|
||||
lngUser = lng;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_ubicationController.text = formattedAddress;
|
||||
latUser = lat;
|
||||
lngUser = lng;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
@@ -826,17 +864,21 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
getLocationName(
|
||||
coordinates.latitude, coordinates.longitude)
|
||||
.then((locationName) {
|
||||
setState(() {
|
||||
_locationController.text = locationName;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_locationController.text = locationName;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
onCameraMove: (position) {
|
||||
setState(() {
|
||||
coordinates = position.target;
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
coordinates = position.target;
|
||||
});
|
||||
}
|
||||
},
|
||||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
||||
Factory<OneSequenceGestureRecognizer>(
|
||||
@@ -874,7 +916,9 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
zoom: 17),
|
||||
),
|
||||
);
|
||||
setState(() {});
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
'ubicación desactivada',
|
||||
@@ -945,13 +989,16 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
) as String?;
|
||||
|
||||
if (serviceType != null) {
|
||||
setState(() {
|
||||
_serviceType = serviceType;
|
||||
_serviceTypeController.text =
|
||||
_serviceType;
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_serviceType = serviceType;
|
||||
_serviceTypeController.text =
|
||||
_serviceType;
|
||||
|
||||
updateMarkersForServiceType(_serviceType);
|
||||
});
|
||||
updateMarkersForServiceType(
|
||||
_serviceType);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
@@ -984,56 +1031,59 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
ubicacion = datos[1];
|
||||
|
||||
if (profesional != null) {
|
||||
setState(() {
|
||||
_profesionalController.text =
|
||||
profesional.name.toString();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_profesionalController.text =
|
||||
profesional.name.toString();
|
||||
|
||||
professionalId = profesional.id;
|
||||
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;
|
||||
|
||||
_locationController.text =
|
||||
profesional.realAddress;
|
||||
|
||||
if (professionalLatitude !=
|
||||
null &&
|
||||
professionalLatitude != 0 &&
|
||||
professionalLongitude !=
|
||||
null &&
|
||||
professionalLongitude != 0) {
|
||||
googleMapController
|
||||
?.animateCamera(
|
||||
CameraUpdate
|
||||
.newCameraPosition(
|
||||
CameraPosition(
|
||||
target: LatLng(
|
||||
professionalLatitude!,
|
||||
professionalLongitude!,
|
||||
),
|
||||
zoom: 17),
|
||||
),
|
||||
);
|
||||
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;
|
||||
|
||||
_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),
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_placesList = [];
|
||||
});
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_placesList = [];
|
||||
});
|
||||
}
|
||||
},
|
||||
title: Text(_placesList[index]
|
||||
['formatted_address']),
|
||||
@@ -1170,12 +1222,18 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
hintText: 'Observaciones'),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ElevatedButton(
|
||||
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(
|
||||
@@ -1247,23 +1305,9 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
}
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2BA4EC),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
text: 'Solicitar servicio',
|
||||
minWidth: 230,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
|
||||
class FirebaseMessagingService {
|
||||
FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
|
||||
|
||||
@@ -21,32 +20,35 @@ class FirebaseMessagingService {
|
||||
print('Token FCM: $token');
|
||||
|
||||
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
|
||||
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');
|
||||
}
|
||||
});
|
||||
// Obtener el valor de la clave "screen" de los datos de la notificación
|
||||
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');
|
||||
}
|
||||
});
|
||||
|
||||
// Manejar la notificación cuando se toca y la aplicación está en primer plano (opcional)
|
||||
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
|
||||
});
|
||||
|
||||
// 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) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ dependencies:
|
||||
flutter_animate:
|
||||
flutter_rating_bar:
|
||||
table_calendar:
|
||||
google_maps_flutter: ^2.2.5
|
||||
google_maps_flutter: ^2.5.0
|
||||
flutter_polyline_points: ^2.0.0
|
||||
http: ^1.1.0
|
||||
geolocator: ^9.0.2
|
||||
|
||||
Reference in New Issue
Block a user