order detail fetch
This commit is contained in:
parent
0ad7d44642
commit
883c196aae
|
|
@ -1,3 +1,6 @@
|
|||
{
|
||||
"dart.flutterSdkPath": ".fvm/versions/3.22.1"
|
||||
"dart.flutterSdkPath": ".fvm/versions/3.22.1",
|
||||
"cSpell.words": [
|
||||
"dartz"
|
||||
]
|
||||
}
|
||||
|
|
@ -3,3 +3,4 @@ export 'language_bloc/language_bloc.dart';
|
|||
export 'splash_cubit/splash_cubit.dart';
|
||||
export 'user_bloc/user_bloc.dart';
|
||||
export 'order_bloc/order_bloc.dart';
|
||||
export 'order_detail_bloc/order_detail_bloc.dart';
|
||||
|
|
|
|||
|
|
@ -27,10 +27,7 @@ class OrderBloc extends Bloc<OrderEvent, OrderState> {
|
|||
on<GetMoreOrders>(_onLoadMoreOrders);
|
||||
}
|
||||
|
||||
FutureOr<void> _onGetOrders(
|
||||
GetOrders event,
|
||||
Emitter<OrderState> emit,
|
||||
) async {
|
||||
FutureOr<void> _onGetOrders(GetOrders event, Emitter<OrderState> emit) async {
|
||||
try {
|
||||
emit(OrderLoading(
|
||||
orders: const [],
|
||||
|
|
@ -61,7 +58,7 @@ class OrderBloc extends Bloc<OrderEvent, OrderState> {
|
|||
}
|
||||
}
|
||||
|
||||
void _onLoadMoreOrders(GetMoreOrders event, Emitter<OrderState> emit) async {
|
||||
Future<void> _onLoadMoreOrders(GetMoreOrders event, Emitter<OrderState> emit) async {
|
||||
var state = this.state;
|
||||
var limit = state.metaData.limit;
|
||||
var total = state.metaData.total;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../core/errors/failures.dart';
|
||||
import '../../domain/entities/route/route.dart';
|
||||
import '../../domain/usecases/order/get_routes_usecase.dart';
|
||||
|
||||
part 'order_detail_event.dart';
|
||||
part 'order_detail_state.dart';
|
||||
|
||||
class OrderDetailBloc extends Bloc<OrderDetailEvent, OrderDetailState> {
|
||||
final GetRoutesUseCase _getRoutesUseCase;
|
||||
|
||||
OrderDetailBloc(this._getRoutesUseCase) : super(OrderDetailInitial()) {
|
||||
on<GetRoutes>(_onGetRoutes);
|
||||
}
|
||||
|
||||
FutureOr<void> _onGetRoutes(GetRoutes event, Emitter<OrderDetailState> emit) async {
|
||||
try {
|
||||
emit(RoutesLoading());
|
||||
final result = await _getRoutesUseCase(event.cargoId);
|
||||
result.fold(
|
||||
(failure) => emit(RoutesError(failure: failure)),
|
||||
(response) => emit(RoutesLoaded(routes: response.routes)),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(RoutesError(failure: ExceptionFailure()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
part of 'order_detail_bloc.dart';
|
||||
|
||||
sealed class OrderDetailEvent extends Equatable {
|
||||
const OrderDetailEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class GetRoutes extends OrderDetailEvent {
|
||||
final String cargoId;
|
||||
const GetRoutes(this.cargoId);
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
part of 'order_detail_bloc.dart';
|
||||
|
||||
sealed class OrderDetailState extends Equatable {
|
||||
const OrderDetailState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class OrderDetailInitial extends OrderDetailState {}
|
||||
|
||||
class RoutesLoading extends OrderDetailState {}
|
||||
|
||||
class RoutesLoaded extends OrderDetailState {
|
||||
final List<RouteEntity> routes;
|
||||
const RoutesLoaded({required this.routes});
|
||||
@override
|
||||
List<Object> get props => [routes];
|
||||
}
|
||||
|
||||
class RoutesError extends OrderDetailState {
|
||||
final Failure failure;
|
||||
const RoutesError({
|
||||
required this.failure,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
|
@ -27,6 +27,9 @@ class MyApp extends StatelessWidget {
|
|||
BlocProvider(
|
||||
create: (context) => di.sl<OrderBloc>()..add(const GetOrders(FilterProductParams())),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (context) => di.sl<OrderDetailBloc>(),
|
||||
),
|
||||
],
|
||||
child: MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cargo/domain/domain.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../presentation/presentation.dart';
|
||||
|
|
@ -22,7 +23,8 @@ sealed class AppRouter {
|
|||
case root:
|
||||
return MaterialPageRoute(builder: (_) => const RootScreen());
|
||||
case orderDetails:
|
||||
return MaterialPageRoute(builder: (_) => const OrderDetailsScreen());
|
||||
OrderEntity order = routeSettings.arguments as OrderEntity;
|
||||
return MaterialPageRoute(builder: (_) => OrderDetailsScreen(order: order));
|
||||
|
||||
default:
|
||||
throw const RouteException('Route not found!');
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@ import 'package:http/http.dart' as http;
|
|||
import '../../../core/core.dart';
|
||||
import '../../../domain/domain.dart';
|
||||
import '../../data.dart';
|
||||
import '../../models/route/route_response_model.dart';
|
||||
|
||||
abstract class OrderRemoteDataSource {
|
||||
Future<OrderResponseModel> getOrders(FilterProductParams params, String token);
|
||||
Future<RouteResponseModel> getRoutes(String orderId);
|
||||
}
|
||||
|
||||
class OrderRemoteDataSourceImpl implements OrderRemoteDataSource {
|
||||
|
|
@ -29,4 +31,21 @@ class OrderRemoteDataSourceImpl implements OrderRemoteDataSource {
|
|||
throw ServerException();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<RouteResponseModel> getRoutes(String orderId) async {
|
||||
final response = await client.get(
|
||||
Uri.parse('$baseUrl/Cargo/Route/$orderId'),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'accept': '*/*',
|
||||
},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return routeResponseModelFromJson(response.body);
|
||||
} else {
|
||||
throw ServerException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@ export 'user/authentication_response_model.dart';
|
|||
export 'user/user_model.dart';
|
||||
export 'order/order_model.dart';
|
||||
export 'order/order_response_model.dart';
|
||||
export 'route/route_model.dart';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
import 'package:cargo/domain/domain.dart';
|
||||
|
||||
class RouteModel extends RouteEntity {
|
||||
const RouteModel({
|
||||
required super.name,
|
||||
required super.lat,
|
||||
required super.long,
|
||||
required super.isCurrent,
|
||||
});
|
||||
|
||||
factory RouteModel.fromJson(Map<String, dynamic> json) {
|
||||
return RouteModel(
|
||||
name: json['Name'],
|
||||
lat: json['Lat'] + .0,
|
||||
long: json['Long'] + .0,
|
||||
isCurrent: json['IsCurrent'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'Name': name,
|
||||
'Lat': lat,
|
||||
'Long': long,
|
||||
'IsCurrent': isCurrent,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import '../../../domain/domain.dart';
|
||||
import 'route_model.dart';
|
||||
|
||||
RouteResponseModel routeResponseModelFromJson(String str) => RouteResponseModel.fromJson(json.decode(str));
|
||||
|
||||
class RouteResponseModel extends RouteResponse {
|
||||
RouteResponseModel({
|
||||
required super.routes,
|
||||
});
|
||||
|
||||
factory RouteResponseModel.fromJson(List<dynamic> jsonList) {
|
||||
return RouteResponseModel(
|
||||
routes: jsonList.map((json) => RouteModel.fromJson(json)).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cargo/data/models/route/route_response_model.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import '../../core/core.dart';
|
||||
|
|
@ -34,4 +35,18 @@ class OrderRepositoryImpl extends OrderRepository {
|
|||
return Left(failure);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, RouteResponseModel>> getRoutes(String cargoId) async {
|
||||
if (!await networkInfo.isConnected) {
|
||||
return Left(NetworkFailure());
|
||||
}
|
||||
|
||||
try {
|
||||
final response = await remoteDataSource.getRoutes(cargoId);
|
||||
return Right(response);
|
||||
} on Failure catch (failure) {
|
||||
return Left(failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ void registerOrderFeature() {
|
|||
sl.registerFactory(() => OrderBloc(sl()));
|
||||
sl.registerLazySingleton(() => GetOrderUseCase(sl()));
|
||||
|
||||
// OrderDetails
|
||||
sl.registerFactory(() => OrderDetailBloc(sl()));
|
||||
sl.registerLazySingleton(() => GetRoutesUseCase(sl()));
|
||||
|
||||
// Order Repository and Data Sources
|
||||
sl.registerLazySingleton<OrderRepository>(
|
||||
() => OrderRepositoryImpl(
|
||||
|
|
|
|||
|
|
@ -3,3 +3,5 @@ export 'order/order.dart';
|
|||
export 'order/filter_params_model.dart';
|
||||
export 'order/order_response.dart';
|
||||
export 'order/pagination_meta_data.dart';
|
||||
export 'route/route.dart';
|
||||
export 'route/route_response.dart';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class RouteEntity extends Equatable {
|
||||
final String name;
|
||||
final double lat;
|
||||
final double long;
|
||||
final bool isCurrent;
|
||||
|
||||
const RouteEntity({
|
||||
required this.name,
|
||||
required this.lat,
|
||||
required this.long,
|
||||
required this.isCurrent,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [name, lat, long, isCurrent];
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import 'route.dart';
|
||||
|
||||
class RouteResponse {
|
||||
final List<RouteEntity> routes;
|
||||
|
||||
RouteResponse({required this.routes});
|
||||
}
|
||||
|
|
@ -2,8 +2,10 @@ import 'package:dartz/dartz.dart';
|
|||
|
||||
import '../../core/errors/failures.dart';
|
||||
import '../../data/models/order/order_response_model.dart';
|
||||
import '../../data/models/route/route_response_model.dart';
|
||||
import '../domain.dart';
|
||||
|
||||
abstract class OrderRepository {
|
||||
Future<Either<Failure, OrderResponseModel>> getOrders(FilterProductParams params);
|
||||
Future<Either<Failure, RouteResponseModel>> getRoutes(String cargoId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import '../../../core/core.dart';
|
||||
import '../../../data/models/route/route_response_model.dart';
|
||||
import '../../domain.dart';
|
||||
|
||||
class GetRoutesUseCase implements UseCase<RouteResponseModel, String> {
|
||||
final OrderRepository repository;
|
||||
GetRoutesUseCase(this.repository);
|
||||
|
||||
@override
|
||||
Future<Either<Failure, RouteResponseModel>> call(String cargoId) async {
|
||||
return await repository.getRoutes(cargoId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1,2 @@
|
|||
export 'get_orders_usecase.dart';
|
||||
export 'get_routes_usecase.dart';
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||
final TextEditingController _userNameController = TextEditingController();
|
||||
final TextEditingController _passwordController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
bool _obscureText = false;
|
||||
bool _obscureText = true;
|
||||
|
||||
void _nextScreen() {
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
|
|
|
|||
|
|
@ -1,12 +1,27 @@
|
|||
import 'package:cargo/application/application.dart';
|
||||
import 'package:cargo/configs/configs.dart';
|
||||
import 'package:cargo/domain/domain.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../core/core.dart';
|
||||
import '../widgets/map/clustering.dart';
|
||||
import '../widgets/widgets.dart';
|
||||
|
||||
class OrderDetailsScreen extends StatelessWidget {
|
||||
const OrderDetailsScreen({super.key});
|
||||
class OrderDetailsScreen extends StatefulWidget {
|
||||
final OrderEntity order;
|
||||
const OrderDetailsScreen({super.key, required this.order});
|
||||
|
||||
@override
|
||||
State<OrderDetailsScreen> createState() => _OrderDetailsScreenState();
|
||||
}
|
||||
|
||||
class _OrderDetailsScreenState extends State<OrderDetailsScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
context.read<OrderDetailBloc>().add(GetRoutes(widget.order.cargoId));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -71,7 +86,7 @@ class OrderDetailsScreen extends StatelessWidget {
|
|||
Space.y!,
|
||||
|
||||
/// location card
|
||||
const LocationCard()
|
||||
LocationCard(cargoId: widget.order.cargoId)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -13,14 +13,10 @@ class OrdersScreen extends StatefulWidget {
|
|||
State<OrdersScreen> createState() => _OrdersScreenState();
|
||||
}
|
||||
|
||||
class _OrdersScreenState extends State<OrdersScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
class _OrdersScreenState extends State<OrdersScreen> with AutomaticKeepAliveClientMixin<OrdersScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
App.init(context);
|
||||
|
||||
return Scaffold(
|
||||
|
|
@ -106,4 +102,7 @@ class _OrdersScreenState extends State<OrdersScreen> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,27 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../application/application.dart';
|
||||
import '../../configs/configs.dart';
|
||||
import '../../core/core.dart';
|
||||
import 'dashed_line.dart';
|
||||
import 'retry_widget.dart';
|
||||
|
||||
class LocationCard extends StatelessWidget {
|
||||
const LocationCard({super.key});
|
||||
final String cargoId;
|
||||
const LocationCard({super.key, required this.cargoId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<OrderDetailBloc, OrderDetailState>(
|
||||
builder: (context, state) {
|
||||
if (state is RoutesLoading) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
} else if (state is RoutesLoaded) {
|
||||
final routes = state.routes;
|
||||
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: Card(
|
||||
|
|
@ -19,15 +32,16 @@ class LocationCard extends StatelessWidget {
|
|||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
final route = routes[index];
|
||||
return Row(
|
||||
children: [
|
||||
index % 2 == 0
|
||||
route.isCurrent
|
||||
? const Icon(
|
||||
Icons.radio_button_checked,
|
||||
color: AppColors.grey,
|
||||
)
|
||||
: Container(
|
||||
margin: Space.hf(0.35), //const EdgeInsets.only(left: 6),
|
||||
margin: Space.hf(0.35),
|
||||
height: AppDimensions.normalize(4.5),
|
||||
width: AppDimensions.normalize(4.5),
|
||||
decoration: const BoxDecoration(
|
||||
|
|
@ -37,18 +51,18 @@ class LocationCard extends StatelessWidget {
|
|||
),
|
||||
Space.x!,
|
||||
Text(
|
||||
routess[index].city,
|
||||
routes[index].name,
|
||||
style: AppText.b1b,
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
routess[index].date,
|
||||
'30.02.2024', // routes[index].date,
|
||||
style: AppText.b1!.copyWith(color: AppColors.grey),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
itemCount: routess.length,
|
||||
itemCount: routes.length,
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Padding(
|
||||
padding: Space.vf(0.5),
|
||||
|
|
@ -66,20 +80,16 @@ class LocationCard extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
);
|
||||
} else if (state is RoutesError) {
|
||||
return Center(
|
||||
child: RetryWidget(onRetry: () {
|
||||
context.read<OrderDetailBloc>().add(GetRoutes(cargoId));
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Path {
|
||||
final String city;
|
||||
final String date;
|
||||
|
||||
Path(this.city, this.date);
|
||||
}
|
||||
|
||||
List<Path> routess = [
|
||||
Path('Urumchi', '10.07.2024'),
|
||||
Path('Astana', '14.07.2024'),
|
||||
Path('Tashkent', '16.07.2024'),
|
||||
Path('Samarkant', '25.07.2024'),
|
||||
Path('Mary', '30.07.2024'),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ class OrderCard extends StatelessWidget {
|
|||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(AppRouter.orderDetails);
|
||||
Navigator.of(context).pushNamed(
|
||||
AppRouter.orderDetails,
|
||||
arguments: order,
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'Ginişleýin >',
|
||||
|
|
|
|||
Loading…
Reference in New Issue