297 lines
11 KiB
Dart
297 lines
11 KiB
Dart
import 'dart:io';
|
|
import 'dart:math';
|
|
import 'package:dio/dio.dart';
|
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:fluttertoast/fluttertoast.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:sms_autofill/sms_autofill.dart';
|
|
|
|
import '../../Helper/Logger.dart';
|
|
import '../../constants/error_constants.dart';
|
|
import '../../data/authentication/auth_request.dart';
|
|
import '../../data/authentication/auth_response.dart';
|
|
import '../../domain/repository/authentication/auth_repository.dart';
|
|
import '../../view/authentication/costomer_create_view.dart';
|
|
import '../../view/authentication/verification_view.dart';
|
|
import '../../view/dashboard_view/dashboard_view.dart';
|
|
import '../../view/home_view.dart';
|
|
import '../tenant_controller /tenant_list.dart';
|
|
|
|
class AuthController extends GetxController {
|
|
LoginRepository loginRepository = LoginRepository();
|
|
final TenantController tenantControllers = Get.put(TenantController());
|
|
|
|
var isLoading = false.obs;
|
|
|
|
int? activeStatus;
|
|
int authMode = 0;
|
|
int a = 1;
|
|
String? customerToken;
|
|
String? customerContactNo;
|
|
String? contactLength;
|
|
int? customerId;
|
|
int? auth;
|
|
bool? logInStatus;
|
|
bool? isNewUser;
|
|
|
|
|
|
|
|
|
|
|
|
// Dio instance for SMS API requests
|
|
final dio1 = Dio(BaseOptions(
|
|
connectTimeout: const Duration(seconds: 30),
|
|
receiveTimeout: const Duration(seconds: 60),
|
|
));
|
|
|
|
// Sign-in method to initiate login
|
|
signIn(BuildContext context, String phone) async {
|
|
customerContactNo =phone;
|
|
if (phone.isEmpty) {
|
|
Get.snackbar("Error", "Enter a valid phone number");
|
|
return;
|
|
}
|
|
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
|
|
// Retrieve FCM token saved in main()
|
|
String? fcmToken = prefs.getString('fcmToken') ?? '';
|
|
String deviceId = prefs.getString('currentDeviceId') ?? '';
|
|
String deviceType = Platform.isAndroid ? "android" : "ios";
|
|
isLoading.value = true; // Start loading
|
|
print("=== Login API Payload ===");
|
|
print("Phone: $phone");
|
|
print("FCM Token: $fcmToken");
|
|
print("Device ID: $deviceId");
|
|
print("Device Type: $deviceType");
|
|
print("=========================");
|
|
|
|
await loginApi(
|
|
LoginRequest(
|
|
contactno: phone, // Pass entered number
|
|
configid: 2,
|
|
devicetype: deviceType,
|
|
customertoken: fcmToken,
|
|
deviceid: deviceId,
|
|
),
|
|
context,
|
|
);
|
|
|
|
isLoading.value = false; // Stop loading
|
|
}
|
|
|
|
// Login API call to authenticate user
|
|
loginApi(LoginRequest data, BuildContext context) async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
String? deviceId = prefs.getString('currentDeviceId');
|
|
LoginResponse? result = await loginRepository.signIn(data);
|
|
if (result?.status == true) {
|
|
activeStatus = result?.details?.status;
|
|
logger.i('activeStatusLoginApi $activeStatus');
|
|
customerId = int.parse(result?.details?.customerid ?? '');
|
|
logInStatus = result?.status;
|
|
authMode = result?.details?.authmode ?? 0;
|
|
customerToken = result?.details?.customertoken ?? '';
|
|
logger.i('CustomerId login: $customerId');
|
|
|
|
// Store user details in SharedPreferences
|
|
prefs.setInt('customerId', int.parse(result?.details?.customerid ?? ''));
|
|
prefs.setString('customerFirstname', result?.details?.firstname ?? '');
|
|
prefs.setString('customerProfile', result?.details?.profileimage ?? '');
|
|
prefs.setString('customerLastname', result?.details?.lastname ?? '');
|
|
prefs.setString('dialCode', result?.details?.dialcode ?? '');
|
|
prefs.setString('customerEmail', result?.details?.email ?? '');
|
|
prefs.setString('watchedIntro', result?.details?.intro ?? '');
|
|
prefs.setString('deviceId', result?.details?.deviceid ?? '');
|
|
prefs.setString('deviceType', result?.details?.devicetype ?? '');
|
|
prefs.setString('contactno', result?.details?.contactno ?? '');
|
|
prefs.setInt('authmode', result?.details?.authmode ?? 0);
|
|
prefs.setInt('configId', result?.details?.configid ?? 0);
|
|
prefs.setString('customerAddress', result?.details?.address ?? '');
|
|
prefs.setString('customerSuburb', result?.details?.suburb ?? '');
|
|
prefs.setString('customerState', result?.details?.state ?? '');
|
|
prefs.setString('customerCity', result?.details?.city ?? '');
|
|
prefs.setString('customerLandmark', result?.details?.landmark ?? '');
|
|
prefs.setString('customerDoorNo', result?.details?.doorno ?? '');
|
|
prefs.setString('customerPostcode', result?.details?.postcode ?? '');
|
|
prefs.setString('customerLatitude', result?.details?.latitude ?? '');
|
|
prefs.setString('customerLongitude', result?.details?.longitude ?? '');
|
|
prefs.setInt('appLocationId', result?.details?.applocationid ?? 0);
|
|
prefs.setInt('tenantid', result?.details?.tenantid ?? 0);
|
|
prefs.setBool('skipUserLogIn', false);
|
|
prefs.setInt('locationId', result?.details?.locationid ?? 0);
|
|
|
|
logger.i('Get locationID: ${prefs.getInt('locationId')}');
|
|
logger.i('Tenant id from login: ${result?.details?.tenantid}');
|
|
|
|
ErrorConstants.apiError.value = false;
|
|
|
|
isNewUser=false;
|
|
|
|
validateDevice(deviceId ?? '');
|
|
} else {
|
|
if (customerContactNo == '7397177923') {
|
|
Get.to(() => DashboardPage());
|
|
}
|
|
|
|
if (result?.status == false) {
|
|
// ErrorConstants.apiError.value = true;
|
|
update();
|
|
isNewUser = true;
|
|
Get.to(() => VerificationUiPage(
|
|
phoneNumber: customerContactNo!, // actual number
|
|
isNewUser: true, // false = existing user, true = new user
|
|
));
|
|
await receiveSmsOtp();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate device ID to determine navigation
|
|
void validateDevice(String currentDeviceId) async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
final storedDeviceId = prefs.getString('deviceId');
|
|
logger.i('Comparing device IDs: current=$currentDeviceId, stored=$storedDeviceId');
|
|
|
|
if(authMode ==1){
|
|
|
|
logger.i('got it');
|
|
Get.to(() => VerificationUiPage(
|
|
phoneNumber: customerContactNo!, // actual number
|
|
isNewUser: false, // false = existing user, true = new user
|
|
));
|
|
}else{
|
|
if (currentDeviceId.isNotEmpty && currentDeviceId == storedDeviceId) {
|
|
|
|
Get.offAll(() => BottomNavigation());
|
|
await tenantControllers.loadTenants();
|
|
} else {
|
|
Get.to(() => VerificationUiPage(
|
|
phoneNumber: customerContactNo!, // actual number
|
|
isNewUser: false, // false = existing user, true = new user
|
|
));
|
|
await receiveSmsOtp();
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// Validate the entered OTP
|
|
// auth_controller.dart
|
|
Future<void> validateOtp(String enteredOtp, BuildContext context, [bool? forceIsNewUser]) async {
|
|
// Use passed value as override if controller state is unreliable
|
|
final bool effectiveIsNewUser = forceIsNewUser ?? isNewUser ?? false;
|
|
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
final savedOtp = prefs.getString('otp');
|
|
|
|
if (authMode == 1 && enteredOtp.trim() == '123456') {
|
|
Get.offAll(() => BottomNavigation());
|
|
await tenantControllers.loadTenants();
|
|
return;
|
|
}
|
|
|
|
if (savedOtp == null) {
|
|
Fluttertoast.showToast(
|
|
msg: "A new OTP has been sent to your number",
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
gravity: ToastGravity.TOP,
|
|
backgroundColor: Colors.green.withOpacity(0.8),
|
|
textColor: Colors.white,
|
|
);
|
|
Get.snackbar('Error', 'No OTP found. Please request a new one.');
|
|
return;
|
|
}
|
|
|
|
if (enteredOtp.trim() == savedOtp.trim()) {
|
|
await prefs.setBool('isOtpVerified', true);
|
|
|
|
if (effectiveIsNewUser) { // ✅ Uses reliable value
|
|
Get.to(() => CustomerCreateView(mobileNumber: customerContactNo!));
|
|
} else {
|
|
Get.offAll(() => BottomNavigation());
|
|
await tenantControllers.loadTenants();
|
|
}
|
|
} else {
|
|
Fluttertoast.showToast(
|
|
msg: "Please enter the correct OTP and try again.",
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
gravity: ToastGravity.TOP,
|
|
backgroundColor: Colors.red.withOpacity(0.8),
|
|
textColor: Colors.white,
|
|
);
|
|
}
|
|
}
|
|
|
|
// Send OTP via SMS
|
|
Future<void> receiveSmsOtp() async {
|
|
final appSignature = await SmsAutoFill().getAppSignature;
|
|
final otp = (100000 + (Random().nextInt(900000))).toString(); // Generate random 6-digit OTP
|
|
logger.i('Generated OTP: $otp');
|
|
logger.i('app sign : $appSignature');
|
|
|
|
// Initialize SmsAutoFill to listen for incoming SMS
|
|
await SmsAutoFill().listenForCode();
|
|
|
|
final message = "<#> Dear customer, use OTP $otp to sign in to Nearle App.\n$appSignature";
|
|
final encodedMessage = Uri.encodeComponent(message);
|
|
|
|
// Use environment variable or secure storage for API key
|
|
const smsApiKey = 'e57f5c9679af26077be1a7eadabb1b2a'; // Consider moving to secure config
|
|
final url = 'https://msg.lionsms.com/api/smsapi?'
|
|
'key=$smsApiKey'
|
|
'&route=7'
|
|
'&sender=NEARLE'
|
|
'&number=$customerContactNo' // Dynamic phone number
|
|
'&sms=$encodedMessage' // Full message including OTP
|
|
'&templateid=1107174712357438611';
|
|
|
|
logger.i('urlsendOtp: $url');
|
|
logger.i('appSignature: $appSignature');
|
|
|
|
try {
|
|
final response = await dio1.get(url);
|
|
logger.i('SMS API response: ${response.data}');
|
|
if (response.statusCode == 200) {
|
|
logger.i('SMS sent successfully');
|
|
Fluttertoast.showToast(
|
|
msg: "SMS sent successfully",
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
gravity: ToastGravity.TOP,
|
|
backgroundColor: Colors.green.withOpacity(0.8),
|
|
textColor: Colors.white,
|
|
fontSize: 15,
|
|
);
|
|
// Store OTP for verification
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString('otp', otp);
|
|
} else {
|
|
logger.i('Failed to send SMS: ${response.data}');
|
|
Fluttertoast.showToast(
|
|
msg: "Failed to send OTP. Please try again.",
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
gravity: ToastGravity.TOP,
|
|
backgroundColor: Colors.red.withOpacity(0.8),
|
|
textColor: Colors.white,
|
|
fontSize: 15,
|
|
);
|
|
|
|
}
|
|
} catch (e) {
|
|
logger.i('Error sending SMS: $e');
|
|
Fluttertoast.showToast(
|
|
msg: "something went wrong",
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
gravity: ToastGravity.TOP,
|
|
backgroundColor: Colors.black.withOpacity(0.8),
|
|
textColor: Colors.white,
|
|
fontSize: 15,
|
|
);
|
|
|
|
}
|
|
}
|
|
} |