Files
be_happy_public/lib/presentation/viewmodel/tariff_sheet_bloc.dart
2026-05-12 12:03:37 +03:00

152 lines
4.4 KiB
Dart

import 'dart:async';
import 'package:be_happy/core/failures.dart';
import 'package:be_happy/domain/entities/scooter_order.dart';
import 'package:be_happy/domain/usecase/get_profile_usecase.dart';
import 'package:collection/collection.dart';
import 'package:be_happy/domain/entities/payment_card.dart';
import 'package:be_happy/domain/usecase/book_scooter_usecase.dart';
import 'package:be_happy/domain/usecase/get_payment_cards_usecase.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../core/result.dart';
import '../../domain/entities/tariff.dart';
import '../../domain/usecase/get_available_tariffs_usecase.dart';
import '../event/tariff_sheet_event.dart';
import '../state/tariff_sheet_state.dart';
class TariffSheetBloc extends Bloc<TariffSheetEvent, TariffSheetState> {
final GetAvailableTariffsUsecase _getAvailableTariffsUsecase;
final GetProfileUseCase _getProfileUseCase;
final GetPaymentCardsUsecase _getPaymentCardsUsecase;
final BookScooterUsecase _bookScooterUsecase;
TariffSheetBloc(
this._getAvailableTariffsUsecase,
this._getProfileUseCase,
this._getPaymentCardsUsecase,
this._bookScooterUsecase,
) : super(TariffSheetState(status: TariffSheetStatus.initial)) {
on<TariffSheetStarted>(_onStarted);
on<PaymentCardChanged>(_onPaymentCardChanged);
on<BookScooterPressed>(_onBookScooterPressed);
on<SelectBalancePressed>(_onSelectBalancePressed);
on<InsuranceToggled>(_onInsuranceToggled);
}
Future<void> _onStarted(
TariffSheetStarted event,
Emitter<TariffSheetState> emit,
) async {
emit(state.copyWith(status: TariffSheetStatus.loading));
try {
final result = await _getAvailableTariffsUsecase(event.scooterId);
final cards_result = await _getPaymentCardsUsecase();
if (result is Success<List<Tariff>> &&
cards_result is Success<List<PaymentCard>>) {
emit(
state.copyWith(
status: TariffSheetStatus.success,
tariffs: result.data ?? [],
selectedCard: cards_result.data?.firstWhereOrNull(
(element) => element.isMain,
),
),
);
} else {
emit(
state.copyWith(
status: TariffSheetStatus.failure,
errorMessage: 'Failed to load tariffs',
),
);
}
} catch (e, stackTrace) {
emit(
state.copyWith(
status: TariffSheetStatus.failure,
errorMessage: "ERROR: ${e.toString()} \n $stackTrace",
),
);
}
}
FutureOr<void> _onPaymentCardChanged(
PaymentCardChanged event,
Emitter<TariffSheetState> emit,
) {
try {
emit(
state.copyWith(
status: TariffSheetStatus.success,
selectedCard: event.card,
useBalance: false,
),
);
} catch (e) {
emit(
state.copyWith(
status: TariffSheetStatus.failure,
errorMessage: 'Failed to change card',
),
);
}
}
FutureOr<void> _onBookScooterPressed (
BookScooterPressed event,
Emitter<TariffSheetState> emit,
) async {
try {
final result = await _bookScooterUsecase(
scooterId: event.scooterId,
planId: event.planId,
cardId: event.cardId,
subscriptionId: event.subscriptionId,
isBalance: event.isBalance,
isInsurance: event.isInsurance,
);
switch (result) {
case Success<ScooterOrder>():
// TODO: Handle this case.
throw UnimplementedError();
case Failure<ScooterOrder>():
if (result is WrongZoneFailure) {
emit(
state.copyWith(
status: TariffSheetStatus.failure,
errorMessage: result.failure.message,
),
);
}
}
} catch (e) {
emit(
state.copyWith(
status: TariffSheetStatus.failure,
errorMessage: 'Failed to book scooter',
),
);
}
}
FutureOr<void> _onSelectBalancePressed(SelectBalancePressed event, Emitter<TariffSheetState> emit) async {
final profile = await _getProfileUseCase();
emit(state.copyWith(
useBalance: true,
userBalance: profile.balance,
selectedCard: null,
));
}
FutureOr<void> _onInsuranceToggled(InsuranceToggled event, Emitter<TariffSheetState> emit) async {
emit(state.copyWith(isInsurance: event.isEnabled));
}
}