proxibuy_bussiness/lib/presentation/discount/bloc/discount_bloc.dart

244 lines
7.4 KiB
Dart

import 'dart:developer';
import 'package:business_panel/core/config/api_config.dart';
import 'package:business_panel/core/services/token_storage_service.dart';
import 'package:business_panel/core/utils/logging_interceptor.dart';
import 'package:dio/dio.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'discount_event.dart';
import 'discount_state.dart';
class DiscountBloc extends Bloc<DiscountEvent, DiscountState> {
final Dio _dio = Dio();
final TokenStorageService _tokenStorage = TokenStorageService();
DiscountBloc() : super(const DiscountState()) {
_dio.interceptors.add(LoggingInterceptor());
on<FetchDiscountDetails>((event, emit) async {
emit(state.copyWith(isLoadingDetails: true, errorMessage: null));
try {
final token = await _tokenStorage.getAccessToken();
if (token == null) {
emit(
state.copyWith(
isLoadingDetails: false,
errorMessage: "خطای احراز هویت.",
),
);
return;
}
final response = await _dio.get(
ApiConfig.getDiscountById(event.discountId),
options: Options(headers: {'Authorization': 'Bearer $token'}),
);
if (response.statusCode == 200 && response.data['data'] != null) {
final data = response.data['data'];
List<Map<String, String?>> images = [];
if (data['Images'] is List) {
images = (data['Images'] as List)
.map<Map<String, String?>>(
(img) => {
'id': img['ID'] as String?,
'url': img['Url'] as String?,
},
)
.where((img) => img['url'] != null)
.toList();
}
final name = data['Name'] ?? '';
final typeId = data['Type']?['ID'];
final description = data['Description'] ?? '';
final price = data['Price']?.toString() ?? '0';
final nPrice = data['NPrice']?.toString() ?? '0';
final startDate =
data['StartDate'] != null ? DateTime.tryParse(data['StartDate']) : null;
final endDate =
data['EndDate'] != null ? DateTime.tryParse(data['EndDate']) : null;
final startTime = data['StartTime'];
final endTime = data['EndTime'];
final radius = (data['Radius'] as num?)?.toDouble() ?? 0.0;
emit(
state.copyWith(
isLoadingDetails: false,
discountId: data['_id'],
productName: name,
productImages: images,
discountTypeId: typeId,
description: description,
price: price,
discountedPrice: nPrice,
startDate: startDate,
endDate: endDate,
startTime: startTime,
endTime: endTime,
notificationRadius: radius,
),
);
} else {
emit(
state.copyWith(
isLoadingDetails: false,
errorMessage: "تخفیف یافت نشد.",
),
);
}
} catch (e) {
emit(
state.copyWith(
isLoadingDetails: false,
errorMessage: 'خطا در دریافت اطلاعات.',
),
);
}
});
on<ProductImageAdded>((event, emit) {
List<Map<String, String?>> updatedImages = List.from(state.productImages);
final newImageMap = {'id': null, 'url': event.imagePath};
if (updatedImages.length > event.index) {
updatedImages[event.index] = newImageMap;
} else {
updatedImages.add(newImageMap);
}
emit(state.copyWith(productImages: updatedImages));
});
on<ProductNameChanged>((event, emit) {
emit(state.copyWith(productName: event.name));
});
on<DiscountTypeChanged>((event, emit) {
emit(state.copyWith(discountTypeId: event.typeId));
});
on<DescriptionChanged>((event, emit) {
emit(state.copyWith(description: event.description));
});
on<ValidityDateChanged>((event, emit) {
emit(state.copyWith(startDate: event.startDate, endDate: event.endDate));
});
on<TimeRangeChanged>((event, emit) {
emit(state.copyWith(startTime: event.startTime, endTime: event.endTime));
});
on<PriceChanged>((event, emit) {
emit(state.copyWith(price: event.price));
});
on<DiscountedPriceChanged>((event, emit) {
emit(state.copyWith(discountedPrice: event.price));
});
on<NotificationRadiusChanged>((event, emit) {
emit(state.copyWith(notificationRadius: event.radius));
});
on<SubmitDiscount>((event, emit) async {
await _submitDiscountForm(emit, isEdit: false);
});
on<UpdateDiscount>((event, emit) async {
await _submitDiscountForm(
emit,
isEdit: true,
discountId: event.discountId,
);
});
on<ClearErrorMessage>((event, emit) {
emit(state.copyWith(clearErrorMessage: true));
});
}
Future<void> _submitDiscountForm(
Emitter<DiscountState> emit, {
required bool isEdit,
String? discountId,
}) async {
emit(state.copyWith(isSubmitting: true, errorMessage: null));
try {
final token = await _tokenStorage.getAccessToken();
if (token == null) {
emit(
state.copyWith(isSubmitting: false, errorMessage: "خطای احراز هویت."),
);
return;
}
final Map<String, dynamic> data = {
'Name': state.productName,
'Type': state.discountTypeId,
'Description': state.description,
'Price': double.tryParse(state.price),
'NPrice': double.tryParse(state.discountedPrice),
'Start': state.startDate?.toUtc().toIso8601String(),
'End': state.endDate?.toUtc().toIso8601String(),
'StartTime': state.startTime,
'EndTime': state.endTime,
'Radius': state.notificationRadius,
};
List<MultipartFile> newImageFiles = [];
List<String> existingImageIds = [];
for (var imageMap in state.productImages) {
final id = imageMap['id'];
final url = imageMap['url'];
if (id != null && url != null && url.startsWith('http')) {
existingImageIds.add(id);
} else if (url != null && !url.startsWith('http')) {
newImageFiles.add(
await MultipartFile.fromFile(url, filename: url.split('/').last),
);
}
}
if (newImageFiles.isNotEmpty) {
data['Images'] = newImageFiles;
}
if (isEdit) {
data['Picture'] = existingImageIds;
}
log('Submitting Discount Data: $data', name: 'DiscountBloc');
final formData = FormData.fromMap(data);
final url =
isEdit ? ApiConfig.editDiscount(discountId!) : ApiConfig.addDiscount;
await _dio.post(
url,
data: formData,
options: Options(headers: {'Authorization': 'Bearer $token'}),
);
emit(state.copyWith(isSubmitting: false, isSuccess: true));
}on DioException catch (e) {
emit(
state.copyWith(
isSubmitting: false,
errorMessage: e.response?.data['message'] ?? 'خطای سرور.',
),
);
} catch (e) {
emit(
state.copyWith(
isSubmitting: false,
errorMessage: 'خطای ناشناخته: ${e.toString()}',
),
);
}
}
}