added painter
This commit is contained in:
parent
0eead07f00
commit
b946ef0f59
Binary file not shown.
|
After Width: | Height: | Size: 774 B |
Binary file not shown.
|
After Width: | Height: | Size: 243 B |
|
|
@ -1,11 +1,17 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:another_stepper/another_stepper.dart';
|
||||
import 'package:cargo/core/constants/colors.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import '../../core/constants/assets.dart';
|
||||
import '../../core/errors/failures.dart';
|
||||
import '../../domain/entities/route/route.dart';
|
||||
import '../../domain/usecases/order/get_routes_usecase.dart';
|
||||
import '../../presentation/widgets/circle_painter.dart';
|
||||
|
||||
part 'order_detail_event.dart';
|
||||
part 'order_detail_state.dart';
|
||||
|
|
@ -23,7 +29,87 @@ class OrderDetailBloc extends Bloc<OrderDetailEvent, OrderDetailState> {
|
|||
final result = await _getRoutesUseCase(event.cargoId);
|
||||
result.fold(
|
||||
(failure) => emit(RoutesError(failure: failure)),
|
||||
(response) => emit(RoutesLoaded(routes: response.routes)),
|
||||
(response) {
|
||||
// Find the index of the current route
|
||||
int currentIndex = response.routes.indexWhere((r) => r.isCurrent);
|
||||
|
||||
emit(
|
||||
RoutesLoaded(
|
||||
routes: response.routes,
|
||||
activeIndex: currentIndex,
|
||||
steppers: response.routes.mapIndexed((index, route) {
|
||||
// Determine if the icon should be splashed
|
||||
final bool isSplashedIcon = index == 0 || index == response.routes.length - 1;
|
||||
|
||||
// Determine the color based on the conditions
|
||||
Color textColor;
|
||||
Color iconColor;
|
||||
|
||||
if (route.isCurrent) {
|
||||
textColor = AppColors.greenDark;
|
||||
iconColor = AppColors.greenDark;
|
||||
} else if (index < currentIndex) {
|
||||
textColor = const Color(0xFFD8D8DA);
|
||||
iconColor = AppColors.greenDark;
|
||||
} else {
|
||||
textColor = AppColors.darkGrey;
|
||||
iconColor = AppColors.darkGrey;
|
||||
}
|
||||
|
||||
return StepperData(
|
||||
title: StepperText(
|
||||
route.name,
|
||||
textStyle: TextStyle(
|
||||
color: textColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
subtitle: StepperText(
|
||||
route.dateAt,
|
||||
textStyle: TextStyle(
|
||||
color: textColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
iconWidget: isSplashedIcon
|
||||
? Image.asset(
|
||||
AppAssets.circle,
|
||||
color: iconColor,
|
||||
)
|
||||
: CirclePainterWidget(
|
||||
radius: 8,
|
||||
color: iconColor,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
/* RoutesLoaded(
|
||||
routes: response.routes,
|
||||
steppers: response.routes.mapIndexed((index, route) {
|
||||
return StepperData(
|
||||
title: StepperText(
|
||||
route.name,
|
||||
textStyle: const TextStyle(
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
subtitle: StepperText(route.dateAt),
|
||||
iconWidget: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.green,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(18),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
), */
|
||||
);
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
emit(RoutesError(failure: ExceptionFailure()));
|
||||
|
|
|
|||
|
|
@ -13,9 +13,15 @@ class RoutesLoading extends OrderDetailState {}
|
|||
|
||||
class RoutesLoaded extends OrderDetailState {
|
||||
final List<RouteEntity> routes;
|
||||
const RoutesLoaded({required this.routes});
|
||||
final List<StepperData> steppers;
|
||||
final int activeIndex;
|
||||
const RoutesLoaded({
|
||||
required this.routes,
|
||||
required this.steppers,
|
||||
required this.activeIndex,
|
||||
});
|
||||
@override
|
||||
List<Object> get props => [routes];
|
||||
List<Object> get props => [routes, steppers, activeIndex];
|
||||
}
|
||||
|
||||
class RoutesError extends OrderDetailState {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ sealed class AppAssets {
|
|||
static const String boxesPng = 'assets/images/boxes.png';
|
||||
static const String trucksPng = 'assets/images/trucks.png';
|
||||
static const String header = 'assets/images/header.png';
|
||||
static const String circle = 'assets/images/circle.png';
|
||||
static const String circle2 = 'assets/images/circle2.png';
|
||||
static const String search = 'assets/images/search.png';
|
||||
static const String searchGif = 'assets/images/search.gif';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ sealed class AppColors {
|
|||
static const Color yellow = Color(0xFFFFC71E);
|
||||
static const Color surface = Color(0xFFEDEEFC);
|
||||
static const Color green = Color(0xFFA2E052);
|
||||
static const Color greenDark = Color(0xFF61971B);
|
||||
static const Color grey = Color(0xFF96969C);
|
||||
static const Color darkGrey = Color(0xFF57575C);
|
||||
static const Color lightGrey = Color(0xFFE5E5E6);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,15 @@ class _OrderDetailsScreenState extends State<OrderDetailsScreen> {
|
|||
),
|
||||
|
||||
if (!_isFullScreen) ...[
|
||||
/// current location info
|
||||
if (_showLocation)
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: Space.all(1, 1),
|
||||
child: LocationCard(cargoId: widget.order.cargoId),
|
||||
),
|
||||
),
|
||||
|
||||
/// info text
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
|
|
@ -116,29 +125,6 @@ class _OrderDetailsScreenState extends State<OrderDetailsScreen> {
|
|||
|
||||
/// info card
|
||||
InfoCard(order: widget.order),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
/// current location info
|
||||
if (_showLocation)
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: Space.all(1, 1),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'route'.tr(),
|
||||
style: AppText.h2b,
|
||||
),
|
||||
|
||||
/// gap
|
||||
Space.y!,
|
||||
|
||||
/// location card
|
||||
LocationCard(cargoId: widget.order.cargoId),
|
||||
|
||||
/// gap
|
||||
Space.y!,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class CirclePainter extends CustomPainter {
|
||||
final double radius;
|
||||
final Color color;
|
||||
|
||||
CirclePainter({required this.radius, required this.color});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
// Create a paint object with the specified color
|
||||
final paint = Paint()
|
||||
..color = color
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
// Draw the circle in the center of the canvas
|
||||
canvas.drawCircle(
|
||||
Offset(size.width / 2, size.height / 2),
|
||||
radius,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class CirclePainterWidget extends StatelessWidget {
|
||||
final double radius;
|
||||
final Color color;
|
||||
|
||||
const CirclePainterWidget({super.key, required this.radius, required this.color});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomPaint(
|
||||
painter: CirclePainter(radius: radius, color: color),
|
||||
// Ensure the widget is large enough to fit the circle
|
||||
size: Size(radius * 2, radius * 2),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
import 'package:another_stepper/another_stepper.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
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 {
|
||||
|
|
@ -16,69 +17,43 @@ class LocationCard extends StatelessWidget {
|
|||
return BlocBuilder<OrderDetailBloc, OrderDetailState>(
|
||||
builder: (context, state) {
|
||||
if (state is RoutesLoading) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
return const SizedBox.shrink();
|
||||
// const Center(
|
||||
// child: CircularProgressIndicator(),
|
||||
// );
|
||||
} else if (state is RoutesLoaded) {
|
||||
final routes = state.routes;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'route'.tr(),
|
||||
style: AppText.h2b,
|
||||
),
|
||||
|
||||
return SizedBox(
|
||||
/// gap
|
||||
Space.y!,
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
final route = routes[index];
|
||||
return Row(
|
||||
children: [
|
||||
route.isCurrent
|
||||
? const Icon(
|
||||
Icons.radio_button_checked,
|
||||
color: AppColors.primary,
|
||||
)
|
||||
: Container(
|
||||
margin: Space.hf(0.35),
|
||||
height: AppDimensions.normalize(4.5),
|
||||
width: AppDimensions.normalize(4.5),
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColors.grey,
|
||||
shape: BoxShape.circle,
|
||||
child: AnotherStepper(
|
||||
stepperList: state.steppers,
|
||||
stepperDirection: Axis.vertical,
|
||||
iconWidth: 30,
|
||||
iconHeight: 30,
|
||||
activeBarColor: AppColors.greenDark,
|
||||
inActiveBarColor: AppColors.darkGrey,
|
||||
inverted: false,
|
||||
verticalGap: 25,
|
||||
activeIndex: state.activeIndex,
|
||||
barThickness: 2.6,
|
||||
),
|
||||
),
|
||||
Space.x!,
|
||||
Text(
|
||||
routes[index].name,
|
||||
style: AppText.h3b,
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
routes[index].dateAt,
|
||||
style: AppText.b1!.copyWith(color: AppColors.grey),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
itemCount: routes.length,
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Padding(
|
||||
padding: Space.vf(0.5),
|
||||
child: DashedLine(
|
||||
height: 1,
|
||||
width: AppDimensions.normalize(8),
|
||||
color: AppColors.lightGrey,
|
||||
strokeWidth: 1,
|
||||
dashWidth: 5,
|
||||
dashSpace: AppDimensions.normalize(2),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (state is RoutesError) {
|
||||
return Center(
|
||||
|
|
|
|||
|
|
@ -13,3 +13,4 @@ export 'successful_auth_dialog.dart';
|
|||
export 'vertical_line.dart';
|
||||
export 'images.dart';
|
||||
export 'empty_order.dart';
|
||||
export 'circle_painter.dart';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
another_stepper:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: another_stepper
|
||||
sha256: "04f5166c57f2412c612b17101e8a3d819f210c53f6bc1b5be541dc4c6987c681"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
ansicolor:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ dependencies:
|
|||
# cached_network_image: ^3.4.1
|
||||
flutter_native_splash: ^2.4.1
|
||||
url_launcher: ^6.3.0
|
||||
another_stepper: ^1.2.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in New Issue