Files
AAU-Store/lib/controllers/authentication/authentication_controller.dart

211 lines
6.8 KiB
Dart

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:laundry_seller/models/authentication/authentication_model.dart';
import 'package:laundry_seller/models/authentication/settings.dart';
import 'package:laundry_seller/models/authentication/user.dart';
import 'package:laundry_seller/models/common/common_response_model.dart';
import 'package:laundry_seller/services/auth_service_provider.dart';
import 'package:laundry_seller/services/hive_service.dart';
import 'package:laundry_seller/utils/api_client.dart';
class AuthController extends StateNotifier<bool> {
final Ref ref;
AuthController(this.ref) : super(false);
String? _lastError;
String? get lastError => _lastError;
late Settings _settings;
Settings get settings => _settings;
// get settings info
Future<bool> getSettingsInfo() async {
try {
final response = await ref.read(authServiceProvider).settings();
_settings =
Settings.fromMap(Map<String, dynamic>.from(response.data['data']));
return true;
} catch (e) {
debugPrint(e.toString());
return false;
}
}
// login
Future<bool> login(
{required String contact, required String password}) async {
try {
state = true;
_lastError = null;
final response = await ref
.read(authServiceProvider)
.login(contact: contact, password: password);
if (response.data == null ||
response.data['data'] == null ||
response.data['data']['user'] == null) {
_lastError =
response.data?['message'] ?? 'Login failed. Invalid response.';
state = false;
return false;
}
final userInfo = User.fromMap(
Map<String, dynamic>.from(response.data['data']['user']));
final accessToken = response.data['data']['access']['token'];
ref.read(hiveStoreService).saveUserInfo(userInfo: userInfo);
ref.read(hiveStoreService).saveUserAuthToken(authToken: accessToken);
ref.read(apiClientProvider).updateToken(token: accessToken);
state = false;
return true;
} on DioException catch (e) {
_lastError = _extractErrorMessage(e);
debugPrint('Login error: $_lastError');
state = false;
return false;
} catch (e) {
_lastError = 'Connection error. Please try again.';
debugPrint(e.toString());
state = false;
return false;
}
}
// pin login
Future<bool> pinLogin({required String storeId, required String pin}) async {
try {
state = true;
_lastError = null;
final response = await ref
.read(authServiceProvider)
.pinLogin(storeId: storeId, pin: pin);
if (response.data == null ||
response.data['data'] == null ||
response.data['data']['user'] == null) {
_lastError =
response.data?['message'] ?? 'Login failed. Invalid response.';
state = false;
return false;
}
final userInfo = User.fromMap(
Map<String, dynamic>.from(response.data['data']['user']));
final accessToken = response.data['data']['access']['token'];
ref.read(hiveStoreService).saveUserInfo(userInfo: userInfo);
ref.read(hiveStoreService).saveUserAuthToken(authToken: accessToken);
ref.read(apiClientProvider).updateToken(token: accessToken);
state = false;
return true;
} on DioException catch (e) {
_lastError = _extractErrorMessage(e);
debugPrint('Pin login error: $_lastError');
state = false;
return false;
} catch (e) {
_lastError = 'Connection error. Please try again.';
debugPrint(e.toString());
state = false;
return false;
}
}
// registration
Future<CommonResponse> registration({
required SignUpModel signUpModel,
required File profile,
required File shopLogo,
required File shopBanner,
}) async {
try {
state = true;
final response = await ref.read(authServiceProvider).registration(
signUpModel: signUpModel,
profile: profile,
shopLogo: shopLogo,
shopBanner: shopBanner,
);
final message = response.data['message'];
if (response.statusCode == 200) {
return CommonResponse(isSuccess: true, message: message);
}
state = false;
return CommonResponse(isSuccess: false, message: message);
} catch (e) {
debugPrint(e.toString());
state = false;
return CommonResponse(isSuccess: false, message: e.toString());
}
}
// send verification OTP
Future<CommonResponse> sendOTP({required String mobile}) async {
try {
state = true;
final response =
await ref.read(authServiceProvider).sendOTP(mobile: mobile);
final message = response.data['message'];
if (response.statusCode == 200) {
state = false;
return CommonResponse(isSuccess: true, message: message);
}
state = false;
return CommonResponse(isSuccess: false, message: message);
} catch (e) {
debugPrint(e.toString());
state = false;
return CommonResponse(isSuccess: false, message: e.toString());
}
}
// verify otp
Future<CommonResponse> verifyOTP(
{required String mobile, required String otp}) async {
try {
state = true;
final response = await ref
.read(authServiceProvider)
.verifyOTP(mobile: mobile, otp: otp);
final message = response.data['message'];
if (response.statusCode == 200) {
state = false;
return CommonResponse(isSuccess: true, message: message);
}
state = false;
return CommonResponse(isSuccess: false, message: message);
} catch (e) {
debugPrint(e.toString());
state = false;
return CommonResponse(isSuccess: false, message: e.toString());
}
}
/// Extract a human-readable error message from a DioException
String _extractErrorMessage(DioException e) {
if (e.response?.data != null) {
final data = e.response!.data;
if (data is Map) {
// Laravel returns {"message": "..."}
return data['message']?.toString() ??
'Request failed (${e.response?.statusCode})';
}
if (data is String && data.isNotEmpty) return data;
}
switch (e.type) {
case DioExceptionType.connectionTimeout:
return 'Connection timed out. Check your network.';
case DioExceptionType.connectionError:
return 'Cannot reach server. Check your connection.';
case DioExceptionType.receiveTimeout:
return 'Server took too long to respond.';
default:
return 'Request failed. Please try again.';
}
}
}
final authController =
StateNotifierProvider<AuthController, bool>((ref) => AuthController(ref));