proxibuy/lib/presentation/auth/bloc/auth_bloc.dart

184 lines
5.7 KiB
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);
on<SendFcmTokenEvent>(_onSendFcmToken);
}
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;
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;
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) {
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());
}
Future<void> _onSendFcmToken(
SendFcmTokenEvent event,
Emitter<AuthState> emit,
) async {
try {
final token = await _storage.read(key: 'accessToken');
if (token == null) {
emit(const AuthFailure("شما وارد نشده‌اید."));
return;
}
await _dio.post(
ApiConfig.baseUrl + ApiConfig.updateFcmToken,
data: {'Token': event.fcmToken},
options: Options(headers: {'Authorization': 'Bearer $token'}),
);
print("Firebase token: ${event.fcmToken}");
} on DioException catch (e) {
debugPrint("Error sending FCM token: ${e.response?.data['message']}");
}
}
}