import 'dart:developer'; import 'package:bloc/bloc.dart'; import 'package:enaklo_pos/data/datasources/product_local_datasource.dart'; import 'package:enaklo_pos/data/models/response/discount_response_model.dart'; import 'package:enaklo_pos/presentation/table/models/draft_order_item.dart'; import 'package:enaklo_pos/presentation/table/models/draft_order_model.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:intl/intl.dart'; import '../../../../data/models/response/product_response_model.dart'; import '../../../../data/datasources/settings_local_datasource.dart'; import '../../models/product_quantity.dart'; import '../../models/order_type.dart'; part 'checkout_event.dart'; part 'checkout_state.dart'; part 'checkout_bloc.freezed.dart'; class CheckoutBloc extends Bloc { final SettingsLocalDatasource settingsLocalDatasource; CheckoutBloc({required this.settingsLocalDatasource}) : super(const CheckoutState.initial()) { on<_AddItem>((event, emit) { var currentState = state as _Loaded; List items = [...currentState.items]; var index = items.indexWhere( (element) => element.product.id == event.product.id && element.variant?.id == event.variant?.id, ); emit(const _Loading()); if (index != -1) { items[index] = ProductQuantity( product: event.product, quantity: items[index].quantity + 1, variant: event.variant, ); } else { items.add( ProductQuantity( product: event.product, quantity: 1, variant: event.variant, ), ); } log("Items: $items"); emit(_Loaded( items, currentState.discountModel, currentState.discount, currentState.discountAmount, currentState.tax, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType)); }); on<_RemoveItem>((event, emit) { var currentState = state as _Loaded; List items = [...currentState.items]; var index = items.indexWhere( (element) => element.product.id == event.product.id && element.variant?.id == event.variant?.id, ); emit(const _Loading()); if (index != -1) { if (items[index].quantity > 1) { items[index] = ProductQuantity( product: event.product, quantity: items[index].quantity - 1, variant: event.variant); ; } else { items.removeAt(index); } } emit(_Loaded( items, currentState.discountModel, currentState.discount, currentState.discountAmount, currentState.tax, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType)); }); on<_DeleteItem>((event, emit) { var currentState = state as _Loaded; List items = [...currentState.items]; var index = items.indexWhere( (element) => element.product.id == event.product.id && element.variant?.id == event.variant?.id, ); emit(const _Loading()); items.removeAt(index); emit(_Loaded( items, currentState.discountModel, currentState.discount, currentState.discountAmount, currentState.tax, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType)); }); on<_Started>((event, emit) async { emit(const _Loading()); try { // Load tax and service charge from settings final tax = await settingsLocalDatasource.getTax(); final serviceCharge = await settingsLocalDatasource.getServiceCharge(); emit(_Loaded([], null, 0, 0, tax.value, serviceCharge, 0, 0, '', OrderType.dineIn)); } catch (e) { // If loading fails, use default values log('Failed to load settings: $e'); emit(const _Loaded([], null, 0, 0, 10, 5, 0, 0, '', OrderType.dineIn)); } }); on<_AddDiscount>((event, emit) { var currentState = state as _Loaded; emit(_Loaded( currentState.items, event.discount, currentState.discount, currentState.discountAmount, currentState.tax, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType, )); }); on<_RemoveDiscount>((event, emit) { var currentState = state as _Loaded; emit(_Loaded( currentState.items, null, currentState.discount, currentState.discountAmount, currentState.tax, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType)); }); on<_AddTax>((event, emit) { var currentState = state as _Loaded; emit(_Loaded( currentState.items, currentState.discountModel, currentState.discount, currentState.discountAmount, event.tax, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType)); }); on<_AddServiceCharge>((event, emit) { var currentState = state as _Loaded; emit(_Loaded( currentState.items, currentState.discountModel, currentState.discount, currentState.discountAmount, currentState.tax, event.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType, )); }); on<_RemoveTax>((event, emit) { var currentState = state as _Loaded; emit(_Loaded( currentState.items, currentState.discountModel, currentState.discount, currentState.discountAmount, 0, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType)); }); on<_RemoveServiceCharge>((event, emit) { var currentState = state as _Loaded; emit(_Loaded( currentState.items, currentState.discountModel, currentState.discount, currentState.discountAmount, currentState.tax, 0, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType)); }); on<_UpdateOrderType>((event, emit) { var currentState = state as _Loaded; emit(_Loaded( currentState.items, currentState.discountModel, currentState.discount, currentState.discountAmount, currentState.tax, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, event.orderType)); }); on<_UpdateItemNotes>((event, emit) { var currentState = state as _Loaded; List items = [...currentState.items]; var index = items.indexWhere((element) => element.product.id == event.product.id); if (index != -1) { items[index] = items[index].copyWith(notes: event.notes); } emit(_Loaded( items, currentState.discountModel, currentState.discount, currentState.discountAmount, currentState.tax, currentState.serviceCharge, currentState.totalQuantity, currentState.totalPrice, currentState.draftName, currentState.orderType)); }); on<_SaveDraftOrder>((event, emit) async { var currentStates = state as _Loaded; emit(const _Loading()); final draftOrder = DraftOrderModel( orders: currentStates.items .map((e) => DraftOrderItem( product: e.product, quantity: e.quantity, )) .toList(), totalQuantity: currentStates.totalQuantity, totalPrice: currentStates.totalPrice, discount: currentStates.discount, discountAmount: event.discountAmount, tax: currentStates.tax, serviceCharge: currentStates.serviceCharge, subTotal: currentStates.totalPrice, tableNumber: event.tableNumber, draftName: event.draftName, transactionTime: DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()), ); log("draftOrder12: ${draftOrder.toMapForLocal()}"); final orderDraftId = await ProductLocalDatasource.instance.saveDraftOrder(draftOrder); emit(_SavedDraftOrder(orderDraftId)); }); //load draft order on<_LoadDraftOrder>((event, emit) async { emit(const _Loading()); final draftOrder = event.data; log("draftOrder: ${draftOrder.toMap()}"); emit(_Loaded( draftOrder.orders .map((e) => ProductQuantity(product: e.product, quantity: e.quantity)) .toList(), null, draftOrder.discount, draftOrder.discountAmount, draftOrder.tax, draftOrder.serviceCharge, draftOrder.totalQuantity, draftOrder.totalPrice, draftOrder.draftName, OrderType.dineIn)); }); } }