feat: implement core architecture, design system, localization, and trip features for both driver and rider apps.
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../data/tariff_repository.dart';
|
||||
import '../data/models/quote_model.dart';
|
||||
|
||||
/// حالة شاشة اختيار فئة الرحلة + السعر.
|
||||
class QuoteState extends Equatable {
|
||||
final bool loading;
|
||||
final QuoteModel? quote;
|
||||
final String? selectedClass;
|
||||
final String paymentMethod;
|
||||
final String? couponCode;
|
||||
final String? error;
|
||||
|
||||
const QuoteState({
|
||||
this.loading = false,
|
||||
this.quote,
|
||||
this.selectedClass,
|
||||
this.paymentMethod = 'cash',
|
||||
this.couponCode,
|
||||
this.error,
|
||||
});
|
||||
|
||||
QuoteState copyWith({
|
||||
bool? loading,
|
||||
QuoteModel? quote,
|
||||
String? selectedClass,
|
||||
String? paymentMethod,
|
||||
String? couponCode,
|
||||
String? error,
|
||||
bool clearError = false,
|
||||
bool clearCoupon = false,
|
||||
}) {
|
||||
return QuoteState(
|
||||
loading: loading ?? this.loading,
|
||||
quote: quote ?? this.quote,
|
||||
selectedClass: selectedClass ?? this.selectedClass,
|
||||
paymentMethod: paymentMethod ?? this.paymentMethod,
|
||||
couponCode: clearCoupon ? null : (couponCode ?? this.couponCode),
|
||||
error: clearError ? null : (error ?? this.error),
|
||||
);
|
||||
}
|
||||
|
||||
QuoteClassModel? get selectedQuoteClass {
|
||||
if (quote == null || selectedClass == null) return null;
|
||||
try {
|
||||
return quote!.classes.firstWhere((c) => c.vehicleClass == selectedClass);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [loading, quote, selectedClass, paymentMethod, couponCode, error];
|
||||
}
|
||||
|
||||
/// جلب الأسعار واختيار الفئة.
|
||||
class QuoteCubit extends Cubit<QuoteState> {
|
||||
final TariffRepository _tariffRepo;
|
||||
|
||||
QuoteCubit(this._tariffRepo) : super(const QuoteState());
|
||||
|
||||
Future<void> fetchQuote({
|
||||
required double pickupLat,
|
||||
required double pickupLng,
|
||||
String? pickupAddress,
|
||||
required double dropoffLat,
|
||||
required double dropoffLng,
|
||||
String? dropoffAddress,
|
||||
List<Map<String, dynamic>>? stops,
|
||||
String? vehicleClass,
|
||||
String? scheduledAt,
|
||||
}) async {
|
||||
emit(state.copyWith(loading: true, clearError: true));
|
||||
try {
|
||||
final quote = await _tariffRepo.getQuote(
|
||||
pickupLat: pickupLat,
|
||||
pickupLng: pickupLng,
|
||||
pickupAddress: pickupAddress,
|
||||
dropoffLat: dropoffLat,
|
||||
dropoffLng: dropoffLng,
|
||||
dropoffAddress: dropoffAddress,
|
||||
vehicleClass: vehicleClass,
|
||||
scheduledAt: scheduledAt,
|
||||
);
|
||||
final firstClass = quote.classes.isNotEmpty ? quote.classes.first.vehicleClass : null;
|
||||
emit(state.copyWith(
|
||||
loading: false,
|
||||
quote: quote,
|
||||
selectedClass: firstClass,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(state.copyWith(loading: false, error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void selectClass(String vehicleClass) {
|
||||
emit(state.copyWith(selectedClass: vehicleClass));
|
||||
}
|
||||
|
||||
void setPaymentMethod(String method) {
|
||||
emit(state.copyWith(paymentMethod: method));
|
||||
}
|
||||
|
||||
void setCouponCode(String? code) {
|
||||
emit(state.copyWith(couponCode: code));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user