checkout form
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
|
||||
import '../../../common/types/order_type.dart';
|
||||
import '../../../domain/delivery/delivery.dart';
|
||||
import '../../../domain/product/product.dart';
|
||||
|
||||
part 'checkout_form_event.dart';
|
||||
part 'checkout_form_state.dart';
|
||||
part 'checkout_form_bloc.freezed.dart';
|
||||
|
||||
@injectable
|
||||
class CheckoutFormBloc extends Bloc<CheckoutFormEvent, CheckoutFormState> {
|
||||
CheckoutFormBloc() : super(CheckoutFormState.initial()) {
|
||||
on<CheckoutFormEvent>(_onCheckoutFormEvent);
|
||||
}
|
||||
Future<void> _onCheckoutFormEvent(
|
||||
CheckoutFormEvent event,
|
||||
Emitter<CheckoutFormState> emit,
|
||||
) {
|
||||
return event.map(
|
||||
addItem: (e) async {
|
||||
final currentState = state;
|
||||
emit(currentState.copyWith(isLoading: true));
|
||||
|
||||
List<ProductQuantity> items = [...currentState.items];
|
||||
|
||||
final index = items.indexWhere(
|
||||
(element) =>
|
||||
element.product.id == e.product.id &&
|
||||
element.variant?.id == e.variant?.id,
|
||||
);
|
||||
|
||||
if (index != -1) {
|
||||
// Jika sudah ada → tambah quantity
|
||||
items[index] = items[index].copyWith(
|
||||
quantity: items[index].quantity + 1,
|
||||
);
|
||||
} else {
|
||||
// Jika belum ada → tambahkan item baru
|
||||
items.add(
|
||||
ProductQuantity(
|
||||
product: e.product,
|
||||
quantity: 1,
|
||||
variant: e.variant,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
log('🛒 Items updated: ${items.length} items total');
|
||||
|
||||
final totalQuantity = items.fold<int>(
|
||||
0,
|
||||
(sum, item) => sum + item.quantity,
|
||||
);
|
||||
final totalPrice = items.fold<int>(
|
||||
0,
|
||||
(sum, item) =>
|
||||
sum +
|
||||
(item.quantity *
|
||||
(item.variant?.priceModifier.toInt() ??
|
||||
item.product.price.toInt())),
|
||||
);
|
||||
|
||||
emit(
|
||||
currentState.copyWith(
|
||||
items: items,
|
||||
totalQuantity: totalQuantity,
|
||||
totalPrice: totalPrice,
|
||||
isLoading: false,
|
||||
),
|
||||
);
|
||||
},
|
||||
removeItem: (e) async {
|
||||
final currentState = state;
|
||||
emit(currentState.copyWith(isLoading: true));
|
||||
List<ProductQuantity> items = [...currentState.items];
|
||||
|
||||
final index = items.indexWhere(
|
||||
(element) =>
|
||||
element.product.id == e.product.id &&
|
||||
element.variant?.id == e.variant?.id,
|
||||
);
|
||||
|
||||
if (index != -1) {
|
||||
final currentItem = items[index];
|
||||
if (currentItem.quantity > 1) {
|
||||
// Kurangi quantity
|
||||
items[index] = currentItem.copyWith(
|
||||
quantity: currentItem.quantity - 1,
|
||||
);
|
||||
} else {
|
||||
// Hapus item kalau quantity = 1
|
||||
items.removeAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
final totalQuantity = items.fold<int>(
|
||||
0,
|
||||
(sum, item) => sum + item.quantity,
|
||||
);
|
||||
final totalPrice = items.fold<int>(
|
||||
0,
|
||||
(sum, item) =>
|
||||
sum +
|
||||
(item.quantity *
|
||||
(item.variant?.priceModifier.toInt() ??
|
||||
item.product.price.toInt())),
|
||||
);
|
||||
|
||||
log(
|
||||
'🗑️ Item removed. Total items: ${items.length}, totalQuantity: $totalQuantity, totalPrice: $totalPrice',
|
||||
);
|
||||
|
||||
// Emit state baru
|
||||
emit(
|
||||
currentState.copyWith(
|
||||
items: items,
|
||||
totalQuantity: totalQuantity,
|
||||
totalPrice: totalPrice,
|
||||
isLoading: false,
|
||||
),
|
||||
);
|
||||
},
|
||||
started: (e) async {
|
||||
emit(CheckoutFormState.initial().copyWith(isLoading: true));
|
||||
try {
|
||||
emit(
|
||||
CheckoutFormState.initial().copyWith(
|
||||
items: e.items,
|
||||
tax: 0,
|
||||
serviceCharge: 0,
|
||||
isLoading: false,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
// Kalau gagal, pakai default values
|
||||
log('⚠️ Failed to load settings: $e');
|
||||
emit(
|
||||
CheckoutFormState.initial().copyWith(
|
||||
tax: 10,
|
||||
serviceCharge: 5,
|
||||
isLoading: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
updateItemNotes: (e) async {
|
||||
final currentState = state;
|
||||
|
||||
// Clone list items agar tidak mutasi langsung
|
||||
final items = [...currentState.items];
|
||||
final index = items.indexWhere(
|
||||
(element) => element.product.id == e.product.id,
|
||||
);
|
||||
|
||||
if (index != -1) {
|
||||
items[index] = items[index].copyWith(notes: e.notes);
|
||||
}
|
||||
|
||||
emit(currentState.copyWith(items: items, isLoading: false));
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
part of 'checkout_form_bloc.dart';
|
||||
|
||||
@freezed
|
||||
class CheckoutFormEvent with _$CheckoutFormEvent {
|
||||
const factory CheckoutFormEvent.started(List<ProductQuantity> items) =
|
||||
_Started;
|
||||
|
||||
const factory CheckoutFormEvent.addItem(
|
||||
Product product,
|
||||
ProductVariant? variant,
|
||||
) = _AddItem;
|
||||
|
||||
const factory CheckoutFormEvent.removeItem(
|
||||
Product product,
|
||||
ProductVariant? variant,
|
||||
) = _RemoveItem;
|
||||
|
||||
const factory CheckoutFormEvent.updateItemNotes(
|
||||
Product product,
|
||||
String notes,
|
||||
) = _UpdateItemNotes;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
part of 'checkout_form_bloc.dart';
|
||||
|
||||
@freezed
|
||||
class CheckoutFormState with _$CheckoutFormState {
|
||||
factory CheckoutFormState({
|
||||
required List<ProductQuantity> items,
|
||||
required int discount,
|
||||
required int discountAmount,
|
||||
required int tax,
|
||||
required int serviceCharge,
|
||||
required int totalQuantity,
|
||||
required int totalPrice,
|
||||
required String draftName,
|
||||
required OrderType orderType,
|
||||
Delivery? delivery,
|
||||
@Default(false) bool isLoading,
|
||||
}) = _CheckoutFormState;
|
||||
|
||||
factory CheckoutFormState.initial() => CheckoutFormState(
|
||||
items: [],
|
||||
discount: 0,
|
||||
discountAmount: 0,
|
||||
tax: 0,
|
||||
serviceCharge: 0,
|
||||
totalQuantity: 0,
|
||||
totalPrice: 0,
|
||||
draftName: '',
|
||||
orderType: OrderType.dineIn,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user