Initial commit

This commit is contained in:
jahongireshonqulov
2025-10-18 09:40:06 +05:00
commit 1bf3e41abe
352 changed files with 16315 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
import 'package:cargocalculaterapp/router/app_routes.dart';
import 'package:cargocalculaterapp/router/name_routes.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../data/model/price_calculate_request.dart';
import '../../domain/usecase/calculate_price_usecase.dart';
import '../arguments/calculator_info_argument.dart';
part 'calculator_event.dart';
part 'calculator_state.dart';
class CalculatorBloc extends Bloc<CalculatorEvent, CalculatorState> {
CalculatorBloc(this.calculatePriceUseCase)
: super(const CalculatorState(isLoading: false)) {
on<WeightSizeEnterEvent>(_weightSizeEntered);
on<WareHouseSelectEvent>(_wareHouseSelect);
on<CalculateEvent>(_calculate);
}
final CalculatePriceUseCase calculatePriceUseCase;
void _weightSizeEntered(
WeightSizeEnterEvent event,
Emitter<CalculatorState> emit,
) {
emit(
state.copyWith(
size: double.tryParse(event.size.replaceAll(",", "")),
weight: double.tryParse(event.weight.replaceAll(",", "")),
),
);
}
void _wareHouseSelect(
WareHouseSelectEvent event,
Emitter<CalculatorState> emit,
) {
emit(state.copyWith(selectedWarehouse: event.wareHouse));
}
Future<void> _calculate(
CalculateEvent event,
Emitter<CalculatorState> emit,
) async {
emit(state.copyWith(isLoading: true));
final response = await calculatePriceUseCase(
PriceCalculateRequest(
m3: state.size,
avg: (state.weight ?? 0) / (state.size ?? 1),
),
);
response.fold(
(l) {
emit(state.copyWith(isLoading: false));
},
(r) {
emit(state.copyWith(isLoading: false));
Navigator.pushNamed(
rootNavigatorKey.currentContext!,
Routes.calculationInfo,
arguments: CalculatorInfoArgument(
productName: event.productName,
deliveryPrice: r.price ?? 0,
size: state.size ?? 0,
averageWeight: (state.weight ?? 0) / (state.size ?? 1),
weight: state.weight ?? 0,
weraHouse: state.selectedWarehouse ?? "",
),
);
},
);
}
}

View File

@@ -0,0 +1,33 @@
part of 'calculator_bloc.dart';
sealed class CalculatorEvent extends Equatable {
const CalculatorEvent();
}
final class WeightSizeEnterEvent extends CalculatorEvent {
final String weight;
final String size;
const WeightSizeEnterEvent({required this.weight, required this.size});
@override
List<Object?> get props => [weight, size];
}
final class WareHouseSelectEvent extends CalculatorEvent {
final String wareHouse;
const WareHouseSelectEvent({required this.wareHouse});
@override
List<Object?> get props => [wareHouse];
}
final class CalculateEvent extends CalculatorEvent {
const CalculateEvent({required this.productName});
final String productName;
@override
List<Object?> get props => [productName];
}

View File

@@ -0,0 +1,120 @@
import 'package:cargocalculaterapp/core/extension/build_context_extension.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../../../constants/constants.dart';
import '../../../../../generated/l10n.dart';
import '../../../../../router/app_routes.dart';
import '../../../../../router/name_routes.dart';
import '../../../data/model/lead_create_request.dart';
import '../../../domain/usecase/create_lead_usecase.dart';
import '../../arguments/calculator_info_argument.dart';
import '../../pages/calculator_info/dialog/order_dialog.dart';
part 'calculator_info_event.dart';
part 'calculator_info_state.dart';
class CalculatorInfoBloc
extends Bloc<CalculatorInfoEvent, CalculatorInfoState> {
CalculatorInfoBloc(this.createLeadUseCase)
: super(const CalculatorInfoState(isLoading: false)) {
on<CreateLeadEvent>(_createLead);
on<ShowSuccessDialogEvent>(_showSuccessDialog);
}
final CreateLeadUseCase createLeadUseCase;
Future<void> _createLead(
CreateLeadEvent event,
Emitter<CalculatorInfoState> emit,
) async {
emit(state.copyWith(isLoading: true));
final local = Localizations.localeOf(
rootNavigatorKey.currentContext!,
).languageCode;
final response = await createLeadUseCase(
LeadCreateRequest(
status: "NOT_CONTACTED",
m3: "${event.argument.size}",
averageWeightKg: "${event.argument.averageWeight}",
weight: "${event.argument.weight}",
nameRu: local == "ru" ? event.argument.productName : "",
nameUz: local == "uz" ? event.argument.productName : "",
nameZh: local == "zh" ? event.argument.productName : "",
price: "${event.argument.deliveryPrice}",
warehouseCode: int.tryParse(event.argument.weraHouse),
wharehouseRu: AppConst.warehouseOptions[event.argument.weraHouse]?.ru,
wharehouseUz: AppConst.warehouseOptions[event.argument.weraHouse]?.uz,
wharehouseZh: AppConst.warehouseOptions[event.argument.weraHouse]?.zh,
),
);
response.fold(
(l) {
emit(state.copyWith(isLoading: false));
},
(r) {
emit(state.copyWith(isLoading: false));
add(ShowSuccessDialogEvent(isCall: event.isCall));
},
);
}
void _showSuccessDialog(
ShowSuccessDialogEvent event,
Emitter<CalculatorInfoState> emit,
) {
if (event.isCall) {
showCupertinoModalPopup(
context: rootNavigatorKey.currentContext!,
builder: (context) => CupertinoActionSheet(
actions: [
CupertinoActionSheetAction(
child: Text(
"+998 99-110-22-22",
style: TextStyle(color: context.color.primaryColor),
),
onPressed: () async {
final Uri url = Uri(scheme: 'tel', path: "+998991102222");
if (await canLaunchUrl(url)) {
await launchUrl(url);
}
Navigator.pop(rootNavigatorKey.currentContext!, true);
},
),
],
cancelButton: CupertinoActionSheetAction(
onPressed: () {
Navigator.pop(rootNavigatorKey.currentContext!);
},
child: Text(
AppLocalization.current.cancel,
style: TextStyle(color: context.color.textColor),
),
),
),
).then((value) {
if (value is bool) {
Navigator.pushNamedAndRemoveUntil(
rootNavigatorKey.currentContext!,
Routes.main,
(route) => false,
);
}
});
} else {
showDialog(
context: rootNavigatorKey.currentContext!,
builder: (context) => OrderDialog(isCall: event.isCall),
).then((value) {
Navigator.pushNamedAndRemoveUntil(
rootNavigatorKey.currentContext!,
Routes.main,
(route) => false,
);
});
}
}
}

View File

@@ -0,0 +1,24 @@
part of 'calculator_info_bloc.dart';
sealed class CalculatorInfoEvent extends Equatable {
const CalculatorInfoEvent();
}
final class CreateLeadEvent extends CalculatorInfoEvent {
const CreateLeadEvent({required this.argument, required this.isCall});
final bool isCall;
final CalculatorInfoArgument argument;
@override
List<Object?> get props => [argument, isCall];
}
final class ShowSuccessDialogEvent extends CalculatorInfoEvent {
const ShowSuccessDialogEvent({required this.isCall});
final bool isCall;
@override
List<Object?> get props => [isCall];
}

View File

@@ -0,0 +1,14 @@
part of 'calculator_info_bloc.dart';
class CalculatorInfoState extends Equatable {
const CalculatorInfoState({required this.isLoading});
final bool isLoading;
CalculatorInfoState copyWith({bool? isLoading}) {
return CalculatorInfoState(isLoading: isLoading ?? this.isLoading);
}
@override
List<Object?> get props => [isLoading];
}

View File

@@ -0,0 +1,32 @@
part of 'calculator_bloc.dart';
class CalculatorState extends Equatable {
const CalculatorState({
required this.isLoading,
this.weight,
this.size,
this.selectedWarehouse,
});
final bool isLoading;
final double? weight;
final double? size;
final String? selectedWarehouse;
CalculatorState copyWith({
bool? isLoading,
double? weight,
double? size,
String? selectedWarehouse,
}) {
return CalculatorState(
isLoading: isLoading ?? this.isLoading,
weight: weight ?? this.weight,
size: size ?? this.size,
selectedWarehouse: selectedWarehouse ?? this.selectedWarehouse,
);
}
@override
List<Object?> get props => [isLoading, weight, size, selectedWarehouse];
}