mpin add and 2026-04-19 updates
This commit is contained in:
1 parent
41d7cfa8c6
commit
7d25e77138
15 files changed
+2555
-1643
No files matched your search
@@ -2,7 +2,7 @@ class ConstsApi {
|
||||
static const String baseUrl = "https://www.taxglide.amrithaa.net";
|
||||
|
||||
static const String login = "$baseUrl/api/otp/sms/request";
|
||||
static const String verifyOtp = "$baseUrl/api/otp/sms/verify";
|
||||
static const String verifyOtp = "$baseUrl/api/otp/email/verify";
|
||||
static const String signup = "$baseUrl/api/register";
|
||||
static const String terms = "$baseUrl/api/get_terms_conditions";
|
||||
static const String policy = "$baseUrl/api/get_privacy_policy";
|
||||
@@ -28,4 +28,10 @@ class ConstsApi {
|
||||
static const String dashboard = "$baseUrl/api/get_dashboard_data";
|
||||
static const String proformaaccept = "$baseUrl/api/proforma/accept";
|
||||
static const String payNow = "$baseUrl/api/pay_now";
|
||||
static const String changePin = "$baseUrl/api/change_pin";
|
||||
|
||||
static const String loginWithPin = "$baseUrl/api/login";
|
||||
static const String employeeLoginWithPin = "$baseUrl/api/employee/login";
|
||||
static const String forgotPassword = "$baseUrl/api/otp/email/request";
|
||||
static const String employeeForgotPassword = "$baseUrl/api/otp/employee/email/request";
|
||||
}
|
||||
@@ -33,6 +33,17 @@ class LoginNotifier extends StateNotifier<AsyncValue<Map<String, dynamic>>> {
|
||||
|
||||
LoginNotifier(this._apiRepository) : super(const AsyncValue.data({}));
|
||||
|
||||
Future<void> loginWithPin(String email, String pin) async {
|
||||
if (!mounted) return;
|
||||
state = const AsyncValue.loading();
|
||||
try {
|
||||
final result = await _apiRepository.loginWithPin(email, pin);
|
||||
if (mounted) state = AsyncValue.data(result);
|
||||
} catch (e, st) {
|
||||
if (mounted) state = AsyncValue.error(e, st);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> login(String mobile) async {
|
||||
if (!mounted) return;
|
||||
state = const AsyncValue.loading();
|
||||
@@ -86,11 +97,11 @@ class SignupNotifier extends StateNotifier<AsyncValue<Map<String, dynamic>>> {
|
||||
}
|
||||
|
||||
// Verify OTP for signup
|
||||
Future<void> verifySignupOtp(String mobile, String otp) async {
|
||||
Future<void> verifySignupOtp(String email, String otp) async {
|
||||
if (!mounted) return;
|
||||
state = const AsyncValue.loading();
|
||||
try {
|
||||
final result = await _apiRepository.verifySignupOtp(mobile, otp);
|
||||
final result = await _apiRepository.verifySignupOtp(email, otp);
|
||||
if (mounted) state = AsyncValue.data(result);
|
||||
} catch (e, st) {
|
||||
if (mounted) state = AsyncValue.error(e, st);
|
||||
@@ -115,6 +126,17 @@ class EmployeeLoginNotifier
|
||||
|
||||
EmployeeLoginNotifier(this._apiRepository) : super(const AsyncValue.data({}));
|
||||
|
||||
Future<void> loginWithPin(String email, String pin) async {
|
||||
if (!mounted) return;
|
||||
state = const AsyncValue.loading();
|
||||
try {
|
||||
final result = await _apiRepository.employeeLoginWithPin(email, pin);
|
||||
if (mounted) state = AsyncValue.data(result);
|
||||
} catch (e, st) {
|
||||
if (mounted) state = AsyncValue.error(e, st);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> login(String mobile) async {
|
||||
if (!mounted) return;
|
||||
state = const AsyncValue.loading();
|
||||
@@ -137,6 +159,77 @@ class EmployeeLoginNotifier
|
||||
if (mounted) state = AsyncValue.error(e, st);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
state = const AsyncValue.data({});
|
||||
}
|
||||
}
|
||||
|
||||
final forgotPasswordProvider =
|
||||
StateNotifierProvider<
|
||||
ForgotPasswordNotifier,
|
||||
AsyncValue<Map<String, dynamic>>
|
||||
>((ref) => ForgotPasswordNotifier(ref.read(apiRepositoryProvider)));
|
||||
|
||||
class ForgotPasswordNotifier
|
||||
extends StateNotifier<AsyncValue<Map<String, dynamic>>> {
|
||||
final ApiRepository _apiRepository;
|
||||
|
||||
ForgotPasswordNotifier(this._apiRepository)
|
||||
: super(const AsyncValue.data({}));
|
||||
|
||||
Future<void> requestOtp(String email, bool isEmployee) async {
|
||||
if (!mounted) return;
|
||||
state = const AsyncValue.loading();
|
||||
try {
|
||||
final result = await _apiRepository.requestForgotPasswordOtp(
|
||||
email,
|
||||
isEmployee,
|
||||
);
|
||||
if (mounted) state = AsyncValue.data(result);
|
||||
} catch (e, st) {
|
||||
if (mounted) state = AsyncValue.error(e, st);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> verifyOtp(String email, String otp) async {
|
||||
if (!mounted) return;
|
||||
state = const AsyncValue.loading();
|
||||
try {
|
||||
final result = await _apiRepository.verifyEmailOtp(email, otp);
|
||||
if (mounted) state = AsyncValue.data(result);
|
||||
} catch (e, st) {
|
||||
if (mounted) state = AsyncValue.error(e, st);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
state = const AsyncValue.data({});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// PIN controller
|
||||
final changePinProvider =
|
||||
StateNotifierProvider<PinNotifier, AsyncValue<Map<String, dynamic>>>(
|
||||
(ref) => PinNotifier(ref.read(apiRepositoryProvider)),
|
||||
);
|
||||
|
||||
class PinNotifier extends StateNotifier<AsyncValue<Map<String, dynamic>>> {
|
||||
final ApiRepository _apiRepository;
|
||||
|
||||
PinNotifier(this._apiRepository) : super(const AsyncValue.data({}));
|
||||
|
||||
Future<void> changePin(String pinOrOtp) async {
|
||||
if (!mounted) return;
|
||||
state = const AsyncValue.loading();
|
||||
try {
|
||||
final result = await _apiRepository.changePin(pinOrOtp);
|
||||
if (mounted) state = AsyncValue.data(result);
|
||||
} catch (e, st) {
|
||||
if (mounted) state = AsyncValue.error(e, st);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final termsProvider = FutureProvider<TermsModel>((ref) async {
|
||||
|
||||
@@ -159,6 +159,54 @@ class ApiRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 DIRECT LOGIN (Email + PIN) - ✅ Regenerates FCM token
|
||||
Future<Map<String, dynamic>> loginWithPin(String email, String pin) async {
|
||||
try {
|
||||
final params = {'email': email, 'pin': pin};
|
||||
|
||||
// ✅ Regenerate FCM and APNS tokens on every login
|
||||
final tokens = await _regenerateFcmToken();
|
||||
final fcmToken = tokens['fcm_token'];
|
||||
final apnsToken = tokens['apns_token'];
|
||||
|
||||
if (fcmToken != null && fcmToken.isNotEmpty) {
|
||||
params['fcm_token'] = fcmToken;
|
||||
}
|
||||
if (apnsToken != null && apnsToken.isNotEmpty) {
|
||||
params['apns_token'] = apnsToken;
|
||||
}
|
||||
|
||||
if (params['fcm_token'] == null) {
|
||||
debugPrint('⚠️ Failed to generate FCM token, trying fallback...');
|
||||
final fallbackToken = await _getFreshFcmToken();
|
||||
if (fallbackToken != null && fallbackToken.isNotEmpty) {
|
||||
params['fcm_token'] = fallbackToken;
|
||||
}
|
||||
}
|
||||
|
||||
final uri = Uri.parse(ConstsApi.loginWithPin).replace(
|
||||
queryParameters: params.map(
|
||||
(key, value) => MapEntry(key, value.toString()),
|
||||
),
|
||||
);
|
||||
|
||||
final response = await http.post(uri, headers: _baseHeaders);
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
await _localStore.saveLoginData(data);
|
||||
return {'success': true, 'data': data};
|
||||
} else {
|
||||
return {'success': false, 'error': _extractErrorMessage(data)};
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
'success': false,
|
||||
'error': 'Connection error. Please check your internet.',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 VERIFY OTP (LOGIN) - ✅ Regenerates FCM token
|
||||
Future<Map<String, dynamic>> verifyOtp(LoginModel model) async {
|
||||
try {
|
||||
@@ -230,6 +278,143 @@ class ApiRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 EMPLOYEE LOGIN (Email + PIN) - ✅ Regenerates FCM token
|
||||
Future<Map<String, dynamic>> employeeLoginWithPin(
|
||||
String email,
|
||||
String pin,
|
||||
) async {
|
||||
try {
|
||||
final params = {'email': email, 'pin': pin};
|
||||
|
||||
// ✅ Regenerate FCM and APNS tokens on every login
|
||||
final tokens = await _regenerateFcmToken();
|
||||
final fcmToken = tokens['fcm_token'];
|
||||
final apnsToken = tokens['apns_token'];
|
||||
|
||||
if (fcmToken != null && fcmToken.isNotEmpty) {
|
||||
params['fcm_token'] = fcmToken;
|
||||
}
|
||||
if (apnsToken != null && apnsToken.isNotEmpty) {
|
||||
params['apns_token'] = apnsToken;
|
||||
}
|
||||
|
||||
if (params['fcm_token'] == null) {
|
||||
debugPrint('⚠️ Failed to generate FCM token, trying fallback...');
|
||||
final fallbackToken = await _getFreshFcmToken();
|
||||
if (fallbackToken != null && fallbackToken.isNotEmpty) {
|
||||
params['fcm_token'] = fallbackToken;
|
||||
}
|
||||
}
|
||||
|
||||
final uri = Uri.parse(ConstsApi.employeeLoginWithPin).replace(
|
||||
queryParameters: params.map(
|
||||
(key, value) => MapEntry(key, value.toString()),
|
||||
),
|
||||
);
|
||||
|
||||
final response = await http.post(uri, headers: _baseHeaders);
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
await _localStore.saveLoginData(data);
|
||||
return {'success': true, 'data': data};
|
||||
} else {
|
||||
return {'success': false, 'error': _extractErrorMessage(data)};
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
'success': false,
|
||||
'error': 'Connection error. Please check your internet.',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 FORGOT PASSWORD REQUEST (Email OTP)
|
||||
Future<Map<String, dynamic>> requestForgotPasswordOtp(
|
||||
String email,
|
||||
bool isEmployee,
|
||||
) async {
|
||||
try {
|
||||
final endpoint = isEmployee
|
||||
? ConstsApi.employeeForgotPassword
|
||||
: ConstsApi.forgotPassword;
|
||||
final uri = Uri.parse(endpoint).replace(queryParameters: {'email': email});
|
||||
|
||||
final response = await http.post(uri, headers: _baseHeaders);
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
return {'success': true, 'data': data};
|
||||
} else {
|
||||
return {'success': false, 'error': _extractErrorMessage(data)};
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
'success': false,
|
||||
'error': 'Connection error. Please check your internet.',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 VERIFY EMAIL OTP (Generic)
|
||||
Future<Map<String, dynamic>> verifyEmailOtp(String email, String otp) async {
|
||||
try {
|
||||
final fcmToken = await _getFreshFcmToken();
|
||||
final uri = Uri.parse(ConstsApi.verifyOtp).replace(
|
||||
queryParameters: {
|
||||
'email': email,
|
||||
'otp': otp,
|
||||
if (fcmToken != null) 'fcm_token': fcmToken,
|
||||
},
|
||||
);
|
||||
|
||||
final response = await http.post(uri, headers: _baseHeaders);
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
// ✅ CRITICAL: Save login data to get the token for subsequent requests (like set_pin)
|
||||
await _localStore.saveLoginData(data);
|
||||
return {'success': true, 'data': data};
|
||||
} else {
|
||||
return {'success': false, 'error': _extractErrorMessage(data)};
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
'success': false,
|
||||
'error': 'Connection error. Please check your internet.',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 CHANGE/SET PIN
|
||||
Future<Map<String, dynamic>> changePin(String pin) async {
|
||||
try {
|
||||
final token = await _localStore.getToken();
|
||||
final uri = Uri.parse(ConstsApi.changePin).replace(
|
||||
queryParameters: {'otp': pin},
|
||||
);
|
||||
|
||||
final response = await http.post(
|
||||
uri,
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
);
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
return {'success': true, 'data': data};
|
||||
} else {
|
||||
return {'success': false, 'error': _extractErrorMessage(data)};
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
'success': false,
|
||||
'error': 'Connection error. Please check your internet.',
|
||||
};
|
||||
}
|
||||
}
|
||||
// 🔹 SIGNUP API
|
||||
Future<Map<String, dynamic>> signupUser(SignupModel model) async {
|
||||
try {
|
||||
@@ -258,7 +443,7 @@ class ApiRepository {
|
||||
|
||||
// 🔹 VERIFY OTP (SIGNUP) - ✅ Regenerates FCM token
|
||||
Future<Map<String, dynamic>> verifySignupOtp(
|
||||
String mobile,
|
||||
String email,
|
||||
String otp,
|
||||
) async {
|
||||
try {
|
||||
@@ -267,7 +452,7 @@ class ApiRepository {
|
||||
final fcmToken = tokens['fcm_token'];
|
||||
final apnsToken = tokens['apns_token'];
|
||||
|
||||
final params = {'mobile': mobile, 'otp': otp};
|
||||
final params = {'email': email, 'otp': otp};
|
||||
|
||||
if (fcmToken != null && fcmToken.isNotEmpty) {
|
||||
params['fcm_token'] = fcmToken;
|
||||
@@ -945,6 +1130,41 @@ debugPrint('📦 KYC Response Body: ${response.body}');
|
||||
throw {'error': 'Failed to accept proforma: ${e.toString()}'};
|
||||
}
|
||||
}
|
||||
|
||||
// // 🔹 CHANGE PIN (Verify OTP)
|
||||
// Future<Map<String, dynamic>> changePin(String otp) async {
|
||||
// try {
|
||||
// final token = await _localStore.getToken();
|
||||
// final uri = Uri.parse(ConstsApi.changePin).replace(
|
||||
// queryParameters: {'otp': otp},
|
||||
// );
|
||||
|
||||
// final response = await http.post(
|
||||
// uri,
|
||||
// headers: {
|
||||
// 'Authorization': 'Bearer $token',
|
||||
// 'Accept': 'application/json',
|
||||
// },
|
||||
// );
|
||||
|
||||
// final data = jsonDecode(response.body);
|
||||
// debugPrint("🚀 Change Pin (Verify) API Response: $data");
|
||||
|
||||
// if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
// return {'success': true, 'data': data};
|
||||
// } else {
|
||||
// return {'success': false, 'error': _extractErrorMessage(data)};
|
||||
// }
|
||||
// } catch (e) {
|
||||
// debugPrint('❌ Change Pin API Error: $e');
|
||||
// return {
|
||||
// 'success': false,
|
||||
// 'error': 'Connection error. Please try again.',
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// 🔹 LOGOUT - ✅ Deletes FCM token
|
||||
Future<void> logout() async {
|
||||
|
||||
Reference in new issue
Block a user