checkout form

This commit is contained in:
efrilm
2025-10-25 02:09:47 +07:00
parent e85138f27e
commit 013f313e35
13 changed files with 1719 additions and 4 deletions
@@ -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,
);
}