151 lines
5.4 KiB
Dart
151 lines
5.4 KiB
Dart
// lib/presentation/auth/bloc/auth_bloc.dart
|
||
|
||
import 'package:bloc/bloc.dart';
|
||
import 'package:dio/dio.dart';
|
||
import 'package:equatable/equatable.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||
import 'package:meta/meta.dart';
|
||
import 'package:proxibuy/core/config/api_config.dart';
|
||
|
||
part 'auth_event.dart';
|
||
part 'auth_state.dart';
|
||
|
||
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||
late final Dio _dio;
|
||
final _storage = const FlutterSecureStorage();
|
||
|
||
AuthBloc() : super(AuthInitial()) {
|
||
_dio = Dio();
|
||
_dio.interceptors.add(
|
||
LogInterceptor(
|
||
requestHeader: true,
|
||
requestBody: true,
|
||
responseBody: true,
|
||
error: true,
|
||
),
|
||
);
|
||
|
||
on<CheckAuthStatusEvent>(_onCheckAuthStatus);
|
||
on<SendOTPEvent>(_onSendOTP);
|
||
on<VerifyOTPEvent>(_onVerifyOTP);
|
||
on<UpdateUserInfoEvent>(_onUpdateUserInfo);
|
||
on<LogoutEvent>(_onLogout);
|
||
}
|
||
|
||
Future<void> _onCheckAuthStatus(
|
||
CheckAuthStatusEvent event, Emitter<AuthState> emit) async {
|
||
final token = await _storage.read(key: 'accessToken');
|
||
if (token != null && token.isNotEmpty) {
|
||
emit(AuthSuccess());
|
||
} else {
|
||
emit(AuthInitial());
|
||
}
|
||
}
|
||
|
||
Future<void> _onSendOTP(SendOTPEvent event, Emitter<AuthState> emit) async {
|
||
emit(AuthLoading());
|
||
try {
|
||
final response = await _dio.post(
|
||
ApiConfig.baseUrl + ApiConfig.sendCode,
|
||
data: {'Phone': event.phoneNumber, 'Code': event.countryCode},
|
||
);
|
||
if (isClosed) return;
|
||
if (response.statusCode == 200) {
|
||
emit(AuthCodeSentSuccess(
|
||
phone: event.phoneNumber,
|
||
countryCode: event.countryCode,
|
||
));
|
||
} else {
|
||
emit(AuthFailure(response.data['message'] ?? 'خطایی رخ داد'));
|
||
}
|
||
} on DioException catch (e) {
|
||
if (isClosed) return;
|
||
emit(AuthFailure(e.response?.data['message'] ?? 'خطا در ارتباط با سرور'));
|
||
}
|
||
}
|
||
|
||
Future<void> _onVerifyOTP(VerifyOTPEvent event, Emitter<AuthState> emit) async {
|
||
emit(AuthLoading());
|
||
try {
|
||
final response = await _dio.post(
|
||
ApiConfig.baseUrl + ApiConfig.verifyCode,
|
||
data: {
|
||
'Phone': event.phoneNumber,
|
||
'Code': event.countryCode,
|
||
'OTP': event.otp,
|
||
},
|
||
);
|
||
|
||
if (isClosed) return; // FIX: Add check here
|
||
|
||
if (response.statusCode == 200) {
|
||
final accessToken = response.data['data']['accessToken'];
|
||
final refreshToken = response.data['data']['refreshToken'];
|
||
final userID = response.data['data']['ID'];
|
||
await _storage.write(key: 'accessToken', value: accessToken);
|
||
await _storage.write(key: 'refreshToken', value: refreshToken);
|
||
await _storage.write(key: 'userID', value: userID);
|
||
emit(AuthNeedsInfo());
|
||
} else {
|
||
emit(AuthFailure(response.data['message'] ?? 'کد صحیح نیست'));
|
||
}
|
||
} on DioException catch (e) {
|
||
if (isClosed) return; // FIX: Add check here
|
||
emit(AuthFailure(e.response?.data['message'] ?? 'خطایی در سرور رخ داد'));
|
||
}
|
||
}
|
||
|
||
Future<void> _onUpdateUserInfo(
|
||
UpdateUserInfoEvent event, Emitter<AuthState> emit) async {
|
||
// ******** لاگ ۱: شروع پردازش ********
|
||
debugPrint("AuthBloc: 🔵 ایونت UpdateUserInfoEvent دریافت شد با نام: ${event.name}");
|
||
emit(AuthLoading());
|
||
try {
|
||
final token = await _storage.read(key: 'accessToken');
|
||
if (token == null) {
|
||
// ******** لاگ خطا: توکن وجود ندارد ********
|
||
debugPrint("AuthBloc: 🔴 خطا: توکن کاربر یافت نشد.");
|
||
emit(const AuthFailure("شما وارد نشدهاید."));
|
||
return;
|
||
}
|
||
|
||
// ******** لاگ ۲: ارسال درخواست به سرور ********
|
||
debugPrint("AuthBloc: 🟡 در حال ارسال درخواست آپدیت به سرور...");
|
||
final response = await _dio.post(
|
||
ApiConfig.baseUrl + ApiConfig.updateUser,
|
||
data: {'Name': event.name, 'Gender': event.gender},
|
||
options: Options(headers: {'Authorization': 'Bearer $token'}),
|
||
);
|
||
|
||
// ******** لاگ ۳: پاسخ سرور ********
|
||
debugPrint("AuthBloc: 🟠 پاسخ سرور دریافت شد. StatusCode: ${response.statusCode}");
|
||
|
||
if (isClosed) {
|
||
debugPrint("AuthBloc: 🔴 خطا: BLoC قبل از اتمام عملیات بسته شده است.");
|
||
return;
|
||
}
|
||
|
||
if (response.statusCode == 200) {
|
||
// ******** لاگ ۴: موفقیتآمیز بودن عملیات ********
|
||
debugPrint("AuthBloc: ✅ درخواست موفق بود. در حال emit کردن AuthSuccess...");
|
||
emit(AuthSuccess());
|
||
} else {
|
||
// ******** لاگ خطا: پاسخ ناموفق از سرور ********
|
||
debugPrint("AuthBloc: 🔴 سرور پاسخ ناموفق داد: ${response.data['message']}");
|
||
emit(AuthFailure(response.data['message'] ?? 'خطا در ثبت اطلاعات'));
|
||
}
|
||
} on DioException catch (e) {
|
||
// ******** لاگ خطا: خطای Dio ********
|
||
debugPrint("AuthBloc: 🔴 خطای DioException رخ داد: ${e.response?.data['message']}");
|
||
if (isClosed) return;
|
||
emit(AuthFailure(e.response?.data['message'] ?? 'خطا در ارتباط با سرور'));
|
||
}
|
||
}
|
||
|
||
|
||
Future<void> _onLogout(LogoutEvent event, Emitter<AuthState> emit) async {
|
||
await _storage.deleteAll();
|
||
emit(AuthInitial());
|
||
}
|
||
} |