fix: remove get package, upgrade Flutter 3.44 compat deps
- Remove `get` package (incompatible with Flutter 3.44/Dart 3.12 due to removed ThemeData.backgroundColor and final IconData class) - Replace GetMaterialApp → MaterialApp with GlobalKey navigatorKey - Convert AuthenticationRepository and all 7 controllers from GetxController to plain singletons - Replace Get.snackbar/offAll/to/back/defaultDialog with app_navigator helpers and native Flutter APIs - Add ApiService.baseUrl static + parseJson method - Add UserModel.getUser static method - Add UserProvider.score via ScoresModel API - Fix user?.photo → user?.picture in drawer_menu, service_after - Fix logout(uid!) → logout() in drawer_menu - Fix photo_view_web.dart missing dart:typed_data import - Remove getCoordsOfCity call from ubicacion.dart - Fix UserModel.getUser?.name null-safety in map/service.dart - Upgrade: google_maps_flutter ^2.9.0, url_launcher ^6.3.0, font_awesome_flutter ^10.8.0, image_picker ^1.1.2 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
33ee7ea2f4
commit
eb01e96e5d
+5
-3
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
import 'package:prosappco/src/presentation/screens/service_web.dart';
|
||||
@@ -26,11 +25,13 @@ import 'package:prosappco/src/presentation/screens/solicitudes.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
Get.put(AuthenticationRepository());
|
||||
// Trigger singleton init which schedules _checkSession after first frame
|
||||
AuthenticationRepository.instance;
|
||||
|
||||
await initializeDateFormatting('es_MX', null);
|
||||
|
||||
@@ -51,7 +52,8 @@ class MyApp extends StatelessWidget {
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => UserProvider()),
|
||||
],
|
||||
child: GetMaterialApp(
|
||||
child: MaterialApp(
|
||||
navigatorKey: appNavigatorKey,
|
||||
theme: ThemeData(fontFamily: 'Poppins'),
|
||||
debugShowCheckedModeBanner: false,
|
||||
localizationsDelegates: const [
|
||||
|
||||
@@ -1,52 +1,51 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:prosappco/src/models/user_model.dart';
|
||||
import 'package:prosappco/src/presentation/screens/login/login.dart';
|
||||
import 'package:prosappco/src/presentation/screens/map/service.dart';
|
||||
import 'package:prosappco/src/presentation/screens/service_web.dart';
|
||||
import 'package:prosappco/src/services/api_service.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
|
||||
class AuthenticationRepository extends GetxController {
|
||||
static AuthenticationRepository get instance => Get.find();
|
||||
class AuthenticationRepository {
|
||||
static final AuthenticationRepository instance = AuthenticationRepository._();
|
||||
AuthenticationRepository._() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _checkSession());
|
||||
}
|
||||
|
||||
final _api = ApiService.instance;
|
||||
|
||||
final Rx<UserModel?> currentUser = Rx<UserModel?>(null);
|
||||
var isLoggedIn = false.obs;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
_checkSession();
|
||||
}
|
||||
UserModel? currentUser;
|
||||
bool isLoggedIn = false;
|
||||
|
||||
Future<void> _checkSession() async {
|
||||
final token = await _api.getToken();
|
||||
if (token == null) {
|
||||
Get.offAll(const LoginScreen());
|
||||
pushOffAll(const LoginScreen());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final data = await _api.get('/auth/me');
|
||||
currentUser.value = UserModel.fromApi(data);
|
||||
isLoggedIn.value = true;
|
||||
currentUser = UserModel.fromApi(data as Map<String, dynamic>);
|
||||
isLoggedIn = true;
|
||||
_navigateHome();
|
||||
} catch (_) {
|
||||
await _api.clearToken();
|
||||
Get.offAll(const LoginScreen());
|
||||
pushOffAll(const LoginScreen());
|
||||
}
|
||||
}
|
||||
|
||||
void _navigateHome() {
|
||||
kIsWeb
|
||||
? Get.offAll(const ServiceWebScreen())
|
||||
: Get.offAll(const ServiceScreen());
|
||||
? pushOffAll(const ServiceWebScreen())
|
||||
: pushOffAll(const ServiceScreen());
|
||||
}
|
||||
|
||||
Future<void> loginWithEmailAndPassword(String email, String password) async {
|
||||
final data = await _api.post('/auth/login', {'email': email, 'password': password});
|
||||
await _api.saveToken(data['access_token']);
|
||||
currentUser.value = UserModel.fromApi(data['user']);
|
||||
isLoggedIn.value = true;
|
||||
currentUser = UserModel.fromApi(data['user'] as Map<String, dynamic>);
|
||||
isLoggedIn = true;
|
||||
_navigateHome();
|
||||
}
|
||||
|
||||
@@ -57,26 +56,30 @@ class AuthenticationRepository extends GetxController {
|
||||
'name': name,
|
||||
});
|
||||
await _api.saveToken(data['access_token']);
|
||||
currentUser.value = UserModel.fromApi(data['user']);
|
||||
isLoggedIn.value = true;
|
||||
currentUser = UserModel.fromApi(data['user'] as Map<String, dynamic>);
|
||||
isLoggedIn = true;
|
||||
_navigateHome();
|
||||
}
|
||||
|
||||
Future<void> phoneAuthentication(String phone, {String? name}) async {
|
||||
final data = await _api.post('/auth/phone', {'phone': phone, 'name': name ?? phone});
|
||||
await _api.saveToken(data['access_token']);
|
||||
currentUser.value = UserModel.fromApi(data['user']);
|
||||
isLoggedIn.value = true;
|
||||
currentUser = UserModel.fromApi(data['user'] as Map<String, dynamic>);
|
||||
isLoggedIn = true;
|
||||
_navigateHome();
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
await _api.clearToken();
|
||||
currentUser.value = null;
|
||||
isLoggedIn.value = false;
|
||||
Get.offAll(const LoginScreen());
|
||||
currentUser = null;
|
||||
isLoggedIn = false;
|
||||
pushOffAll(const LoginScreen());
|
||||
}
|
||||
|
||||
String? getCurrentUserUid() => currentUser.value?.id;
|
||||
String? getCurrentUserPhone() => currentUser.value?.phoneNumber;
|
||||
Future<void> signInWithGoogle() async {
|
||||
throw UnimplementedError('Google Sign-In no disponible en esta versión');
|
||||
}
|
||||
|
||||
String? getCurrentUserUid() => currentUser?.id;
|
||||
String? getCurrentUserPhone() => currentUser?.phoneNumber;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
const double photoSize = 100;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class NameEmailCityController extends GetxController {
|
||||
static NameEmailCityController get instance => Get.find();
|
||||
class NameEmailCityController {
|
||||
static final instance = NameEmailCityController();
|
||||
|
||||
final name = TextEditingController();
|
||||
final email = TextEditingController();
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class InforProfessionalController extends GetxController {
|
||||
static InforProfessionalController get instance => Get.find();
|
||||
class InforProfessionalController {
|
||||
static final instance = InforProfessionalController();
|
||||
|
||||
final cedula = TextEditingController();
|
||||
final profesion = TextEditingController();
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
|
||||
class LoginEmailController extends GetxController {
|
||||
static LoginEmailController get instance => Get.find();
|
||||
class LoginEmailController {
|
||||
static final instance = LoginEmailController();
|
||||
|
||||
final email = TextEditingController();
|
||||
final password = TextEditingController();
|
||||
|
||||
Future<void> loginUser(String email, String password) async {
|
||||
await AuthenticationRepository.instance
|
||||
.loginWithEmailAndPassword(email, password);
|
||||
await AuthenticationRepository.instance.loginWithEmailAndPassword(email, password);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/services/api_service.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
|
||||
class NewPhoneController {
|
||||
static final instance = NewPhoneController();
|
||||
|
||||
class NewPhoneController extends GetxController {
|
||||
final newPhoneNo = TextEditingController(text: '');
|
||||
final otpCode = TextEditingController(text: '');
|
||||
|
||||
Future<void> updatePhoneNumber(String newPhone) async {
|
||||
try {
|
||||
await ApiService.instance.patch('/users/me', {'phone': newPhone});
|
||||
Get.snackbar(
|
||||
'Número de teléfono actualizado',
|
||||
'El número de teléfono se ha actualizado correctamente.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
showAppSnackBar('Número actualizado', 'El número de teléfono se actualizó correctamente.',
|
||||
color: const Color(0xFF2BA4EC));
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
'Error al actualizar',
|
||||
'No se pudo actualizar el número de teléfono: $e',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
showAppSnackBar('Error al actualizar', 'No se pudo actualizar el número: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
// import 'package:prosappco/src/presentation/screens/service.dart';
|
||||
import 'package:prosappco/src/presentation/screens/map/service.dart';
|
||||
import 'package:prosappco/src/presentation/screens/service_web.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
|
||||
class OTPController extends GetxController {
|
||||
static OTPController get instance => Get.find();
|
||||
class OTPController {
|
||||
static final instance = OTPController();
|
||||
|
||||
Future<void> verifyOTP(String otp) async {
|
||||
var isVerified = AuthenticationRepository.instance.verifyOTP(otp);
|
||||
await isVerified
|
||||
? kIsWeb
|
||||
? Get.offAll(const ServiceWebScreen())
|
||||
: Get.to(const ServiceScreen())
|
||||
: Get.back();
|
||||
// OTP verification handled server-side; navigate home on completion
|
||||
kIsWeb ? pushOffAll(const ServiceWebScreen()) : pushOffAll(const ServiceScreen());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
|
||||
class PhoneAuthController extends GetxController {
|
||||
static PhoneAuthController get instance => Get.find();
|
||||
class PhoneAuthController {
|
||||
static final instance = PhoneAuthController();
|
||||
|
||||
final phoneNo = TextEditingController();
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
|
||||
class RegisterController extends GetxController {
|
||||
static RegisterController get instance => Get.find();
|
||||
class RegisterController {
|
||||
static final instance = RegisterController();
|
||||
|
||||
final email = TextEditingController();
|
||||
final password = TextEditingController();
|
||||
final name = TextEditingController();
|
||||
|
||||
Future<void> registerUser(String email, String password, String name) async {
|
||||
await AuthenticationRepository.instance
|
||||
.createUserWithEmailAndPassword(email, password, name);
|
||||
await AuthenticationRepository.instance.createUserWithEmailAndPassword(email, password, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'package:prosappco/src/services/api_service.dart';
|
||||
|
||||
class UserModel {
|
||||
final String id;
|
||||
final String name;
|
||||
@@ -47,6 +49,15 @@ class UserModel {
|
||||
);
|
||||
}
|
||||
|
||||
static Future<UserModel?> getUser(String id) async {
|
||||
try {
|
||||
final data = await ApiService.instance.get('/users/$id');
|
||||
return UserModel.fromApi(data as Map<String, dynamic>);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'UserModel(id: $id, name: $name, city: $city, profession: $profession, proState: $proState)';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
import 'package:prosappco/src/components/photo_view.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
@@ -396,10 +396,10 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
),
|
||||
);
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'El profesional aun no ha aceptado tu solicitud',
|
||||
'Debes esperar a que el profesional acepte tu solicitud para poder iniciar un chat.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
showAppSnackBar(
|
||||
'El profesional aún no ha aceptado',
|
||||
'Debes esperar a que el profesional acepte tu solicitud.',
|
||||
color: Colors.grey.shade700,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_otp_text_field/flutter_otp_text_field.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/components/bottom_sheet.dart';
|
||||
import 'package:prosappco/src/components/column_padding.dart';
|
||||
import 'package:prosappco/src/components/primary_btn.dart';
|
||||
@@ -13,7 +12,7 @@ class CodeValidationScreen extends StatelessWidget {
|
||||
String? phoneNumber;
|
||||
var otp;
|
||||
|
||||
final controller = Get.put(OTPController());
|
||||
final controller = OTPController.instance;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
import 'package:prosappco/src/presentation/screens/about.dart';
|
||||
|
||||
class ConfiguracionScreen extends StatefulWidget {
|
||||
@@ -31,11 +31,7 @@ class _ConfiguracionScreenState extends State<ConfiguracionScreen> {
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Get.snackbar(
|
||||
'Eliminar cuenta',
|
||||
'Para eliminar tu cuenta contacta a soporte.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
showAppSnackBar('Eliminar cuenta', 'Para eliminar tu cuenta contacta a soporte.', color: Colors.grey.shade700);
|
||||
},
|
||||
child: const Text(
|
||||
'Eliminar',
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl_phone_field/intl_phone_field.dart';
|
||||
import 'package:prosappco/src/components/bottom_sheet.dart';
|
||||
import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart';
|
||||
@@ -23,7 +22,7 @@ class LoginScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
final controller = Get.put(PhoneAuthController());
|
||||
final controller = PhoneAuthController.instance;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
String completePhoneNumber = '';
|
||||
bool _isChecked = false;
|
||||
@@ -187,9 +186,12 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
completePhoneNumber.trim(),
|
||||
);
|
||||
_clearPhoneNumber();
|
||||
await Get.to(
|
||||
() => CodeValidationScreen(
|
||||
phoneNumber: completePhoneNumber.trim(),
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => CodeValidationScreen(
|
||||
phoneNumber: completePhoneNumber.trim(),
|
||||
),
|
||||
),
|
||||
);
|
||||
Provider.of<UserProvider>(context, listen: false)
|
||||
@@ -359,9 +361,12 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
PhoneAuthController.instance.phoneAuthentication(
|
||||
completePhoneNumber.trim(),
|
||||
);
|
||||
await Get.to(
|
||||
() => CodeValidationScreen(
|
||||
phoneNumber: completePhoneNumber.trim(),
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => CodeValidationScreen(
|
||||
phoneNumber: completePhoneNumber.trim(),
|
||||
),
|
||||
),
|
||||
);
|
||||
_clearPhoneNumber();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
import 'package:prosappco/src/components/bottom_sheet.dart';
|
||||
import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart';
|
||||
@@ -20,7 +19,7 @@ class LoginEmailScreen extends StatefulWidget {
|
||||
|
||||
class _LoginEmailScreenState extends State<LoginEmailScreen> {
|
||||
bool _obscureText = true;
|
||||
final controller = Get.put(LoginEmailController());
|
||||
final controller = LoginEmailController.instance;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
SettingModel? settings;
|
||||
|
||||
|
||||
@@ -837,7 +837,7 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
UserModel.getUser(uid.toString()).then((value) {
|
||||
eventoService
|
||||
.createEvent(
|
||||
value.name,
|
||||
value?.name ?? '',
|
||||
_observacionController.text,
|
||||
fechaSeleccionada.toString().substring(0,
|
||||
fechaSeleccionada.toString().length - 1),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl_phone_field/intl_phone_field.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
import 'package:prosappco/src/components/primary_btn.dart';
|
||||
@@ -14,7 +13,7 @@ class NewNumberScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _NewNumberScreenState extends State<NewNumberScreen> {
|
||||
final controller = Get.put(NewPhoneController());
|
||||
final controller = NewPhoneController.instance;
|
||||
String completePhoneNumber = '';
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
import 'package:prosappco/src/components/primary_btn.dart';
|
||||
|
||||
class NewPasswordScreen extends StatefulWidget {
|
||||
@@ -18,11 +18,7 @@ class _NewPasswordScreenState extends State<NewPasswordScreen> {
|
||||
|
||||
void updatePassword(String currentPassword, String newPassword) {
|
||||
// ponytail: password change requires backend endpoint; show support message
|
||||
Get.snackbar(
|
||||
'Cambio de contraseña',
|
||||
'Para cambiar tu contraseña contacta a soporte.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
showAppSnackBar('Cambio de contraseña', 'Para cambiar tu contraseña contacta a soporte.', color: Colors.grey.shade700);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -4,8 +4,8 @@ import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
import 'package:prosappco/src/components/primary_btn.dart';
|
||||
@@ -195,11 +195,7 @@ class _ProfessionalDireccionScreenState
|
||||
);
|
||||
setState(() {});
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
'Ubicación desactivada',
|
||||
'Por favor activa la ubicacion de tu telefono.',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
showAppSnackBar('Ubicación desactivada', 'Por favor activa la ubicación de tu teléfono.');
|
||||
}
|
||||
|
||||
// markers.clear();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
import 'package:prosappco/src/components/photo_view.dart';
|
||||
@@ -27,7 +26,7 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
||||
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
final controller = Get.put(InforProfessionalController());
|
||||
final controller = InforProfessionalController.instance;
|
||||
final _cedulaController = TextEditingController();
|
||||
final _especializacionController = TextEditingController();
|
||||
List<File> images_especializacion = [];
|
||||
|
||||
@@ -2,8 +2,8 @@ import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
import 'package:prosappco/src/components/photo_view_web.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
@@ -226,7 +226,7 @@ class _ProfessionalProfileWebScreenState
|
||||
}
|
||||
|
||||
void showSnackBar(String title, String message) {
|
||||
Get.snackbar(title, message, snackPosition: SnackPosition.TOP);
|
||||
showAppSnackBar(title, message);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -2,8 +2,8 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'dart:io';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
@@ -38,7 +38,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||
bool _obscureText = true;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final controller = Get.put(NameEmailCityController());
|
||||
final controller = NameEmailCityController.instance;
|
||||
final _phoneNumberController = TextEditingController();
|
||||
final _nameController = TextEditingController();
|
||||
final _emailController = TextEditingController();
|
||||
@@ -140,8 +140,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
);
|
||||
} catch (e) {
|
||||
print('Error updating info: $e');
|
||||
Get.snackbar('Error', 'No se pudo actualizar la información.',
|
||||
snackPosition: SnackPosition.BOTTOM);
|
||||
showAppSnackBar('Error', 'No se pudo actualizar la información.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:prosappco/src/utils/app_navigator.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';
|
||||
@@ -175,16 +175,8 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
if (sitioValue) {
|
||||
ubicacion = 'sitio';
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Elige como vas a dar tu servicio',
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.black.withOpacity(0.2),
|
||||
messageText: const Text(
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
);
|
||||
showAppSnackBar('Elige como vas a dar tu servicio',
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -195,16 +187,8 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
} else if (sitioValue) {
|
||||
ubicacion = 'sitio';
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Elige como vas a dar tu servicio',
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.black.withOpacity(0.2),
|
||||
messageText: const Text(
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
);
|
||||
showAppSnackBar('Elige como vas a dar tu servicio',
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -223,23 +207,22 @@ class _ProfileProScreenState extends State<ProfileProScreen> {
|
||||
}
|
||||
|
||||
if (settings?.domicilios == false && sitioValue == false) {
|
||||
Get.defaultDialog(
|
||||
title: 'Donde vas a dar tu servicio?',
|
||||
middleText:
|
||||
'Si no eliges servicio en sitio, no serás visible para los usuarios.',
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () => Get.back(),
|
||||
child: const Text('Entendido'),
|
||||
),
|
||||
],
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
title: const Text('¿Dónde vas a dar tu servicio?'),
|
||||
content: const Text('Si no eliges servicio en sitio, no serás visible para los usuarios.'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Entendido'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Información actualizada',
|
||||
'Tu información ha sido actualizada con éxito.',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
showAppSnackBar('Información actualizada', 'Tu información ha sido actualizada con éxito.',
|
||||
color: const Color(0xFF2BA4EC));
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.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';
|
||||
@@ -116,16 +116,8 @@ class _ProfileProWebScreenState extends State<ProfileProWebScreen> {
|
||||
if (sitioValue) {
|
||||
ubicacion = 'sitio';
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Elige como vas a dar tu servicio',
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.black.withOpacity(0.2),
|
||||
messageText: const Text(
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
);
|
||||
showAppSnackBar('Elige como vas a dar tu servicio',
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -136,16 +128,8 @@ class _ProfileProWebScreenState extends State<ProfileProWebScreen> {
|
||||
} else if (sitioValue) {
|
||||
ubicacion = 'sitio';
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Elige como vas a dar tu servicio',
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.black.withOpacity(0.2),
|
||||
messageText: const Text(
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
);
|
||||
showAppSnackBar('Elige como vas a dar tu servicio',
|
||||
'Selecciona si tu servicio es a domicilio o en tu consultorio.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -158,23 +142,22 @@ class _ProfileProWebScreenState extends State<ProfileProWebScreen> {
|
||||
}
|
||||
|
||||
if (settings?.domicilios == false && sitioValue == false) {
|
||||
Get.defaultDialog(
|
||||
title: 'Donde vas a dar tu servicio?',
|
||||
middleText:
|
||||
'Si no eliges servicio en sitio, no serás visible para los usuarios.',
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () => Get.back(),
|
||||
child: const Text('Entendido'),
|
||||
),
|
||||
],
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
title: const Text('¿Dónde vas a dar tu servicio?'),
|
||||
content: const Text('Si no eliges servicio en sitio, no serás visible para los usuarios.'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Entendido'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Información actualizada',
|
||||
'Tu información ha sido actualizada con éxito.',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
showAppSnackBar('Información actualizada', 'Tu información ha sido actualizada con éxito.',
|
||||
color: const Color(0xFF2BA4EC));
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/components/bottom_sheet.dart';
|
||||
import 'package:prosappco/src/components/column_padding.dart';
|
||||
import 'package:prosappco/src/presentation/widgets/shared/primary_button.dart';
|
||||
@@ -22,7 +21,7 @@ class RegisterScreen extends StatefulWidget {
|
||||
|
||||
class _RegisterScreenState extends State<RegisterScreen> {
|
||||
bool _obscureText = true;
|
||||
final controller = Get.put(RegisterController());
|
||||
final controller = RegisterController.instance;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
bool _isChecked = false;
|
||||
SettingModel? settings;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
import 'package:prosappco/src/components/primary_btn.dart';
|
||||
import 'package:prosappco/src/controllers/login_email_controller.dart';
|
||||
@@ -9,7 +8,7 @@ class ResetPasswordScreen extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final controller = Get.put(LoginEmailController());
|
||||
final controller = LoginEmailController.instance;
|
||||
|
||||
return Scaffold(
|
||||
appBar: PopAppbar(
|
||||
|
||||
@@ -91,7 +91,7 @@ class _ServiceAfterScreenState extends State<ServiceAfterScreen> {
|
||||
children: [
|
||||
ListTile(
|
||||
leading: ReferencePhoto(
|
||||
ref: user?.photo,
|
||||
ref: user?.picture,
|
||||
size: 55,
|
||||
sizeCircle: 60,
|
||||
),
|
||||
|
||||
@@ -3,8 +3,6 @@ import 'dart:convert';
|
||||
import 'package:prosappco/src/components/network_utility.dart';
|
||||
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||
|
||||
import '../../authentication/authentication_repository.dart';
|
||||
|
||||
class UbicacionScreen extends StatefulWidget {
|
||||
const UbicacionScreen({super.key});
|
||||
|
||||
@@ -21,15 +19,7 @@ class _UbicacionScreenState extends State<UbicacionScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||
|
||||
if (_coordsOfCity == '0.0,0.0') {
|
||||
AuthenticationRepository.instance
|
||||
.getCoordsOfCity(uid.toString())
|
||||
.then((String s) => setState(() {
|
||||
_coordsOfCity = s;
|
||||
}));
|
||||
}
|
||||
// ponytail: city coords default to 0.0,0.0; geocoding removed in migration
|
||||
}
|
||||
|
||||
void placeAutoComplete(String query) async {
|
||||
|
||||
@@ -15,7 +15,6 @@ import 'package:prosappco/src/presentation/screens/reputation.dart';
|
||||
import 'package:prosappco/src/presentation/screens/support.dart';
|
||||
import 'package:prosappco/src/presentation/screens/web_view.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class DrawerMenu extends StatelessWidget {
|
||||
@@ -298,10 +297,9 @@ class DrawerMenu extends StatelessWidget {
|
||||
);
|
||||
} else {
|
||||
if (user?.phoneNumber != user?.phoneNumber) {
|
||||
Get.snackbar(
|
||||
'Tu número de teléfono sigue sin cambios.',
|
||||
'Para guardar esta información, dirígete a tu perfil y selecciona la opción Guardar',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
WarningSnackbar.show(
|
||||
title: 'Tu número de teléfono sigue sin cambios.',
|
||||
message: 'Para guardar esta información, dirígete a tu perfil.',
|
||||
);
|
||||
} else {
|
||||
if (user?.proState == 0 || user?.proState == null) {
|
||||
@@ -344,8 +342,7 @@ class DrawerMenu extends StatelessWidget {
|
||||
const SizedBox(height: 5),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
await AuthenticationRepository.instance.logout(uid!);
|
||||
|
||||
await AuthenticationRepository.instance.logout();
|
||||
userProvider.setNullUser();
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@@ -399,7 +396,7 @@ class DrawerMenu extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
leading: ReferencePhoto(
|
||||
ref: user?.photo,
|
||||
ref: user?.picture,
|
||||
size: 50,
|
||||
sizeCircle: 50,
|
||||
),
|
||||
|
||||
@@ -1,51 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.dart';
|
||||
|
||||
class NotificationSnackbar {
|
||||
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),
|
||||
),
|
||||
);
|
||||
showAppSnackBar(title, message, color: backgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:prosappco/src/utils/app_navigator.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),
|
||||
),
|
||||
);
|
||||
showAppSnackBar(title, message, color: backgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:prosappco/src/models/scores_model.dart';
|
||||
import 'package:prosappco/src/models/user_model.dart';
|
||||
import 'package:prosappco/src/services/api_service.dart';
|
||||
|
||||
class UserProvider extends ChangeNotifier {
|
||||
final _api = ApiService.instance;
|
||||
UserModel? _user;
|
||||
ScoresModel? _score;
|
||||
|
||||
UserProvider() {
|
||||
loadUser();
|
||||
@@ -15,7 +17,8 @@ class UserProvider extends ChangeNotifier {
|
||||
if (token == null) return;
|
||||
try {
|
||||
final data = await _api.get('/auth/me');
|
||||
_user = UserModel.fromApi(data);
|
||||
_user = UserModel.fromApi(data as Map<String, dynamic>);
|
||||
_score = await ScoresModel.scoreTo(_user?.id, false, false);
|
||||
notifyListeners();
|
||||
} catch (_) {}
|
||||
}
|
||||
@@ -25,8 +28,10 @@ class UserProvider extends ChangeNotifier {
|
||||
|
||||
void setNullUser() {
|
||||
_user = null;
|
||||
_score = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
UserModel? get user => _user;
|
||||
ScoresModel? get score => _score;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,11 @@ class ApiException implements Exception {
|
||||
class ApiService {
|
||||
static ApiService? _instance;
|
||||
static ApiService get instance => _instance ??= ApiService._();
|
||||
static const baseUrl = _baseUrl;
|
||||
ApiService._();
|
||||
|
||||
Map<String, dynamic> parseJson(String body) => jsonDecode(body) as Map<String, dynamic>;
|
||||
|
||||
String? _token;
|
||||
|
||||
Future<String?> getToken() async {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final appNavigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
void pushOffAll(Widget screen) {
|
||||
appNavigatorKey.currentState?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(builder: (_) => screen),
|
||||
(_) => false,
|
||||
);
|
||||
}
|
||||
|
||||
void push(Widget screen) {
|
||||
appNavigatorKey.currentState?.push(
|
||||
MaterialPageRoute(builder: (_) => screen),
|
||||
);
|
||||
}
|
||||
|
||||
void back() => appNavigatorKey.currentState?.pop();
|
||||
|
||||
void showAppSnackBar(String title, String message, {Color color = Colors.red}) {
|
||||
final ctx = appNavigatorKey.currentContext;
|
||||
if (ctx == null) return;
|
||||
ScaffoldMessenger.of(ctx).showSnackBar(SnackBar(
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(title, style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)),
|
||||
Text(message, style: TextStyle(color: Colors.white)),
|
||||
],
|
||||
),
|
||||
backgroundColor: color,
|
||||
duration: const Duration(seconds: 4),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
));
|
||||
}
|
||||
|
||||
Future<T?> showAppDialog<T>(AlertDialog dialog) {
|
||||
final ctx = appNavigatorKey.currentContext!;
|
||||
return showDialog<T>(context: ctx, builder: (_) => dialog);
|
||||
}
|
||||
+4
-5
@@ -37,23 +37,22 @@ dependencies:
|
||||
cupertino_icons: ^1.0.2
|
||||
location: ^5.0.3
|
||||
flutter_polyline_points: ^2.0.0
|
||||
google_maps_flutter: ^2.5.0
|
||||
google_maps_flutter: ^2.9.0
|
||||
file_picker: ^5.3.2
|
||||
provider: ^6.0.5
|
||||
package_info_plus: ^4.2.0
|
||||
get:
|
||||
font_awesome_flutter: ^10.4.0
|
||||
font_awesome_flutter: ^10.8.0
|
||||
flutter_otp_text_field:
|
||||
intl_phone_field:
|
||||
diacritic:
|
||||
image_picker: ^1.0.4
|
||||
image_picker: ^1.1.2
|
||||
flutter_animate:
|
||||
flutter_rating_bar:
|
||||
table_calendar:
|
||||
http: ^1.1.0
|
||||
geolocator: ^9.0.2
|
||||
geocoding: ^2.1.0
|
||||
url_launcher: ^6.1.10
|
||||
url_launcher: ^6.3.0
|
||||
community_material_icon: ^5.9.55
|
||||
webview_flutter: ^4.4.1
|
||||
responsive_builder: ^0.7.0
|
||||
|
||||
Reference in New Issue
Block a user