diff --git a/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart new file mode 100644 index 0000000..d3e7383 --- /dev/null +++ b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart @@ -0,0 +1,50 @@ +import 'package:bloc/bloc.dart'; +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/analytic/analytic.dart'; +import '../../../domain/analytic/repositories/i_analytic_repository.dart'; + +part 'dashboard_analytic_loader_event.dart'; +part 'dashboard_analytic_loader_state.dart'; +part 'dashboard_analytic_loader_bloc.freezed.dart'; + +@injectable +class DashboardAnalyticLoaderBloc + extends Bloc { + final IAnalyticRepository _repository; + DashboardAnalyticLoaderBloc(this._repository) + : super(DashboardAnalyticLoaderState.initial()) { + on(_onDashboardAnalyticLoaderEvent); + } + + Future _onDashboardAnalyticLoaderEvent( + DashboardAnalyticLoaderEvent event, + Emitter emit, + ) { + return event.map( + fetched: (e) async { + emit( + state.copyWith( + isFetching: true, + failureOptionDashboardAnalytic: none(), + ), + ); + + final result = await _repository.getDashboard( + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionDashboardAnalytic: optionOf(f)), + (dashboardAnalytic) => + state.copyWith(dashboardAnalytic: dashboardAnalytic), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.freezed.dart b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.freezed.dart new file mode 100644 index 0000000..4976136 --- /dev/null +++ b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.freezed.dart @@ -0,0 +1,406 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'dashboard_analytic_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models', +); + +/// @nodoc +mixin _$DashboardAnalyticLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardAnalyticLoaderEventCopyWith<$Res> { + factory $DashboardAnalyticLoaderEventCopyWith( + DashboardAnalyticLoaderEvent value, + $Res Function(DashboardAnalyticLoaderEvent) then, + ) = + _$DashboardAnalyticLoaderEventCopyWithImpl< + $Res, + DashboardAnalyticLoaderEvent + >; +} + +/// @nodoc +class _$DashboardAnalyticLoaderEventCopyWithImpl< + $Res, + $Val extends DashboardAnalyticLoaderEvent +> + implements $DashboardAnalyticLoaderEventCopyWith<$Res> { + _$DashboardAnalyticLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$DashboardAnalyticLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'DashboardAnalyticLoaderEvent.fetched()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$FetchedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({required TResult Function() fetched}) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({TResult? Function()? fetched}) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements DashboardAnalyticLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$DashboardAnalyticLoaderState { + DashboardAnalytic get dashboardAnalytic => throw _privateConstructorUsedError; + Option get failureOptionDashboardAnalytic => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardAnalyticLoaderStateCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardAnalyticLoaderStateCopyWith<$Res> { + factory $DashboardAnalyticLoaderStateCopyWith( + DashboardAnalyticLoaderState value, + $Res Function(DashboardAnalyticLoaderState) then, + ) = + _$DashboardAnalyticLoaderStateCopyWithImpl< + $Res, + DashboardAnalyticLoaderState + >; + @useResult + $Res call({ + DashboardAnalytic dashboardAnalytic, + Option failureOptionDashboardAnalytic, + bool isFetching, + }); + + $DashboardAnalyticCopyWith<$Res> get dashboardAnalytic; +} + +/// @nodoc +class _$DashboardAnalyticLoaderStateCopyWithImpl< + $Res, + $Val extends DashboardAnalyticLoaderState +> + implements $DashboardAnalyticLoaderStateCopyWith<$Res> { + _$DashboardAnalyticLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? dashboardAnalytic = null, + Object? failureOptionDashboardAnalytic = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + dashboardAnalytic: null == dashboardAnalytic + ? _value.dashboardAnalytic + : dashboardAnalytic // ignore: cast_nullable_to_non_nullable + as DashboardAnalytic, + failureOptionDashboardAnalytic: + null == failureOptionDashboardAnalytic + ? _value.failureOptionDashboardAnalytic + : failureOptionDashboardAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $DashboardAnalyticCopyWith<$Res> get dashboardAnalytic { + return $DashboardAnalyticCopyWith<$Res>(_value.dashboardAnalytic, (value) { + return _then(_value.copyWith(dashboardAnalytic: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$DashboardAnalyticLoaderStateImplCopyWith<$Res> + implements $DashboardAnalyticLoaderStateCopyWith<$Res> { + factory _$$DashboardAnalyticLoaderStateImplCopyWith( + _$DashboardAnalyticLoaderStateImpl value, + $Res Function(_$DashboardAnalyticLoaderStateImpl) then, + ) = __$$DashboardAnalyticLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + DashboardAnalytic dashboardAnalytic, + Option failureOptionDashboardAnalytic, + bool isFetching, + }); + + @override + $DashboardAnalyticCopyWith<$Res> get dashboardAnalytic; +} + +/// @nodoc +class __$$DashboardAnalyticLoaderStateImplCopyWithImpl<$Res> + extends + _$DashboardAnalyticLoaderStateCopyWithImpl< + $Res, + _$DashboardAnalyticLoaderStateImpl + > + implements _$$DashboardAnalyticLoaderStateImplCopyWith<$Res> { + __$$DashboardAnalyticLoaderStateImplCopyWithImpl( + _$DashboardAnalyticLoaderStateImpl _value, + $Res Function(_$DashboardAnalyticLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? dashboardAnalytic = null, + Object? failureOptionDashboardAnalytic = null, + Object? isFetching = null, + }) { + return _then( + _$DashboardAnalyticLoaderStateImpl( + dashboardAnalytic: null == dashboardAnalytic + ? _value.dashboardAnalytic + : dashboardAnalytic // ignore: cast_nullable_to_non_nullable + as DashboardAnalytic, + failureOptionDashboardAnalytic: null == failureOptionDashboardAnalytic + ? _value.failureOptionDashboardAnalytic + : failureOptionDashboardAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$DashboardAnalyticLoaderStateImpl + implements _DashboardAnalyticLoaderState { + const _$DashboardAnalyticLoaderStateImpl({ + required this.dashboardAnalytic, + required this.failureOptionDashboardAnalytic, + this.isFetching = false, + }); + + @override + final DashboardAnalytic dashboardAnalytic; + @override + final Option failureOptionDashboardAnalytic; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'DashboardAnalyticLoaderState(dashboardAnalytic: $dashboardAnalytic, failureOptionDashboardAnalytic: $failureOptionDashboardAnalytic, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardAnalyticLoaderStateImpl && + (identical(other.dashboardAnalytic, dashboardAnalytic) || + other.dashboardAnalytic == dashboardAnalytic) && + (identical( + other.failureOptionDashboardAnalytic, + failureOptionDashboardAnalytic, + ) || + other.failureOptionDashboardAnalytic == + failureOptionDashboardAnalytic) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + dashboardAnalytic, + failureOptionDashboardAnalytic, + isFetching, + ); + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardAnalyticLoaderStateImplCopyWith< + _$DashboardAnalyticLoaderStateImpl + > + get copyWith => + __$$DashboardAnalyticLoaderStateImplCopyWithImpl< + _$DashboardAnalyticLoaderStateImpl + >(this, _$identity); +} + +abstract class _DashboardAnalyticLoaderState + implements DashboardAnalyticLoaderState { + const factory _DashboardAnalyticLoaderState({ + required final DashboardAnalytic dashboardAnalytic, + required final Option failureOptionDashboardAnalytic, + final bool isFetching, + }) = _$DashboardAnalyticLoaderStateImpl; + + @override + DashboardAnalytic get dashboardAnalytic; + @override + Option get failureOptionDashboardAnalytic; + @override + bool get isFetching; + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardAnalyticLoaderStateImplCopyWith< + _$DashboardAnalyticLoaderStateImpl + > + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_event.dart b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_event.dart new file mode 100644 index 0000000..4ac3dbd --- /dev/null +++ b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_event.dart @@ -0,0 +1,6 @@ +part of 'dashboard_analytic_loader_bloc.dart'; + +@freezed +class DashboardAnalyticLoaderEvent with _$DashboardAnalyticLoaderEvent { + const factory DashboardAnalyticLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_state.dart b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_state.dart new file mode 100644 index 0000000..07937ae --- /dev/null +++ b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_state.dart @@ -0,0 +1,16 @@ +part of 'dashboard_analytic_loader_bloc.dart'; + +@freezed +class DashboardAnalyticLoaderState with _$DashboardAnalyticLoaderState { + const factory DashboardAnalyticLoaderState({ + required DashboardAnalytic dashboardAnalytic, + required Option failureOptionDashboardAnalytic, + @Default(false) bool isFetching, + }) = _DashboardAnalyticLoaderState; + + factory DashboardAnalyticLoaderState.initial() => + DashboardAnalyticLoaderState( + dashboardAnalytic: DashboardAnalytic.empty(), + failureOptionDashboardAnalytic: none(), + ); +} diff --git a/lib/common/url/api_path.dart b/lib/common/url/api_path.dart index 1c2acee..9a84378 100644 --- a/lib/common/url/api_path.dart +++ b/lib/common/url/api_path.dart @@ -7,6 +7,7 @@ class ApiPath { static const String salesAnalytic = '/api/v1/analytics/sales'; static const String profitLossAnalytic = '/api/v1/analytics/profit-loss'; static const String categoryAnalytic = '/api/v1/analytics/categories'; + static const String dashboardAnalytic = '/api/v1/analytics/dashboard'; // Inventory static const String inventoryReportDetail = diff --git a/lib/domain/analytic/analytic.dart b/lib/domain/analytic/analytic.dart index 13925fe..7759997 100644 --- a/lib/domain/analytic/analytic.dart +++ b/lib/domain/analytic/analytic.dart @@ -8,4 +8,5 @@ part 'entities/sales_analytic_entity.dart'; part 'entities/profit_loss_analytic_entity.dart'; part 'entities/category_analytic_entity.dart'; part 'entities/inventory_analytic_entity.dart'; +part 'entities/dashboard_analytic_entity.dart'; part 'failures/analytic_failure.dart'; diff --git a/lib/domain/analytic/analytic.freezed.dart b/lib/domain/analytic/analytic.freezed.dart index 6e221e6..52f35a3 100644 --- a/lib/domain/analytic/analytic.freezed.dart +++ b/lib/domain/analytic/analytic.freezed.dart @@ -4245,6 +4245,1484 @@ abstract class _InventoryIngredient implements InventoryIngredient { throw _privateConstructorUsedError; } +/// @nodoc +mixin _$DashboardAnalytic { + String get organizationId => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get dateFrom => throw _privateConstructorUsedError; + String get dateTo => throw _privateConstructorUsedError; + DashboardOverview get overview => throw _privateConstructorUsedError; + List get topProducts => + throw _privateConstructorUsedError; + List get paymentMethods => + throw _privateConstructorUsedError; + List get recentSales => + throw _privateConstructorUsedError; + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardAnalyticCopyWith<$Res> { + factory $DashboardAnalyticCopyWith( + DashboardAnalytic value, + $Res Function(DashboardAnalytic) then, + ) = _$DashboardAnalyticCopyWithImpl<$Res, DashboardAnalytic>; + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + DashboardOverview overview, + List topProducts, + List paymentMethods, + List recentSales, + }); + + $DashboardOverviewCopyWith<$Res> get overview; +} + +/// @nodoc +class _$DashboardAnalyticCopyWithImpl<$Res, $Val extends DashboardAnalytic> + implements $DashboardAnalyticCopyWith<$Res> { + _$DashboardAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? overview = null, + Object? topProducts = null, + Object? paymentMethods = null, + Object? recentSales = null, + }) { + return _then( + _value.copyWith( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + overview: null == overview + ? _value.overview + : overview // ignore: cast_nullable_to_non_nullable + as DashboardOverview, + topProducts: null == topProducts + ? _value.topProducts + : topProducts // ignore: cast_nullable_to_non_nullable + as List, + paymentMethods: null == paymentMethods + ? _value.paymentMethods + : paymentMethods // ignore: cast_nullable_to_non_nullable + as List, + recentSales: null == recentSales + ? _value.recentSales + : recentSales // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $DashboardOverviewCopyWith<$Res> get overview { + return $DashboardOverviewCopyWith<$Res>(_value.overview, (value) { + return _then(_value.copyWith(overview: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$DashboardAnalyticImplCopyWith<$Res> + implements $DashboardAnalyticCopyWith<$Res> { + factory _$$DashboardAnalyticImplCopyWith( + _$DashboardAnalyticImpl value, + $Res Function(_$DashboardAnalyticImpl) then, + ) = __$$DashboardAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + DashboardOverview overview, + List topProducts, + List paymentMethods, + List recentSales, + }); + + @override + $DashboardOverviewCopyWith<$Res> get overview; +} + +/// @nodoc +class __$$DashboardAnalyticImplCopyWithImpl<$Res> + extends _$DashboardAnalyticCopyWithImpl<$Res, _$DashboardAnalyticImpl> + implements _$$DashboardAnalyticImplCopyWith<$Res> { + __$$DashboardAnalyticImplCopyWithImpl( + _$DashboardAnalyticImpl _value, + $Res Function(_$DashboardAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? overview = null, + Object? topProducts = null, + Object? paymentMethods = null, + Object? recentSales = null, + }) { + return _then( + _$DashboardAnalyticImpl( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + overview: null == overview + ? _value.overview + : overview // ignore: cast_nullable_to_non_nullable + as DashboardOverview, + topProducts: null == topProducts + ? _value._topProducts + : topProducts // ignore: cast_nullable_to_non_nullable + as List, + paymentMethods: null == paymentMethods + ? _value._paymentMethods + : paymentMethods // ignore: cast_nullable_to_non_nullable + as List, + recentSales: null == recentSales + ? _value._recentSales + : recentSales // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$DashboardAnalyticImpl implements _DashboardAnalytic { + const _$DashboardAnalyticImpl({ + required this.organizationId, + required this.outletId, + required this.dateFrom, + required this.dateTo, + required this.overview, + required final List topProducts, + required final List paymentMethods, + required final List recentSales, + }) : _topProducts = topProducts, + _paymentMethods = paymentMethods, + _recentSales = recentSales; + + @override + final String organizationId; + @override + final String outletId; + @override + final String dateFrom; + @override + final String dateTo; + @override + final DashboardOverview overview; + final List _topProducts; + @override + List get topProducts { + if (_topProducts is EqualUnmodifiableListView) return _topProducts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_topProducts); + } + + final List _paymentMethods; + @override + List get paymentMethods { + if (_paymentMethods is EqualUnmodifiableListView) return _paymentMethods; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_paymentMethods); + } + + final List _recentSales; + @override + List get recentSales { + if (_recentSales is EqualUnmodifiableListView) return _recentSales; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_recentSales); + } + + @override + String toString() { + return 'DashboardAnalytic(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, overview: $overview, topProducts: $topProducts, paymentMethods: $paymentMethods, recentSales: $recentSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardAnalyticImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.overview, overview) || + other.overview == overview) && + const DeepCollectionEquality().equals( + other._topProducts, + _topProducts, + ) && + const DeepCollectionEquality().equals( + other._paymentMethods, + _paymentMethods, + ) && + const DeepCollectionEquality().equals( + other._recentSales, + _recentSales, + )); + } + + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + overview, + const DeepCollectionEquality().hash(_topProducts), + const DeepCollectionEquality().hash(_paymentMethods), + const DeepCollectionEquality().hash(_recentSales), + ); + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardAnalyticImplCopyWith<_$DashboardAnalyticImpl> get copyWith => + __$$DashboardAnalyticImplCopyWithImpl<_$DashboardAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardAnalytic implements DashboardAnalytic { + const factory _DashboardAnalytic({ + required final String organizationId, + required final String outletId, + required final String dateFrom, + required final String dateTo, + required final DashboardOverview overview, + required final List topProducts, + required final List paymentMethods, + required final List recentSales, + }) = _$DashboardAnalyticImpl; + + @override + String get organizationId; + @override + String get outletId; + @override + String get dateFrom; + @override + String get dateTo; + @override + DashboardOverview get overview; + @override + List get topProducts; + @override + List get paymentMethods; + @override + List get recentSales; + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardAnalyticImplCopyWith<_$DashboardAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardOverview { + int get totalSales => throw _privateConstructorUsedError; + int get totalOrders => throw _privateConstructorUsedError; + double get averageOrderValue => throw _privateConstructorUsedError; + int get totalCustomers => throw _privateConstructorUsedError; + int get voidedOrders => throw _privateConstructorUsedError; + int get refundedOrders => throw _privateConstructorUsedError; + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardOverviewCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardOverviewCopyWith<$Res> { + factory $DashboardOverviewCopyWith( + DashboardOverview value, + $Res Function(DashboardOverview) then, + ) = _$DashboardOverviewCopyWithImpl<$Res, DashboardOverview>; + @useResult + $Res call({ + int totalSales, + int totalOrders, + double averageOrderValue, + int totalCustomers, + int voidedOrders, + int refundedOrders, + }); +} + +/// @nodoc +class _$DashboardOverviewCopyWithImpl<$Res, $Val extends DashboardOverview> + implements $DashboardOverviewCopyWith<$Res> { + _$DashboardOverviewCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = null, + Object? totalOrders = null, + Object? averageOrderValue = null, + Object? totalCustomers = null, + Object? voidedOrders = null, + Object? refundedOrders = null, + }) { + return _then( + _value.copyWith( + totalSales: null == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + averageOrderValue: null == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double, + totalCustomers: null == totalCustomers + ? _value.totalCustomers + : totalCustomers // ignore: cast_nullable_to_non_nullable + as int, + voidedOrders: null == voidedOrders + ? _value.voidedOrders + : voidedOrders // ignore: cast_nullable_to_non_nullable + as int, + refundedOrders: null == refundedOrders + ? _value.refundedOrders + : refundedOrders // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardOverviewImplCopyWith<$Res> + implements $DashboardOverviewCopyWith<$Res> { + factory _$$DashboardOverviewImplCopyWith( + _$DashboardOverviewImpl value, + $Res Function(_$DashboardOverviewImpl) then, + ) = __$$DashboardOverviewImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + int totalSales, + int totalOrders, + double averageOrderValue, + int totalCustomers, + int voidedOrders, + int refundedOrders, + }); +} + +/// @nodoc +class __$$DashboardOverviewImplCopyWithImpl<$Res> + extends _$DashboardOverviewCopyWithImpl<$Res, _$DashboardOverviewImpl> + implements _$$DashboardOverviewImplCopyWith<$Res> { + __$$DashboardOverviewImplCopyWithImpl( + _$DashboardOverviewImpl _value, + $Res Function(_$DashboardOverviewImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = null, + Object? totalOrders = null, + Object? averageOrderValue = null, + Object? totalCustomers = null, + Object? voidedOrders = null, + Object? refundedOrders = null, + }) { + return _then( + _$DashboardOverviewImpl( + totalSales: null == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + averageOrderValue: null == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double, + totalCustomers: null == totalCustomers + ? _value.totalCustomers + : totalCustomers // ignore: cast_nullable_to_non_nullable + as int, + voidedOrders: null == voidedOrders + ? _value.voidedOrders + : voidedOrders // ignore: cast_nullable_to_non_nullable + as int, + refundedOrders: null == refundedOrders + ? _value.refundedOrders + : refundedOrders // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$DashboardOverviewImpl implements _DashboardOverview { + const _$DashboardOverviewImpl({ + required this.totalSales, + required this.totalOrders, + required this.averageOrderValue, + required this.totalCustomers, + required this.voidedOrders, + required this.refundedOrders, + }); + + @override + final int totalSales; + @override + final int totalOrders; + @override + final double averageOrderValue; + @override + final int totalCustomers; + @override + final int voidedOrders; + @override + final int refundedOrders; + + @override + String toString() { + return 'DashboardOverview(totalSales: $totalSales, totalOrders: $totalOrders, averageOrderValue: $averageOrderValue, totalCustomers: $totalCustomers, voidedOrders: $voidedOrders, refundedOrders: $refundedOrders)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardOverviewImpl && + (identical(other.totalSales, totalSales) || + other.totalSales == totalSales) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.averageOrderValue, averageOrderValue) || + other.averageOrderValue == averageOrderValue) && + (identical(other.totalCustomers, totalCustomers) || + other.totalCustomers == totalCustomers) && + (identical(other.voidedOrders, voidedOrders) || + other.voidedOrders == voidedOrders) && + (identical(other.refundedOrders, refundedOrders) || + other.refundedOrders == refundedOrders)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + totalSales, + totalOrders, + averageOrderValue, + totalCustomers, + voidedOrders, + refundedOrders, + ); + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardOverviewImplCopyWith<_$DashboardOverviewImpl> get copyWith => + __$$DashboardOverviewImplCopyWithImpl<_$DashboardOverviewImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardOverview implements DashboardOverview { + const factory _DashboardOverview({ + required final int totalSales, + required final int totalOrders, + required final double averageOrderValue, + required final int totalCustomers, + required final int voidedOrders, + required final int refundedOrders, + }) = _$DashboardOverviewImpl; + + @override + int get totalSales; + @override + int get totalOrders; + @override + double get averageOrderValue; + @override + int get totalCustomers; + @override + int get voidedOrders; + @override + int get refundedOrders; + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardOverviewImplCopyWith<_$DashboardOverviewImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardTopProduct { + String get productId => throw _privateConstructorUsedError; + String get productName => throw _privateConstructorUsedError; + String get categoryId => throw _privateConstructorUsedError; + String get categoryName => throw _privateConstructorUsedError; + int get quantitySold => throw _privateConstructorUsedError; + int get revenue => throw _privateConstructorUsedError; + double get averagePrice => throw _privateConstructorUsedError; + int get orderCount => throw _privateConstructorUsedError; + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardTopProductCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardTopProductCopyWith<$Res> { + factory $DashboardTopProductCopyWith( + DashboardTopProduct value, + $Res Function(DashboardTopProduct) then, + ) = _$DashboardTopProductCopyWithImpl<$Res, DashboardTopProduct>; + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + double averagePrice, + int orderCount, + }); +} + +/// @nodoc +class _$DashboardTopProductCopyWithImpl<$Res, $Val extends DashboardTopProduct> + implements $DashboardTopProductCopyWith<$Res> { + _$DashboardTopProductCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? averagePrice = null, + Object? orderCount = null, + }) { + return _then( + _value.copyWith( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardTopProductImplCopyWith<$Res> + implements $DashboardTopProductCopyWith<$Res> { + factory _$$DashboardTopProductImplCopyWith( + _$DashboardTopProductImpl value, + $Res Function(_$DashboardTopProductImpl) then, + ) = __$$DashboardTopProductImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + double averagePrice, + int orderCount, + }); +} + +/// @nodoc +class __$$DashboardTopProductImplCopyWithImpl<$Res> + extends _$DashboardTopProductCopyWithImpl<$Res, _$DashboardTopProductImpl> + implements _$$DashboardTopProductImplCopyWith<$Res> { + __$$DashboardTopProductImplCopyWithImpl( + _$DashboardTopProductImpl _value, + $Res Function(_$DashboardTopProductImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? averagePrice = null, + Object? orderCount = null, + }) { + return _then( + _$DashboardTopProductImpl( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$DashboardTopProductImpl implements _DashboardTopProduct { + const _$DashboardTopProductImpl({ + required this.productId, + required this.productName, + required this.categoryId, + required this.categoryName, + required this.quantitySold, + required this.revenue, + required this.averagePrice, + required this.orderCount, + }); + + @override + final String productId; + @override + final String productName; + @override + final String categoryId; + @override + final String categoryName; + @override + final int quantitySold; + @override + final int revenue; + @override + final double averagePrice; + @override + final int orderCount; + + @override + String toString() { + return 'DashboardTopProduct(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, averagePrice: $averagePrice, orderCount: $orderCount)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardTopProductImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + averagePrice, + orderCount, + ); + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardTopProductImplCopyWith<_$DashboardTopProductImpl> get copyWith => + __$$DashboardTopProductImplCopyWithImpl<_$DashboardTopProductImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardTopProduct implements DashboardTopProduct { + const factory _DashboardTopProduct({ + required final String productId, + required final String productName, + required final String categoryId, + required final String categoryName, + required final int quantitySold, + required final int revenue, + required final double averagePrice, + required final int orderCount, + }) = _$DashboardTopProductImpl; + + @override + String get productId; + @override + String get productName; + @override + String get categoryId; + @override + String get categoryName; + @override + int get quantitySold; + @override + int get revenue; + @override + double get averagePrice; + @override + int get orderCount; + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardTopProductImplCopyWith<_$DashboardTopProductImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardPaymentMethod { + String get paymentMethodId => throw _privateConstructorUsedError; + String get paymentMethodName => throw _privateConstructorUsedError; + String get paymentMethodType => throw _privateConstructorUsedError; + int get totalAmount => throw _privateConstructorUsedError; + int get orderCount => throw _privateConstructorUsedError; + int get paymentCount => throw _privateConstructorUsedError; + double get percentage => throw _privateConstructorUsedError; + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardPaymentMethodCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardPaymentMethodCopyWith<$Res> { + factory $DashboardPaymentMethodCopyWith( + DashboardPaymentMethod value, + $Res Function(DashboardPaymentMethod) then, + ) = _$DashboardPaymentMethodCopyWithImpl<$Res, DashboardPaymentMethod>; + @useResult + $Res call({ + String paymentMethodId, + String paymentMethodName, + String paymentMethodType, + int totalAmount, + int orderCount, + int paymentCount, + double percentage, + }); +} + +/// @nodoc +class _$DashboardPaymentMethodCopyWithImpl< + $Res, + $Val extends DashboardPaymentMethod +> + implements $DashboardPaymentMethodCopyWith<$Res> { + _$DashboardPaymentMethodCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = null, + Object? paymentMethodName = null, + Object? paymentMethodType = null, + Object? totalAmount = null, + Object? orderCount = null, + Object? paymentCount = null, + Object? percentage = null, + }) { + return _then( + _value.copyWith( + paymentMethodId: null == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodName: null == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodType: null == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String, + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + paymentCount: null == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int, + percentage: null == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardPaymentMethodImplCopyWith<$Res> + implements $DashboardPaymentMethodCopyWith<$Res> { + factory _$$DashboardPaymentMethodImplCopyWith( + _$DashboardPaymentMethodImpl value, + $Res Function(_$DashboardPaymentMethodImpl) then, + ) = __$$DashboardPaymentMethodImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String paymentMethodId, + String paymentMethodName, + String paymentMethodType, + int totalAmount, + int orderCount, + int paymentCount, + double percentage, + }); +} + +/// @nodoc +class __$$DashboardPaymentMethodImplCopyWithImpl<$Res> + extends + _$DashboardPaymentMethodCopyWithImpl<$Res, _$DashboardPaymentMethodImpl> + implements _$$DashboardPaymentMethodImplCopyWith<$Res> { + __$$DashboardPaymentMethodImplCopyWithImpl( + _$DashboardPaymentMethodImpl _value, + $Res Function(_$DashboardPaymentMethodImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = null, + Object? paymentMethodName = null, + Object? paymentMethodType = null, + Object? totalAmount = null, + Object? orderCount = null, + Object? paymentCount = null, + Object? percentage = null, + }) { + return _then( + _$DashboardPaymentMethodImpl( + paymentMethodId: null == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodName: null == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodType: null == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String, + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + paymentCount: null == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int, + percentage: null == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double, + ), + ); + } +} + +/// @nodoc + +class _$DashboardPaymentMethodImpl implements _DashboardPaymentMethod { + const _$DashboardPaymentMethodImpl({ + required this.paymentMethodId, + required this.paymentMethodName, + required this.paymentMethodType, + required this.totalAmount, + required this.orderCount, + required this.paymentCount, + required this.percentage, + }); + + @override + final String paymentMethodId; + @override + final String paymentMethodName; + @override + final String paymentMethodType; + @override + final int totalAmount; + @override + final int orderCount; + @override + final int paymentCount; + @override + final double percentage; + + @override + String toString() { + return 'DashboardPaymentMethod(paymentMethodId: $paymentMethodId, paymentMethodName: $paymentMethodName, paymentMethodType: $paymentMethodType, totalAmount: $totalAmount, orderCount: $orderCount, paymentCount: $paymentCount, percentage: $percentage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardPaymentMethodImpl && + (identical(other.paymentMethodId, paymentMethodId) || + other.paymentMethodId == paymentMethodId) && + (identical(other.paymentMethodName, paymentMethodName) || + other.paymentMethodName == paymentMethodName) && + (identical(other.paymentMethodType, paymentMethodType) || + other.paymentMethodType == paymentMethodType) && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount) && + (identical(other.paymentCount, paymentCount) || + other.paymentCount == paymentCount) && + (identical(other.percentage, percentage) || + other.percentage == percentage)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + paymentMethodId, + paymentMethodName, + paymentMethodType, + totalAmount, + orderCount, + paymentCount, + percentage, + ); + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardPaymentMethodImplCopyWith<_$DashboardPaymentMethodImpl> + get copyWith => + __$$DashboardPaymentMethodImplCopyWithImpl<_$DashboardPaymentMethodImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardPaymentMethod implements DashboardPaymentMethod { + const factory _DashboardPaymentMethod({ + required final String paymentMethodId, + required final String paymentMethodName, + required final String paymentMethodType, + required final int totalAmount, + required final int orderCount, + required final int paymentCount, + required final double percentage, + }) = _$DashboardPaymentMethodImpl; + + @override + String get paymentMethodId; + @override + String get paymentMethodName; + @override + String get paymentMethodType; + @override + int get totalAmount; + @override + int get orderCount; + @override + int get paymentCount; + @override + double get percentage; + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardPaymentMethodImplCopyWith<_$DashboardPaymentMethodImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardRecentSale { + String get date => throw _privateConstructorUsedError; + int get sales => throw _privateConstructorUsedError; + int get orders => throw _privateConstructorUsedError; + int get items => throw _privateConstructorUsedError; + int get tax => throw _privateConstructorUsedError; + int get discount => throw _privateConstructorUsedError; + int get netSales => throw _privateConstructorUsedError; + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardRecentSaleCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardRecentSaleCopyWith<$Res> { + factory $DashboardRecentSaleCopyWith( + DashboardRecentSale value, + $Res Function(DashboardRecentSale) then, + ) = _$DashboardRecentSaleCopyWithImpl<$Res, DashboardRecentSale>; + @useResult + $Res call({ + String date, + int sales, + int orders, + int items, + int tax, + int discount, + int netSales, + }); +} + +/// @nodoc +class _$DashboardRecentSaleCopyWithImpl<$Res, $Val extends DashboardRecentSale> + implements $DashboardRecentSaleCopyWith<$Res> { + _$DashboardRecentSaleCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? sales = null, + Object? orders = null, + Object? items = null, + Object? tax = null, + Object? discount = null, + Object? netSales = null, + }) { + return _then( + _value.copyWith( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String, + sales: null == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + items: null == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netSales: null == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardRecentSaleImplCopyWith<$Res> + implements $DashboardRecentSaleCopyWith<$Res> { + factory _$$DashboardRecentSaleImplCopyWith( + _$DashboardRecentSaleImpl value, + $Res Function(_$DashboardRecentSaleImpl) then, + ) = __$$DashboardRecentSaleImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String date, + int sales, + int orders, + int items, + int tax, + int discount, + int netSales, + }); +} + +/// @nodoc +class __$$DashboardRecentSaleImplCopyWithImpl<$Res> + extends _$DashboardRecentSaleCopyWithImpl<$Res, _$DashboardRecentSaleImpl> + implements _$$DashboardRecentSaleImplCopyWith<$Res> { + __$$DashboardRecentSaleImplCopyWithImpl( + _$DashboardRecentSaleImpl _value, + $Res Function(_$DashboardRecentSaleImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? sales = null, + Object? orders = null, + Object? items = null, + Object? tax = null, + Object? discount = null, + Object? netSales = null, + }) { + return _then( + _$DashboardRecentSaleImpl( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String, + sales: null == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + items: null == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netSales: null == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$DashboardRecentSaleImpl implements _DashboardRecentSale { + const _$DashboardRecentSaleImpl({ + required this.date, + required this.sales, + required this.orders, + required this.items, + required this.tax, + required this.discount, + required this.netSales, + }); + + @override + final String date; + @override + final int sales; + @override + final int orders; + @override + final int items; + @override + final int tax; + @override + final int discount; + @override + final int netSales; + + @override + String toString() { + return 'DashboardRecentSale(date: $date, sales: $sales, orders: $orders, items: $items, tax: $tax, discount: $discount, netSales: $netSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardRecentSaleImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.sales, sales) || other.sales == sales) && + (identical(other.orders, orders) || other.orders == orders) && + (identical(other.items, items) || other.items == items) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netSales, netSales) || + other.netSales == netSales)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + date, + sales, + orders, + items, + tax, + discount, + netSales, + ); + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardRecentSaleImplCopyWith<_$DashboardRecentSaleImpl> get copyWith => + __$$DashboardRecentSaleImplCopyWithImpl<_$DashboardRecentSaleImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardRecentSale implements DashboardRecentSale { + const factory _DashboardRecentSale({ + required final String date, + required final int sales, + required final int orders, + required final int items, + required final int tax, + required final int discount, + required final int netSales, + }) = _$DashboardRecentSaleImpl; + + @override + String get date; + @override + int get sales; + @override + int get orders; + @override + int get items; + @override + int get tax; + @override + int get discount; + @override + int get netSales; + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardRecentSaleImplCopyWith<_$DashboardRecentSaleImpl> get copyWith => + throw _privateConstructorUsedError; +} + /// @nodoc mixin _$AnalyticFailure { @optionalTypeArgs diff --git a/lib/domain/analytic/entities/dashboard_analytic_entity.dart b/lib/domain/analytic/entities/dashboard_analytic_entity.dart new file mode 100644 index 0000000..204c85b --- /dev/null +++ b/lib/domain/analytic/entities/dashboard_analytic_entity.dart @@ -0,0 +1,118 @@ +part of '../analytic.dart'; + +@freezed +class DashboardAnalytic with _$DashboardAnalytic { + const factory DashboardAnalytic({ + required String organizationId, + required String outletId, + required String dateFrom, + required String dateTo, + required DashboardOverview overview, + required List topProducts, + required List paymentMethods, + required List recentSales, + }) = _DashboardAnalytic; + + factory DashboardAnalytic.empty() => DashboardAnalytic( + organizationId: '', + outletId: '', + dateFrom: '', + dateTo: '', + overview: DashboardOverview.empty(), + topProducts: const [], + paymentMethods: const [], + recentSales: const [], + ); +} + +@freezed +class DashboardOverview with _$DashboardOverview { + const factory DashboardOverview({ + required int totalSales, + required int totalOrders, + required double averageOrderValue, + required int totalCustomers, + required int voidedOrders, + required int refundedOrders, + }) = _DashboardOverview; + + factory DashboardOverview.empty() => const DashboardOverview( + totalSales: 0, + totalOrders: 0, + averageOrderValue: 0.0, + totalCustomers: 0, + voidedOrders: 0, + refundedOrders: 0, + ); +} + +@freezed +class DashboardTopProduct with _$DashboardTopProduct { + const factory DashboardTopProduct({ + required String productId, + required String productName, + required String categoryId, + required String categoryName, + required int quantitySold, + required int revenue, + required double averagePrice, + required int orderCount, + }) = _DashboardTopProduct; + + factory DashboardTopProduct.empty() => const DashboardTopProduct( + productId: '', + productName: '', + categoryId: '', + categoryName: '', + quantitySold: 0, + revenue: 0, + averagePrice: 0.0, + orderCount: 0, + ); +} + +@freezed +class DashboardPaymentMethod with _$DashboardPaymentMethod { + const factory DashboardPaymentMethod({ + required String paymentMethodId, + required String paymentMethodName, + required String paymentMethodType, + required int totalAmount, + required int orderCount, + required int paymentCount, + required double percentage, + }) = _DashboardPaymentMethod; + + factory DashboardPaymentMethod.empty() => const DashboardPaymentMethod( + paymentMethodId: '', + paymentMethodName: '', + paymentMethodType: '', + totalAmount: 0, + orderCount: 0, + paymentCount: 0, + percentage: 0.0, + ); +} + +@freezed +class DashboardRecentSale with _$DashboardRecentSale { + const factory DashboardRecentSale({ + required String date, + required int sales, + required int orders, + required int items, + required int tax, + required int discount, + required int netSales, + }) = _DashboardRecentSale; + + factory DashboardRecentSale.empty() => const DashboardRecentSale( + date: '', + sales: 0, + orders: 0, + items: 0, + tax: 0, + discount: 0, + netSales: 0, + ); +} diff --git a/lib/domain/analytic/repositories/i_analytic_repository.dart b/lib/domain/analytic/repositories/i_analytic_repository.dart index fb45141..50a1a90 100644 --- a/lib/domain/analytic/repositories/i_analytic_repository.dart +++ b/lib/domain/analytic/repositories/i_analytic_repository.dart @@ -22,4 +22,9 @@ abstract class IAnalyticRepository { required DateTime dateFrom, required DateTime dateTo, }); + + Future> getDashboard({ + required DateTime dateFrom, + required DateTime dateTo, + }); } diff --git a/lib/infrastructure/analytic/analytic_dtos.dart b/lib/infrastructure/analytic/analytic_dtos.dart index 35e7062..a604c55 100644 --- a/lib/infrastructure/analytic/analytic_dtos.dart +++ b/lib/infrastructure/analytic/analytic_dtos.dart @@ -9,3 +9,4 @@ part 'dto/sales_analytic_dto.dart'; part 'dto/profit_loss_analytic_dto.dart'; part 'dto/category_analytic_dto.dart'; part 'dto/inventory_analytic_dto.dart'; +part 'dto/dashboard_analytic_dto.dart'; diff --git a/lib/infrastructure/analytic/analytic_dtos.freezed.dart b/lib/infrastructure/analytic/analytic_dtos.freezed.dart index d51b773..2f5bbd5 100644 --- a/lib/infrastructure/analytic/analytic_dtos.freezed.dart +++ b/lib/infrastructure/analytic/analytic_dtos.freezed.dart @@ -4922,3 +4922,1734 @@ abstract class _InventoryIngredientDto implements InventoryIngredientDto { _$$InventoryIngredientDtoImplCopyWith<_$InventoryIngredientDtoImpl> get copyWith => throw _privateConstructorUsedError; } + +DashboardAnalyticDto _$DashboardAnalyticDtoFromJson(Map json) { + return _DashboardAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardAnalyticDto { + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'outlet_id') + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: 'date_from') + String? get dateFrom => throw _privateConstructorUsedError; + @JsonKey(name: 'date_to') + String? get dateTo => throw _privateConstructorUsedError; + @JsonKey(name: 'overview') + DashboardOverviewDto? get overview => throw _privateConstructorUsedError; + @JsonKey(name: 'top_products') + List? get topProducts => + throw _privateConstructorUsedError; + @JsonKey(name: 'payment_methods') + List? get paymentMethods => + throw _privateConstructorUsedError; + @JsonKey(name: 'recent_sales') + List? get recentSales => + throw _privateConstructorUsedError; + + /// Serializes this DashboardAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardAnalyticDtoCopyWith<$Res> { + factory $DashboardAnalyticDtoCopyWith( + DashboardAnalyticDto value, + $Res Function(DashboardAnalyticDto) then, + ) = _$DashboardAnalyticDtoCopyWithImpl<$Res, DashboardAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'overview') DashboardOverviewDto? overview, + @JsonKey(name: 'top_products') List? topProducts, + @JsonKey(name: 'payment_methods') + List? paymentMethods, + @JsonKey(name: 'recent_sales') List? recentSales, + }); + + $DashboardOverviewDtoCopyWith<$Res>? get overview; +} + +/// @nodoc +class _$DashboardAnalyticDtoCopyWithImpl< + $Res, + $Val extends DashboardAnalyticDto +> + implements $DashboardAnalyticDtoCopyWith<$Res> { + _$DashboardAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? overview = freezed, + Object? topProducts = freezed, + Object? paymentMethods = freezed, + Object? recentSales = freezed, + }) { + return _then( + _value.copyWith( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + overview: freezed == overview + ? _value.overview + : overview // ignore: cast_nullable_to_non_nullable + as DashboardOverviewDto?, + topProducts: freezed == topProducts + ? _value.topProducts + : topProducts // ignore: cast_nullable_to_non_nullable + as List?, + paymentMethods: freezed == paymentMethods + ? _value.paymentMethods + : paymentMethods // ignore: cast_nullable_to_non_nullable + as List?, + recentSales: freezed == recentSales + ? _value.recentSales + : recentSales // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $DashboardOverviewDtoCopyWith<$Res>? get overview { + if (_value.overview == null) { + return null; + } + + return $DashboardOverviewDtoCopyWith<$Res>(_value.overview!, (value) { + return _then(_value.copyWith(overview: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$DashboardAnalyticDtoImplCopyWith<$Res> + implements $DashboardAnalyticDtoCopyWith<$Res> { + factory _$$DashboardAnalyticDtoImplCopyWith( + _$DashboardAnalyticDtoImpl value, + $Res Function(_$DashboardAnalyticDtoImpl) then, + ) = __$$DashboardAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'overview') DashboardOverviewDto? overview, + @JsonKey(name: 'top_products') List? topProducts, + @JsonKey(name: 'payment_methods') + List? paymentMethods, + @JsonKey(name: 'recent_sales') List? recentSales, + }); + + @override + $DashboardOverviewDtoCopyWith<$Res>? get overview; +} + +/// @nodoc +class __$$DashboardAnalyticDtoImplCopyWithImpl<$Res> + extends _$DashboardAnalyticDtoCopyWithImpl<$Res, _$DashboardAnalyticDtoImpl> + implements _$$DashboardAnalyticDtoImplCopyWith<$Res> { + __$$DashboardAnalyticDtoImplCopyWithImpl( + _$DashboardAnalyticDtoImpl _value, + $Res Function(_$DashboardAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? overview = freezed, + Object? topProducts = freezed, + Object? paymentMethods = freezed, + Object? recentSales = freezed, + }) { + return _then( + _$DashboardAnalyticDtoImpl( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + overview: freezed == overview + ? _value.overview + : overview // ignore: cast_nullable_to_non_nullable + as DashboardOverviewDto?, + topProducts: freezed == topProducts + ? _value._topProducts + : topProducts // ignore: cast_nullable_to_non_nullable + as List?, + paymentMethods: freezed == paymentMethods + ? _value._paymentMethods + : paymentMethods // ignore: cast_nullable_to_non_nullable + as List?, + recentSales: freezed == recentSales + ? _value._recentSales + : recentSales // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardAnalyticDtoImpl extends _DashboardAnalyticDto { + const _$DashboardAnalyticDtoImpl({ + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'outlet_id') this.outletId, + @JsonKey(name: 'date_from') this.dateFrom, + @JsonKey(name: 'date_to') this.dateTo, + @JsonKey(name: 'overview') this.overview, + @JsonKey(name: 'top_products') + final List? topProducts, + @JsonKey(name: 'payment_methods') + final List? paymentMethods, + @JsonKey(name: 'recent_sales') + final List? recentSales, + }) : _topProducts = topProducts, + _paymentMethods = paymentMethods, + _recentSales = recentSales, + super._(); + + factory _$DashboardAnalyticDtoImpl.fromJson(Map json) => + _$$DashboardAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'outlet_id') + final String? outletId; + @override + @JsonKey(name: 'date_from') + final String? dateFrom; + @override + @JsonKey(name: 'date_to') + final String? dateTo; + @override + @JsonKey(name: 'overview') + final DashboardOverviewDto? overview; + final List? _topProducts; + @override + @JsonKey(name: 'top_products') + List? get topProducts { + final value = _topProducts; + if (value == null) return null; + if (_topProducts is EqualUnmodifiableListView) return _topProducts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _paymentMethods; + @override + @JsonKey(name: 'payment_methods') + List? get paymentMethods { + final value = _paymentMethods; + if (value == null) return null; + if (_paymentMethods is EqualUnmodifiableListView) return _paymentMethods; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _recentSales; + @override + @JsonKey(name: 'recent_sales') + List? get recentSales { + final value = _recentSales; + if (value == null) return null; + if (_recentSales is EqualUnmodifiableListView) return _recentSales; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'DashboardAnalyticDto(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, overview: $overview, topProducts: $topProducts, paymentMethods: $paymentMethods, recentSales: $recentSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardAnalyticDtoImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.overview, overview) || + other.overview == overview) && + const DeepCollectionEquality().equals( + other._topProducts, + _topProducts, + ) && + const DeepCollectionEquality().equals( + other._paymentMethods, + _paymentMethods, + ) && + const DeepCollectionEquality().equals( + other._recentSales, + _recentSales, + )); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + overview, + const DeepCollectionEquality().hash(_topProducts), + const DeepCollectionEquality().hash(_paymentMethods), + const DeepCollectionEquality().hash(_recentSales), + ); + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardAnalyticDtoImplCopyWith<_$DashboardAnalyticDtoImpl> + get copyWith => + __$$DashboardAnalyticDtoImplCopyWithImpl<_$DashboardAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$DashboardAnalyticDtoImplToJson(this); + } +} + +abstract class _DashboardAnalyticDto extends DashboardAnalyticDto { + const factory _DashboardAnalyticDto({ + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'outlet_id') final String? outletId, + @JsonKey(name: 'date_from') final String? dateFrom, + @JsonKey(name: 'date_to') final String? dateTo, + @JsonKey(name: 'overview') final DashboardOverviewDto? overview, + @JsonKey(name: 'top_products') + final List? topProducts, + @JsonKey(name: 'payment_methods') + final List? paymentMethods, + @JsonKey(name: 'recent_sales') + final List? recentSales, + }) = _$DashboardAnalyticDtoImpl; + const _DashboardAnalyticDto._() : super._(); + + factory _DashboardAnalyticDto.fromJson(Map json) = + _$DashboardAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'outlet_id') + String? get outletId; + @override + @JsonKey(name: 'date_from') + String? get dateFrom; + @override + @JsonKey(name: 'date_to') + String? get dateTo; + @override + @JsonKey(name: 'overview') + DashboardOverviewDto? get overview; + @override + @JsonKey(name: 'top_products') + List? get topProducts; + @override + @JsonKey(name: 'payment_methods') + List? get paymentMethods; + @override + @JsonKey(name: 'recent_sales') + List? get recentSales; + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardAnalyticDtoImplCopyWith<_$DashboardAnalyticDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardOverviewDto _$DashboardOverviewDtoFromJson(Map json) { + return _DashboardOverviewDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardOverviewDto { + @JsonKey(name: 'total_sales') + int? get totalSales => throw _privateConstructorUsedError; + @JsonKey(name: 'total_orders') + int? get totalOrders => throw _privateConstructorUsedError; + @JsonKey(name: 'average_order_value') + double? get averageOrderValue => throw _privateConstructorUsedError; + @JsonKey(name: 'total_customers') + int? get totalCustomers => throw _privateConstructorUsedError; + @JsonKey(name: 'voided_orders') + int? get voidedOrders => throw _privateConstructorUsedError; + @JsonKey(name: 'refunded_orders') + int? get refundedOrders => throw _privateConstructorUsedError; + + /// Serializes this DashboardOverviewDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardOverviewDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardOverviewDtoCopyWith<$Res> { + factory $DashboardOverviewDtoCopyWith( + DashboardOverviewDto value, + $Res Function(DashboardOverviewDto) then, + ) = _$DashboardOverviewDtoCopyWithImpl<$Res, DashboardOverviewDto>; + @useResult + $Res call({ + @JsonKey(name: 'total_sales') int? totalSales, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + @JsonKey(name: 'total_customers') int? totalCustomers, + @JsonKey(name: 'voided_orders') int? voidedOrders, + @JsonKey(name: 'refunded_orders') int? refundedOrders, + }); +} + +/// @nodoc +class _$DashboardOverviewDtoCopyWithImpl< + $Res, + $Val extends DashboardOverviewDto +> + implements $DashboardOverviewDtoCopyWith<$Res> { + _$DashboardOverviewDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = freezed, + Object? totalOrders = freezed, + Object? averageOrderValue = freezed, + Object? totalCustomers = freezed, + Object? voidedOrders = freezed, + Object? refundedOrders = freezed, + }) { + return _then( + _value.copyWith( + totalSales: freezed == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + averageOrderValue: freezed == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double?, + totalCustomers: freezed == totalCustomers + ? _value.totalCustomers + : totalCustomers // ignore: cast_nullable_to_non_nullable + as int?, + voidedOrders: freezed == voidedOrders + ? _value.voidedOrders + : voidedOrders // ignore: cast_nullable_to_non_nullable + as int?, + refundedOrders: freezed == refundedOrders + ? _value.refundedOrders + : refundedOrders // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardOverviewDtoImplCopyWith<$Res> + implements $DashboardOverviewDtoCopyWith<$Res> { + factory _$$DashboardOverviewDtoImplCopyWith( + _$DashboardOverviewDtoImpl value, + $Res Function(_$DashboardOverviewDtoImpl) then, + ) = __$$DashboardOverviewDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'total_sales') int? totalSales, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + @JsonKey(name: 'total_customers') int? totalCustomers, + @JsonKey(name: 'voided_orders') int? voidedOrders, + @JsonKey(name: 'refunded_orders') int? refundedOrders, + }); +} + +/// @nodoc +class __$$DashboardOverviewDtoImplCopyWithImpl<$Res> + extends _$DashboardOverviewDtoCopyWithImpl<$Res, _$DashboardOverviewDtoImpl> + implements _$$DashboardOverviewDtoImplCopyWith<$Res> { + __$$DashboardOverviewDtoImplCopyWithImpl( + _$DashboardOverviewDtoImpl _value, + $Res Function(_$DashboardOverviewDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = freezed, + Object? totalOrders = freezed, + Object? averageOrderValue = freezed, + Object? totalCustomers = freezed, + Object? voidedOrders = freezed, + Object? refundedOrders = freezed, + }) { + return _then( + _$DashboardOverviewDtoImpl( + totalSales: freezed == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + averageOrderValue: freezed == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double?, + totalCustomers: freezed == totalCustomers + ? _value.totalCustomers + : totalCustomers // ignore: cast_nullable_to_non_nullable + as int?, + voidedOrders: freezed == voidedOrders + ? _value.voidedOrders + : voidedOrders // ignore: cast_nullable_to_non_nullable + as int?, + refundedOrders: freezed == refundedOrders + ? _value.refundedOrders + : refundedOrders // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardOverviewDtoImpl extends _DashboardOverviewDto { + const _$DashboardOverviewDtoImpl({ + @JsonKey(name: 'total_sales') this.totalSales, + @JsonKey(name: 'total_orders') this.totalOrders, + @JsonKey(name: 'average_order_value') this.averageOrderValue, + @JsonKey(name: 'total_customers') this.totalCustomers, + @JsonKey(name: 'voided_orders') this.voidedOrders, + @JsonKey(name: 'refunded_orders') this.refundedOrders, + }) : super._(); + + factory _$DashboardOverviewDtoImpl.fromJson(Map json) => + _$$DashboardOverviewDtoImplFromJson(json); + + @override + @JsonKey(name: 'total_sales') + final int? totalSales; + @override + @JsonKey(name: 'total_orders') + final int? totalOrders; + @override + @JsonKey(name: 'average_order_value') + final double? averageOrderValue; + @override + @JsonKey(name: 'total_customers') + final int? totalCustomers; + @override + @JsonKey(name: 'voided_orders') + final int? voidedOrders; + @override + @JsonKey(name: 'refunded_orders') + final int? refundedOrders; + + @override + String toString() { + return 'DashboardOverviewDto(totalSales: $totalSales, totalOrders: $totalOrders, averageOrderValue: $averageOrderValue, totalCustomers: $totalCustomers, voidedOrders: $voidedOrders, refundedOrders: $refundedOrders)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardOverviewDtoImpl && + (identical(other.totalSales, totalSales) || + other.totalSales == totalSales) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.averageOrderValue, averageOrderValue) || + other.averageOrderValue == averageOrderValue) && + (identical(other.totalCustomers, totalCustomers) || + other.totalCustomers == totalCustomers) && + (identical(other.voidedOrders, voidedOrders) || + other.voidedOrders == voidedOrders) && + (identical(other.refundedOrders, refundedOrders) || + other.refundedOrders == refundedOrders)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + totalSales, + totalOrders, + averageOrderValue, + totalCustomers, + voidedOrders, + refundedOrders, + ); + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardOverviewDtoImplCopyWith<_$DashboardOverviewDtoImpl> + get copyWith => + __$$DashboardOverviewDtoImplCopyWithImpl<_$DashboardOverviewDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$DashboardOverviewDtoImplToJson(this); + } +} + +abstract class _DashboardOverviewDto extends DashboardOverviewDto { + const factory _DashboardOverviewDto({ + @JsonKey(name: 'total_sales') final int? totalSales, + @JsonKey(name: 'total_orders') final int? totalOrders, + @JsonKey(name: 'average_order_value') final double? averageOrderValue, + @JsonKey(name: 'total_customers') final int? totalCustomers, + @JsonKey(name: 'voided_orders') final int? voidedOrders, + @JsonKey(name: 'refunded_orders') final int? refundedOrders, + }) = _$DashboardOverviewDtoImpl; + const _DashboardOverviewDto._() : super._(); + + factory _DashboardOverviewDto.fromJson(Map json) = + _$DashboardOverviewDtoImpl.fromJson; + + @override + @JsonKey(name: 'total_sales') + int? get totalSales; + @override + @JsonKey(name: 'total_orders') + int? get totalOrders; + @override + @JsonKey(name: 'average_order_value') + double? get averageOrderValue; + @override + @JsonKey(name: 'total_customers') + int? get totalCustomers; + @override + @JsonKey(name: 'voided_orders') + int? get voidedOrders; + @override + @JsonKey(name: 'refunded_orders') + int? get refundedOrders; + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardOverviewDtoImplCopyWith<_$DashboardOverviewDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardTopProductDto _$DashboardTopProductDtoFromJson( + Map json, +) { + return _DashboardTopProductDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardTopProductDto { + @JsonKey(name: 'product_id') + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: 'product_name') + String? get productName => throw _privateConstructorUsedError; + @JsonKey(name: 'category_id') + String? get categoryId => throw _privateConstructorUsedError; + @JsonKey(name: 'category_name') + String? get categoryName => throw _privateConstructorUsedError; + @JsonKey(name: 'quantity_sold') + int? get quantitySold => throw _privateConstructorUsedError; + @JsonKey(name: 'revenue') + int? get revenue => throw _privateConstructorUsedError; + @JsonKey(name: 'average_price') + double? get averagePrice => throw _privateConstructorUsedError; + @JsonKey(name: 'order_count') + int? get orderCount => throw _privateConstructorUsedError; + + /// Serializes this DashboardTopProductDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardTopProductDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardTopProductDtoCopyWith<$Res> { + factory $DashboardTopProductDtoCopyWith( + DashboardTopProductDto value, + $Res Function(DashboardTopProductDto) then, + ) = _$DashboardTopProductDtoCopyWithImpl<$Res, DashboardTopProductDto>; + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }); +} + +/// @nodoc +class _$DashboardTopProductDtoCopyWithImpl< + $Res, + $Val extends DashboardTopProductDto +> + implements $DashboardTopProductDtoCopyWith<$Res> { + _$DashboardTopProductDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? averagePrice = freezed, + Object? orderCount = freezed, + }) { + return _then( + _value.copyWith( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardTopProductDtoImplCopyWith<$Res> + implements $DashboardTopProductDtoCopyWith<$Res> { + factory _$$DashboardTopProductDtoImplCopyWith( + _$DashboardTopProductDtoImpl value, + $Res Function(_$DashboardTopProductDtoImpl) then, + ) = __$$DashboardTopProductDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }); +} + +/// @nodoc +class __$$DashboardTopProductDtoImplCopyWithImpl<$Res> + extends + _$DashboardTopProductDtoCopyWithImpl<$Res, _$DashboardTopProductDtoImpl> + implements _$$DashboardTopProductDtoImplCopyWith<$Res> { + __$$DashboardTopProductDtoImplCopyWithImpl( + _$DashboardTopProductDtoImpl _value, + $Res Function(_$DashboardTopProductDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? averagePrice = freezed, + Object? orderCount = freezed, + }) { + return _then( + _$DashboardTopProductDtoImpl( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardTopProductDtoImpl extends _DashboardTopProductDto { + const _$DashboardTopProductDtoImpl({ + @JsonKey(name: 'product_id') this.productId, + @JsonKey(name: 'product_name') this.productName, + @JsonKey(name: 'category_id') this.categoryId, + @JsonKey(name: 'category_name') this.categoryName, + @JsonKey(name: 'quantity_sold') this.quantitySold, + @JsonKey(name: 'revenue') this.revenue, + @JsonKey(name: 'average_price') this.averagePrice, + @JsonKey(name: 'order_count') this.orderCount, + }) : super._(); + + factory _$DashboardTopProductDtoImpl.fromJson(Map json) => + _$$DashboardTopProductDtoImplFromJson(json); + + @override + @JsonKey(name: 'product_id') + final String? productId; + @override + @JsonKey(name: 'product_name') + final String? productName; + @override + @JsonKey(name: 'category_id') + final String? categoryId; + @override + @JsonKey(name: 'category_name') + final String? categoryName; + @override + @JsonKey(name: 'quantity_sold') + final int? quantitySold; + @override + @JsonKey(name: 'revenue') + final int? revenue; + @override + @JsonKey(name: 'average_price') + final double? averagePrice; + @override + @JsonKey(name: 'order_count') + final int? orderCount; + + @override + String toString() { + return 'DashboardTopProductDto(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, averagePrice: $averagePrice, orderCount: $orderCount)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardTopProductDtoImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + averagePrice, + orderCount, + ); + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardTopProductDtoImplCopyWith<_$DashboardTopProductDtoImpl> + get copyWith => + __$$DashboardTopProductDtoImplCopyWithImpl<_$DashboardTopProductDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$DashboardTopProductDtoImplToJson(this); + } +} + +abstract class _DashboardTopProductDto extends DashboardTopProductDto { + const factory _DashboardTopProductDto({ + @JsonKey(name: 'product_id') final String? productId, + @JsonKey(name: 'product_name') final String? productName, + @JsonKey(name: 'category_id') final String? categoryId, + @JsonKey(name: 'category_name') final String? categoryName, + @JsonKey(name: 'quantity_sold') final int? quantitySold, + @JsonKey(name: 'revenue') final int? revenue, + @JsonKey(name: 'average_price') final double? averagePrice, + @JsonKey(name: 'order_count') final int? orderCount, + }) = _$DashboardTopProductDtoImpl; + const _DashboardTopProductDto._() : super._(); + + factory _DashboardTopProductDto.fromJson(Map json) = + _$DashboardTopProductDtoImpl.fromJson; + + @override + @JsonKey(name: 'product_id') + String? get productId; + @override + @JsonKey(name: 'product_name') + String? get productName; + @override + @JsonKey(name: 'category_id') + String? get categoryId; + @override + @JsonKey(name: 'category_name') + String? get categoryName; + @override + @JsonKey(name: 'quantity_sold') + int? get quantitySold; + @override + @JsonKey(name: 'revenue') + int? get revenue; + @override + @JsonKey(name: 'average_price') + double? get averagePrice; + @override + @JsonKey(name: 'order_count') + int? get orderCount; + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardTopProductDtoImplCopyWith<_$DashboardTopProductDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardPaymentMethodDto _$DashboardPaymentMethodDtoFromJson( + Map json, +) { + return _DashboardPaymentMethodDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardPaymentMethodDto { + @JsonKey(name: 'payment_method_id') + String? get paymentMethodId => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_name') + String? get paymentMethodName => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_type') + String? get paymentMethodType => throw _privateConstructorUsedError; + @JsonKey(name: 'total_amount') + int? get totalAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'order_count') + int? get orderCount => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_count') + int? get paymentCount => throw _privateConstructorUsedError; + @JsonKey(name: 'percentage') + double? get percentage => throw _privateConstructorUsedError; + + /// Serializes this DashboardPaymentMethodDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardPaymentMethodDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardPaymentMethodDtoCopyWith<$Res> { + factory $DashboardPaymentMethodDtoCopyWith( + DashboardPaymentMethodDto value, + $Res Function(DashboardPaymentMethodDto) then, + ) = _$DashboardPaymentMethodDtoCopyWithImpl<$Res, DashboardPaymentMethodDto>; + @useResult + $Res call({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }); +} + +/// @nodoc +class _$DashboardPaymentMethodDtoCopyWithImpl< + $Res, + $Val extends DashboardPaymentMethodDto +> + implements $DashboardPaymentMethodDtoCopyWith<$Res> { + _$DashboardPaymentMethodDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = freezed, + Object? paymentMethodName = freezed, + Object? paymentMethodType = freezed, + Object? totalAmount = freezed, + Object? orderCount = freezed, + Object? paymentCount = freezed, + Object? percentage = freezed, + }) { + return _then( + _value.copyWith( + paymentMethodId: freezed == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodName: freezed == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodType: freezed == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String?, + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + paymentCount: freezed == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int?, + percentage: freezed == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardPaymentMethodDtoImplCopyWith<$Res> + implements $DashboardPaymentMethodDtoCopyWith<$Res> { + factory _$$DashboardPaymentMethodDtoImplCopyWith( + _$DashboardPaymentMethodDtoImpl value, + $Res Function(_$DashboardPaymentMethodDtoImpl) then, + ) = __$$DashboardPaymentMethodDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }); +} + +/// @nodoc +class __$$DashboardPaymentMethodDtoImplCopyWithImpl<$Res> + extends + _$DashboardPaymentMethodDtoCopyWithImpl< + $Res, + _$DashboardPaymentMethodDtoImpl + > + implements _$$DashboardPaymentMethodDtoImplCopyWith<$Res> { + __$$DashboardPaymentMethodDtoImplCopyWithImpl( + _$DashboardPaymentMethodDtoImpl _value, + $Res Function(_$DashboardPaymentMethodDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = freezed, + Object? paymentMethodName = freezed, + Object? paymentMethodType = freezed, + Object? totalAmount = freezed, + Object? orderCount = freezed, + Object? paymentCount = freezed, + Object? percentage = freezed, + }) { + return _then( + _$DashboardPaymentMethodDtoImpl( + paymentMethodId: freezed == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodName: freezed == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodType: freezed == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String?, + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + paymentCount: freezed == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int?, + percentage: freezed == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardPaymentMethodDtoImpl extends _DashboardPaymentMethodDto { + const _$DashboardPaymentMethodDtoImpl({ + @JsonKey(name: 'payment_method_id') this.paymentMethodId, + @JsonKey(name: 'payment_method_name') this.paymentMethodName, + @JsonKey(name: 'payment_method_type') this.paymentMethodType, + @JsonKey(name: 'total_amount') this.totalAmount, + @JsonKey(name: 'order_count') this.orderCount, + @JsonKey(name: 'payment_count') this.paymentCount, + @JsonKey(name: 'percentage') this.percentage, + }) : super._(); + + factory _$DashboardPaymentMethodDtoImpl.fromJson(Map json) => + _$$DashboardPaymentMethodDtoImplFromJson(json); + + @override + @JsonKey(name: 'payment_method_id') + final String? paymentMethodId; + @override + @JsonKey(name: 'payment_method_name') + final String? paymentMethodName; + @override + @JsonKey(name: 'payment_method_type') + final String? paymentMethodType; + @override + @JsonKey(name: 'total_amount') + final int? totalAmount; + @override + @JsonKey(name: 'order_count') + final int? orderCount; + @override + @JsonKey(name: 'payment_count') + final int? paymentCount; + @override + @JsonKey(name: 'percentage') + final double? percentage; + + @override + String toString() { + return 'DashboardPaymentMethodDto(paymentMethodId: $paymentMethodId, paymentMethodName: $paymentMethodName, paymentMethodType: $paymentMethodType, totalAmount: $totalAmount, orderCount: $orderCount, paymentCount: $paymentCount, percentage: $percentage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardPaymentMethodDtoImpl && + (identical(other.paymentMethodId, paymentMethodId) || + other.paymentMethodId == paymentMethodId) && + (identical(other.paymentMethodName, paymentMethodName) || + other.paymentMethodName == paymentMethodName) && + (identical(other.paymentMethodType, paymentMethodType) || + other.paymentMethodType == paymentMethodType) && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount) && + (identical(other.paymentCount, paymentCount) || + other.paymentCount == paymentCount) && + (identical(other.percentage, percentage) || + other.percentage == percentage)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + paymentMethodId, + paymentMethodName, + paymentMethodType, + totalAmount, + orderCount, + paymentCount, + percentage, + ); + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardPaymentMethodDtoImplCopyWith<_$DashboardPaymentMethodDtoImpl> + get copyWith => + __$$DashboardPaymentMethodDtoImplCopyWithImpl< + _$DashboardPaymentMethodDtoImpl + >(this, _$identity); + + @override + Map toJson() { + return _$$DashboardPaymentMethodDtoImplToJson(this); + } +} + +abstract class _DashboardPaymentMethodDto extends DashboardPaymentMethodDto { + const factory _DashboardPaymentMethodDto({ + @JsonKey(name: 'payment_method_id') final String? paymentMethodId, + @JsonKey(name: 'payment_method_name') final String? paymentMethodName, + @JsonKey(name: 'payment_method_type') final String? paymentMethodType, + @JsonKey(name: 'total_amount') final int? totalAmount, + @JsonKey(name: 'order_count') final int? orderCount, + @JsonKey(name: 'payment_count') final int? paymentCount, + @JsonKey(name: 'percentage') final double? percentage, + }) = _$DashboardPaymentMethodDtoImpl; + const _DashboardPaymentMethodDto._() : super._(); + + factory _DashboardPaymentMethodDto.fromJson(Map json) = + _$DashboardPaymentMethodDtoImpl.fromJson; + + @override + @JsonKey(name: 'payment_method_id') + String? get paymentMethodId; + @override + @JsonKey(name: 'payment_method_name') + String? get paymentMethodName; + @override + @JsonKey(name: 'payment_method_type') + String? get paymentMethodType; + @override + @JsonKey(name: 'total_amount') + int? get totalAmount; + @override + @JsonKey(name: 'order_count') + int? get orderCount; + @override + @JsonKey(name: 'payment_count') + int? get paymentCount; + @override + @JsonKey(name: 'percentage') + double? get percentage; + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardPaymentMethodDtoImplCopyWith<_$DashboardPaymentMethodDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardRecentSaleDto _$DashboardRecentSaleDtoFromJson( + Map json, +) { + return _DashboardRecentSaleDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardRecentSaleDto { + @JsonKey(name: 'date') + String? get date => throw _privateConstructorUsedError; + @JsonKey(name: 'sales') + int? get sales => throw _privateConstructorUsedError; + @JsonKey(name: 'orders') + int? get orders => throw _privateConstructorUsedError; + @JsonKey(name: 'items') + int? get items => throw _privateConstructorUsedError; + @JsonKey(name: 'tax') + int? get tax => throw _privateConstructorUsedError; + @JsonKey(name: 'discount') + int? get discount => throw _privateConstructorUsedError; + @JsonKey(name: 'net_sales') + int? get netSales => throw _privateConstructorUsedError; + + /// Serializes this DashboardRecentSaleDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardRecentSaleDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardRecentSaleDtoCopyWith<$Res> { + factory $DashboardRecentSaleDtoCopyWith( + DashboardRecentSaleDto value, + $Res Function(DashboardRecentSaleDto) then, + ) = _$DashboardRecentSaleDtoCopyWithImpl<$Res, DashboardRecentSaleDto>; + @useResult + $Res call({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'sales') int? sales, + @JsonKey(name: 'orders') int? orders, + @JsonKey(name: 'items') int? items, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_sales') int? netSales, + }); +} + +/// @nodoc +class _$DashboardRecentSaleDtoCopyWithImpl< + $Res, + $Val extends DashboardRecentSaleDto +> + implements $DashboardRecentSaleDtoCopyWith<$Res> { + _$DashboardRecentSaleDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? sales = freezed, + Object? orders = freezed, + Object? items = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netSales = freezed, + }) { + return _then( + _value.copyWith( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String?, + sales: freezed == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int?, + items: freezed == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int?, + netSales: freezed == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardRecentSaleDtoImplCopyWith<$Res> + implements $DashboardRecentSaleDtoCopyWith<$Res> { + factory _$$DashboardRecentSaleDtoImplCopyWith( + _$DashboardRecentSaleDtoImpl value, + $Res Function(_$DashboardRecentSaleDtoImpl) then, + ) = __$$DashboardRecentSaleDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'sales') int? sales, + @JsonKey(name: 'orders') int? orders, + @JsonKey(name: 'items') int? items, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_sales') int? netSales, + }); +} + +/// @nodoc +class __$$DashboardRecentSaleDtoImplCopyWithImpl<$Res> + extends + _$DashboardRecentSaleDtoCopyWithImpl<$Res, _$DashboardRecentSaleDtoImpl> + implements _$$DashboardRecentSaleDtoImplCopyWith<$Res> { + __$$DashboardRecentSaleDtoImplCopyWithImpl( + _$DashboardRecentSaleDtoImpl _value, + $Res Function(_$DashboardRecentSaleDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? sales = freezed, + Object? orders = freezed, + Object? items = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netSales = freezed, + }) { + return _then( + _$DashboardRecentSaleDtoImpl( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String?, + sales: freezed == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int?, + items: freezed == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int?, + netSales: freezed == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardRecentSaleDtoImpl extends _DashboardRecentSaleDto { + const _$DashboardRecentSaleDtoImpl({ + @JsonKey(name: 'date') this.date, + @JsonKey(name: 'sales') this.sales, + @JsonKey(name: 'orders') this.orders, + @JsonKey(name: 'items') this.items, + @JsonKey(name: 'tax') this.tax, + @JsonKey(name: 'discount') this.discount, + @JsonKey(name: 'net_sales') this.netSales, + }) : super._(); + + factory _$DashboardRecentSaleDtoImpl.fromJson(Map json) => + _$$DashboardRecentSaleDtoImplFromJson(json); + + @override + @JsonKey(name: 'date') + final String? date; + @override + @JsonKey(name: 'sales') + final int? sales; + @override + @JsonKey(name: 'orders') + final int? orders; + @override + @JsonKey(name: 'items') + final int? items; + @override + @JsonKey(name: 'tax') + final int? tax; + @override + @JsonKey(name: 'discount') + final int? discount; + @override + @JsonKey(name: 'net_sales') + final int? netSales; + + @override + String toString() { + return 'DashboardRecentSaleDto(date: $date, sales: $sales, orders: $orders, items: $items, tax: $tax, discount: $discount, netSales: $netSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardRecentSaleDtoImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.sales, sales) || other.sales == sales) && + (identical(other.orders, orders) || other.orders == orders) && + (identical(other.items, items) || other.items == items) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netSales, netSales) || + other.netSales == netSales)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + date, + sales, + orders, + items, + tax, + discount, + netSales, + ); + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardRecentSaleDtoImplCopyWith<_$DashboardRecentSaleDtoImpl> + get copyWith => + __$$DashboardRecentSaleDtoImplCopyWithImpl<_$DashboardRecentSaleDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$DashboardRecentSaleDtoImplToJson(this); + } +} + +abstract class _DashboardRecentSaleDto extends DashboardRecentSaleDto { + const factory _DashboardRecentSaleDto({ + @JsonKey(name: 'date') final String? date, + @JsonKey(name: 'sales') final int? sales, + @JsonKey(name: 'orders') final int? orders, + @JsonKey(name: 'items') final int? items, + @JsonKey(name: 'tax') final int? tax, + @JsonKey(name: 'discount') final int? discount, + @JsonKey(name: 'net_sales') final int? netSales, + }) = _$DashboardRecentSaleDtoImpl; + const _DashboardRecentSaleDto._() : super._(); + + factory _DashboardRecentSaleDto.fromJson(Map json) = + _$DashboardRecentSaleDtoImpl.fromJson; + + @override + @JsonKey(name: 'date') + String? get date; + @override + @JsonKey(name: 'sales') + int? get sales; + @override + @JsonKey(name: 'orders') + int? get orders; + @override + @JsonKey(name: 'items') + int? get items; + @override + @JsonKey(name: 'tax') + int? get tax; + @override + @JsonKey(name: 'discount') + int? get discount; + @override + @JsonKey(name: 'net_sales') + int? get netSales; + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardRecentSaleDtoImplCopyWith<_$DashboardRecentSaleDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/analytic/analytic_dtos.g.dart b/lib/infrastructure/analytic/analytic_dtos.g.dart index e1f95fc..9d3dbdd 100644 --- a/lib/infrastructure/analytic/analytic_dtos.g.dart +++ b/lib/infrastructure/analytic/analytic_dtos.g.dart @@ -385,3 +385,135 @@ Map _$$InventoryIngredientDtoImplToJson( 'is_zero_stock': instance.isZeroStock, 'updated_at': instance.updatedAt, }; + +_$DashboardAnalyticDtoImpl _$$DashboardAnalyticDtoImplFromJson( + Map json, +) => _$DashboardAnalyticDtoImpl( + organizationId: json['organization_id'] as String?, + outletId: json['outlet_id'] as String?, + dateFrom: json['date_from'] as String?, + dateTo: json['date_to'] as String?, + overview: json['overview'] == null + ? null + : DashboardOverviewDto.fromJson(json['overview'] as Map), + topProducts: (json['top_products'] as List?) + ?.map((e) => DashboardTopProductDto.fromJson(e as Map)) + .toList(), + paymentMethods: (json['payment_methods'] as List?) + ?.map( + (e) => DashboardPaymentMethodDto.fromJson(e as Map), + ) + .toList(), + recentSales: (json['recent_sales'] as List?) + ?.map((e) => DashboardRecentSaleDto.fromJson(e as Map)) + .toList(), +); + +Map _$$DashboardAnalyticDtoImplToJson( + _$DashboardAnalyticDtoImpl instance, +) => { + 'organization_id': instance.organizationId, + 'outlet_id': instance.outletId, + 'date_from': instance.dateFrom, + 'date_to': instance.dateTo, + 'overview': instance.overview, + 'top_products': instance.topProducts, + 'payment_methods': instance.paymentMethods, + 'recent_sales': instance.recentSales, +}; + +_$DashboardOverviewDtoImpl _$$DashboardOverviewDtoImplFromJson( + Map json, +) => _$DashboardOverviewDtoImpl( + totalSales: (json['total_sales'] as num?)?.toInt(), + totalOrders: (json['total_orders'] as num?)?.toInt(), + averageOrderValue: (json['average_order_value'] as num?)?.toDouble(), + totalCustomers: (json['total_customers'] as num?)?.toInt(), + voidedOrders: (json['voided_orders'] as num?)?.toInt(), + refundedOrders: (json['refunded_orders'] as num?)?.toInt(), +); + +Map _$$DashboardOverviewDtoImplToJson( + _$DashboardOverviewDtoImpl instance, +) => { + 'total_sales': instance.totalSales, + 'total_orders': instance.totalOrders, + 'average_order_value': instance.averageOrderValue, + 'total_customers': instance.totalCustomers, + 'voided_orders': instance.voidedOrders, + 'refunded_orders': instance.refundedOrders, +}; + +_$DashboardTopProductDtoImpl _$$DashboardTopProductDtoImplFromJson( + Map json, +) => _$DashboardTopProductDtoImpl( + productId: json['product_id'] as String?, + productName: json['product_name'] as String?, + categoryId: json['category_id'] as String?, + categoryName: json['category_name'] as String?, + quantitySold: (json['quantity_sold'] as num?)?.toInt(), + revenue: (json['revenue'] as num?)?.toInt(), + averagePrice: (json['average_price'] as num?)?.toDouble(), + orderCount: (json['order_count'] as num?)?.toInt(), +); + +Map _$$DashboardTopProductDtoImplToJson( + _$DashboardTopProductDtoImpl instance, +) => { + 'product_id': instance.productId, + 'product_name': instance.productName, + 'category_id': instance.categoryId, + 'category_name': instance.categoryName, + 'quantity_sold': instance.quantitySold, + 'revenue': instance.revenue, + 'average_price': instance.averagePrice, + 'order_count': instance.orderCount, +}; + +_$DashboardPaymentMethodDtoImpl _$$DashboardPaymentMethodDtoImplFromJson( + Map json, +) => _$DashboardPaymentMethodDtoImpl( + paymentMethodId: json['payment_method_id'] as String?, + paymentMethodName: json['payment_method_name'] as String?, + paymentMethodType: json['payment_method_type'] as String?, + totalAmount: (json['total_amount'] as num?)?.toInt(), + orderCount: (json['order_count'] as num?)?.toInt(), + paymentCount: (json['payment_count'] as num?)?.toInt(), + percentage: (json['percentage'] as num?)?.toDouble(), +); + +Map _$$DashboardPaymentMethodDtoImplToJson( + _$DashboardPaymentMethodDtoImpl instance, +) => { + 'payment_method_id': instance.paymentMethodId, + 'payment_method_name': instance.paymentMethodName, + 'payment_method_type': instance.paymentMethodType, + 'total_amount': instance.totalAmount, + 'order_count': instance.orderCount, + 'payment_count': instance.paymentCount, + 'percentage': instance.percentage, +}; + +_$DashboardRecentSaleDtoImpl _$$DashboardRecentSaleDtoImplFromJson( + Map json, +) => _$DashboardRecentSaleDtoImpl( + date: json['date'] as String?, + sales: (json['sales'] as num?)?.toInt(), + orders: (json['orders'] as num?)?.toInt(), + items: (json['items'] as num?)?.toInt(), + tax: (json['tax'] as num?)?.toInt(), + discount: (json['discount'] as num?)?.toInt(), + netSales: (json['net_sales'] as num?)?.toInt(), +); + +Map _$$DashboardRecentSaleDtoImplToJson( + _$DashboardRecentSaleDtoImpl instance, +) => { + 'date': instance.date, + 'sales': instance.sales, + 'orders': instance.orders, + 'items': instance.items, + 'tax': instance.tax, + 'discount': instance.discount, + 'net_sales': instance.netSales, +}; diff --git a/lib/infrastructure/analytic/datasource/remote_data_provider.dart b/lib/infrastructure/analytic/datasource/remote_data_provider.dart index 83ab43f..e8e7c7d 100644 --- a/lib/infrastructure/analytic/datasource/remote_data_provider.dart +++ b/lib/infrastructure/analytic/datasource/remote_data_provider.dart @@ -126,4 +126,32 @@ class AnalyticRemoteDataProvider { return DC.error(AnalyticFailure.serverError(e)); } } + + Future> fetchDashboard({ + required String outletId, + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + final response = await _apiClient.get( + ApiPath.dashboardAnalytic, + params: { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = DashboardAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchDashboardError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } } diff --git a/lib/infrastructure/analytic/dto/dashboard_analytic_dto.dart b/lib/infrastructure/analytic/dto/dashboard_analytic_dto.dart new file mode 100644 index 0000000..f17bfe5 --- /dev/null +++ b/lib/infrastructure/analytic/dto/dashboard_analytic_dto.dart @@ -0,0 +1,145 @@ +part of '../analytic_dtos.dart'; + +@freezed +class DashboardAnalyticDto with _$DashboardAnalyticDto { + const DashboardAnalyticDto._(); + + const factory DashboardAnalyticDto({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'overview') DashboardOverviewDto? overview, + @JsonKey(name: 'top_products') List? topProducts, + @JsonKey(name: 'payment_methods') + List? paymentMethods, + @JsonKey(name: 'recent_sales') List? recentSales, + }) = _DashboardAnalyticDto; + + factory DashboardAnalyticDto.fromJson(Map json) => + _$DashboardAnalyticDtoFromJson(json); + + DashboardAnalytic toDomain() => DashboardAnalytic( + organizationId: organizationId ?? '', + outletId: outletId ?? '', + dateFrom: dateFrom ?? '', + dateTo: dateTo ?? '', + overview: overview?.toDomain() ?? DashboardOverview.empty(), + topProducts: topProducts?.map((e) => e.toDomain()).toList() ?? [], + paymentMethods: paymentMethods?.map((e) => e.toDomain()).toList() ?? [], + recentSales: recentSales?.map((e) => e.toDomain()).toList() ?? [], + ); +} + +@freezed +class DashboardOverviewDto with _$DashboardOverviewDto { + const DashboardOverviewDto._(); + + const factory DashboardOverviewDto({ + @JsonKey(name: 'total_sales') int? totalSales, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + @JsonKey(name: 'total_customers') int? totalCustomers, + @JsonKey(name: 'voided_orders') int? voidedOrders, + @JsonKey(name: 'refunded_orders') int? refundedOrders, + }) = _DashboardOverviewDto; + + factory DashboardOverviewDto.fromJson(Map json) => + _$DashboardOverviewDtoFromJson(json); + + DashboardOverview toDomain() => DashboardOverview( + totalSales: totalSales ?? 0, + totalOrders: totalOrders ?? 0, + averageOrderValue: averageOrderValue ?? 0.0, + totalCustomers: totalCustomers ?? 0, + voidedOrders: voidedOrders ?? 0, + refundedOrders: refundedOrders ?? 0, + ); +} + +@freezed +class DashboardTopProductDto with _$DashboardTopProductDto { + const DashboardTopProductDto._(); + + const factory DashboardTopProductDto({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }) = _DashboardTopProductDto; + + factory DashboardTopProductDto.fromJson(Map json) => + _$DashboardTopProductDtoFromJson(json); + + DashboardTopProduct toDomain() => DashboardTopProduct( + productId: productId ?? '', + productName: productName ?? '', + categoryId: categoryId ?? '', + categoryName: categoryName ?? '', + quantitySold: quantitySold ?? 0, + revenue: revenue ?? 0, + averagePrice: averagePrice ?? 0.0, + orderCount: orderCount ?? 0, + ); +} + +@freezed +class DashboardPaymentMethodDto with _$DashboardPaymentMethodDto { + const DashboardPaymentMethodDto._(); + + const factory DashboardPaymentMethodDto({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }) = _DashboardPaymentMethodDto; + + factory DashboardPaymentMethodDto.fromJson(Map json) => + _$DashboardPaymentMethodDtoFromJson(json); + + DashboardPaymentMethod toDomain() => DashboardPaymentMethod( + paymentMethodId: paymentMethodId ?? '', + paymentMethodName: paymentMethodName ?? '', + paymentMethodType: paymentMethodType ?? '', + totalAmount: totalAmount ?? 0, + orderCount: orderCount ?? 0, + paymentCount: paymentCount ?? 0, + percentage: percentage ?? 0.0, + ); +} + +/// ===================== RECENT SALE DTO ===================== +@freezed +class DashboardRecentSaleDto with _$DashboardRecentSaleDto { + const DashboardRecentSaleDto._(); + + const factory DashboardRecentSaleDto({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'sales') int? sales, + @JsonKey(name: 'orders') int? orders, + @JsonKey(name: 'items') int? items, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_sales') int? netSales, + }) = _DashboardRecentSaleDto; + + factory DashboardRecentSaleDto.fromJson(Map json) => + _$DashboardRecentSaleDtoFromJson(json); + + DashboardRecentSale toDomain() => DashboardRecentSale( + date: date ?? '', + sales: sales ?? 0, + orders: orders ?? 0, + items: items ?? 0, + tax: tax ?? 0, + discount: discount ?? 0, + netSales: netSales ?? 0, + ); +} diff --git a/lib/infrastructure/analytic/repositories/analytic_repository.dart b/lib/infrastructure/analytic/repositories/analytic_repository.dart index 3001595..011f2bc 100644 --- a/lib/infrastructure/analytic/repositories/analytic_repository.dart +++ b/lib/infrastructure/analytic/repositories/analytic_repository.dart @@ -115,4 +115,31 @@ class AnalyticRepository implements IAnalyticRepository { return left(const AnalyticFailure.unexpectedError()); } } + + @override + Future> getDashboard({ + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + User currentUser = await _authLocalDataProvider.currentUser(); + + final result = await _dataProvider.fetchDashboard( + outletId: currentUser.outletId, + dateFrom: dateFrom, + dateTo: dateTo, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.toDomain(); + + return right(auth); + } catch (e, s) { + log('getDashboardError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } } diff --git a/lib/injection.config.dart b/lib/injection.config.dart index 2a46271..a63e8a5 100644 --- a/lib/injection.config.dart +++ b/lib/injection.config.dart @@ -11,6 +11,8 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:apskel_owner_flutter/application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart' as _i1038; +import 'package:apskel_owner_flutter/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart' + as _i516; import 'package:apskel_owner_flutter/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart' as _i785; import 'package:apskel_owner_flutter/application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart' @@ -174,6 +176,9 @@ extension GetItInjectableX on _i174.GetIt { gh.factory<_i785.InventoryAnalyticLoaderBloc>( () => _i785.InventoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()), ); + gh.factory<_i516.DashboardAnalyticLoaderBloc>( + () => _i516.DashboardAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); gh.factory<_i775.LoginFormBloc>( () => _i775.LoginFormBloc(gh<_i49.IAuthRepository>()), ); diff --git a/lib/presentation/pages/report/report_page.dart b/lib/presentation/pages/report/report_page.dart index 05510e4..60be8f5 100644 --- a/lib/presentation/pages/report/report_page.dart +++ b/lib/presentation/pages/report/report_page.dart @@ -1,24 +1,35 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:line_icons/line_icons.dart'; import 'dart:math' as math; +import '../../../application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart'; import '../../../common/theme/theme.dart'; +import '../../../injection.dart'; import '../../components/appbar/appbar.dart'; import '../../components/button/button.dart'; import '../../components/spacer/spacer.dart'; +import 'widgets/payment_method.dart'; import 'widgets/quick_stats.dart'; -import 'widgets/report_action.dart'; import 'widgets/revenue_summary.dart'; import 'widgets/sales.dart'; import 'widgets/top_product.dart'; @RoutePage() -class ReportPage extends StatefulWidget { +class ReportPage extends StatefulWidget implements AutoRouteWrapper { const ReportPage({super.key}); @override State createState() => _ReportPageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (context) => + getIt() + ..add(DashboardAnalyticLoaderEvent.fetched()), + child: this, + ); } class _ReportPageState extends State with TickerProviderStateMixin { @@ -78,54 +89,76 @@ class _ReportPageState extends State with TickerProviderStateMixin { Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, - body: CustomScrollView( - slivers: [ - SliverAppBar( - expandedHeight: 120, - floating: false, - pinned: true, - backgroundColor: AppColor.primary, - centerTitle: false, - flexibleSpace: CustomAppBar(title: 'Laporan', isBack: false), - actions: [ - ActionIconButton(onTap: () {}, icon: LineIcons.download), - ActionIconButton(onTap: () {}, icon: LineIcons.filter), - SpaceWidth(8), - ], - ), + body: + BlocBuilder< + DashboardAnalyticLoaderBloc, + DashboardAnalyticLoaderState + >( + builder: (context, state) { + return CustomScrollView( + slivers: [ + SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + backgroundColor: AppColor.primary, + centerTitle: false, + flexibleSpace: CustomAppBar( + title: 'Laporan', + isBack: false, + ), + actions: [ + ActionIconButton(onTap: () {}, icon: LineIcons.download), + ActionIconButton(onTap: () {}, icon: LineIcons.filter), + SpaceWidth(8), + ], + ), - // Content - SliverPadding( - padding: EdgeInsets.all(AppValue.padding), - sliver: SliverList( - delegate: SliverChildListDelegate([ - FadeTransition( - opacity: _fadeAnimation, - child: SlideTransition( - position: _slideAnimation, - child: Column( - children: [ - ReportRevenueSummary( - rotationAnimation: _rotationAnimation, + // Content + SliverPadding( + padding: EdgeInsets.all(AppValue.padding), + sliver: SliverList( + delegate: SliverChildListDelegate([ + FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Column( + children: [ + ReportRevenueSummary( + overview: state.dashboardAnalytic.overview, + rotationAnimation: _rotationAnimation, + ), + const SpaceHeight(24), + ReportQuickStats( + overview: state.dashboardAnalytic.overview, + ), + const SpaceHeight(24), + ReportSales( + salesData: + state.dashboardAnalytic.recentSales, + ), + const SpaceHeight(24), + ReportPaymentMethod( + paymentMethods: + state.dashboardAnalytic.paymentMethods, + ), + const SpaceHeight(24), + ReportTopProduct( + products: state.dashboardAnalytic.topProducts, + ), + const SpaceHeight(24), + ], + ), + ), ), - const SpaceHeight(24), - ReportQuickStats(), - const SpaceHeight(24), - ReportSales(), - const SpaceHeight(24), - ReportTopProduct(), - const SpaceHeight(24), - ReportAction(), - const SpaceHeight(20), - ], + ]), ), ), - ), - ]), - ), + ], + ); + }, ), - ], - ), ); } } diff --git a/lib/presentation/pages/report/widgets/payment_method.dart b/lib/presentation/pages/report/widgets/payment_method.dart new file mode 100644 index 0000000..dcb1396 --- /dev/null +++ b/lib/presentation/pages/report/widgets/payment_method.dart @@ -0,0 +1,616 @@ +import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; +import '../../../components/widgets/empty_widget.dart'; + +class ReportPaymentMethod extends StatelessWidget { + final List paymentMethods; + + const ReportPaymentMethod({super.key, required this.paymentMethods}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.06), + blurRadius: 20, + offset: const Offset(0, 4), + spreadRadius: -4, + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + child: Icon(Icons.payment, color: AppColor.white, size: 24), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Payment Methods', + style: AppStyle.xl.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + const SizedBox(height: 4), + Text( + 'Revenue breakdown by payment method', + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + ), + ), + ], + ), + ), + ], + ), + + const SizedBox(height: 24), + + // Payment Method List + if (paymentMethods.isEmpty) + _buildEmptyState() + else + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: paymentMethods.length, + padding: EdgeInsets.zero, + separatorBuilder: (context, index) => + const SizedBox(height: 12), + itemBuilder: (context, index) { + final method = paymentMethods[index]; + return TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: Duration(milliseconds: 600 + (index * 150)), + curve: Curves.easeOutCubic, + builder: (context, value, child) { + return Transform.translate( + offset: Offset(30 * (1 - value), 0), + child: Opacity( + opacity: value, + child: _buildPaymentMethodTile( + context, + method, + index, + ), + ), + ); + }, + ); + }, + ), + ], + ), + ), + ); + } + + Widget _buildPaymentMethodTile( + BuildContext context, + DashboardPaymentMethod method, + int index, + ) { + final screenWidth = MediaQuery.of(context).size.width; + final isCompact = screenWidth < 400; // For smaller screens + + return Container( + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.1), + width: 1.5, + ), + boxShadow: [ + BoxShadow( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.08), + blurRadius: 12, + offset: const Offset(0, 4), + spreadRadius: -2, + ), + BoxShadow( + color: Colors.black.withOpacity(0.03), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: Stack( + children: [ + // Subtle background gradient + Positioned.fill( + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.03), + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.01), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + ), + ), + ), + + // Main content + Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header section with improved responsive layout + if (isCompact) + _buildCompactHeader(method) + else + _buildStandardHeader(context, method), + + const SizedBox(height: 16), + + // Stats row with better spacing + _buildStatsSection(method), + + const SizedBox(height: 16), + + // Enhanced progress bar section + _buildProgressSection(method, index), + ], + ), + ), + + // Accent line on the left + Positioned( + left: 0, + top: 0, + bottom: 0, + child: Container( + width: 4, + decoration: BoxDecoration( + color: _getPaymentMethodColor(method.paymentMethodType), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + bottomLeft: Radius.circular(16), + ), + ), + ), + ), + ], + ), + ), + ); + } + + Widget _buildStandardHeader( + BuildContext context, + DashboardPaymentMethod method, + ) { + return Row( + children: [ + // Enhanced icon container + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getPaymentMethodColor(method.paymentMethodType), + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + child: Icon( + _getPaymentMethodIcon(method.paymentMethodType), + color: AppColor.white, + size: 28, + ), + ), + + const SizedBox(width: 16), + + // Payment method info - improved text handling + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + method.paymentMethodName, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 6), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + decoration: BoxDecoration( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.2), + width: 1, + ), + ), + child: Text( + method.paymentMethodType.toUpperCase(), + style: AppStyle.xs.copyWith( + color: _getPaymentMethodColor(method.paymentMethodType), + fontWeight: FontWeight.bold, + letterSpacing: 0.8, + ), + ), + ), + ], + ), + ), + + const SizedBox(width: 12), + + // Percentage badge + Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: _getPaymentMethodColor(method.paymentMethodType), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.3), + blurRadius: 6, + offset: const Offset(0, 3), + ), + ], + ), + child: Text( + '${method.percentage.toStringAsFixed(1)}%', + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ); + } + + Widget _buildCompactHeader(DashboardPaymentMethod method) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getPaymentMethodColor(method.paymentMethodType), + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.8), + ], + ), + borderRadius: BorderRadius.circular(14), + ), + child: Icon( + _getPaymentMethodIcon(method.paymentMethodType), + color: AppColor.white, + size: 24, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + method.paymentMethodName, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 4), + Text( + method.paymentMethodType.toUpperCase(), + style: AppStyle.xs.copyWith( + color: _getPaymentMethodColor(method.paymentMethodType), + fontWeight: FontWeight.bold, + letterSpacing: 0.5, + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + decoration: BoxDecoration( + color: _getPaymentMethodColor(method.paymentMethodType), + borderRadius: BorderRadius.circular(16), + ), + child: Text( + '${method.percentage.toStringAsFixed(1)}%', + style: AppStyle.xs.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ], + ); + } + + Widget _buildStatsSection(DashboardPaymentMethod method) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.background.withOpacity(0.5), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.border.withOpacity(0.2), width: 1), + ), + child: IntrinsicHeight( + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Total Revenue', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + ), + ), + const SizedBox(height: 6), + Text( + method.totalAmount.currencyFormatRp, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + Container( + width: 1, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AppColor.border.withOpacity(0.3), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + 'Orders', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + ), + ), + const SizedBox(height: 6), + Text( + '${method.orderCount}', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: _getPaymentMethodColor(method.paymentMethodType), + ), + ), + ], + ), + ], + ), + ), + ); + } + + Widget _buildProgressSection(DashboardPaymentMethod method, int index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Revenue Share', + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w600, + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + '${method.percentage.toStringAsFixed(1)}%', + style: AppStyle.sm.copyWith( + color: _getPaymentMethodColor(method.paymentMethodType), + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + const SizedBox(height: 12), + TweenAnimationBuilder( + tween: Tween(begin: 0, end: method.percentage / 100), + duration: Duration(milliseconds: 1200 + (index * 200)), + curve: Curves.easeOutCubic, + builder: (context, value, child) { + return Container( + height: 8, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: AppColor.border.withOpacity(0.3), + ), + child: Stack( + children: [ + FractionallySizedBox( + widthFactor: value, + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getPaymentMethodColor(method.paymentMethodType), + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.8), + ], + ), + borderRadius: BorderRadius.circular(4), + boxShadow: [ + BoxShadow( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.3), + blurRadius: 4, + offset: const Offset(0, 1), + ), + ], + ), + ), + ), + ], + ), + ); + }, + ), + ], + ); + } + + Widget _buildEmptyState() { + return EmptyWidget( + title: 'No Payment Methods', + message: + 'Payment method data will appear here once transactions are made', + ); + } + + Color _getPaymentMethodColor(String type) { + switch (type.toLowerCase()) { + case 'cash': + return AppColor.success; + case 'card': + case 'credit_card': + case 'debit_card': + return AppColor.info; + case 'bank_transfer': + case 'transfer': + return AppColor.primary; + case 'ewallet': + case 'e_wallet': + case 'digital_wallet': + return AppColor.warning; + case 'qr_code': + case 'qris': + return const Color(0xFF9C27B0); // Purple + default: + return AppColor.textSecondary; + } + } + + IconData _getPaymentMethodIcon(String type) { + switch (type.toLowerCase()) { + case 'cash': + return Icons.payments; + case 'card': + case 'credit_card': + case 'debit_card': + return Icons.credit_card; + case 'bank_transfer': + case 'transfer': + return Icons.account_balance; + case 'ewallet': + case 'e_wallet': + case 'digital_wallet': + return Icons.account_balance_wallet; + case 'qr_code': + case 'qris': + return Icons.qr_code; + default: + return Icons.payment; + } + } +} diff --git a/lib/presentation/pages/report/widgets/quick_stats.dart b/lib/presentation/pages/report/widgets/quick_stats.dart index 9e46687..49d847c 100644 --- a/lib/presentation/pages/report/widgets/quick_stats.dart +++ b/lib/presentation/pages/report/widgets/quick_stats.dart @@ -1,53 +1,109 @@ import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; import 'stat_tile.dart'; class ReportQuickStats extends StatelessWidget { - const ReportQuickStats({super.key}); + final DashboardOverview overview; + + const ReportQuickStats({super.key, required this.overview}); @override Widget build(BuildContext context) { - return Row( + return Column( children: [ - Expanded( - child: TweenAnimationBuilder( - tween: Tween(begin: 0, end: 1), - duration: const Duration(milliseconds: 800), - builder: (context, value, child) { - return Transform.scale( - scale: value, - child: ReportStatTile( - title: 'Total Transaksi', - value: '245', - icon: Icons.receipt_long, - color: AppColor.info, - change: '+8.2%', - animatedValue: 245 * value, - ), - ); - }, - ), + Row( + children: [ + Expanded( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 800), + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: ReportStatTile( + title: 'Total Orders', + value: overview.totalOrders.toString(), + icon: Icons.receipt_long, + color: AppColor.info, + animatedValue: overview.totalOrders * value, + ), + ); + }, + ), + ), + const SizedBox(width: 16), + Expanded( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 1000), + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: ReportStatTile( + title: 'Average Order', + value: overview.averageOrderValue + .round() + .currencyFormatRp, + icon: Icons.trending_up, + color: AppColor.warning, + animatedValue: overview.averageOrderValue * value, + ), + ); + }, + ), + ), + ], ), - const SizedBox(width: 16), - Expanded( - child: TweenAnimationBuilder( - tween: Tween(begin: 0, end: 1), - duration: const Duration(milliseconds: 1000), - builder: (context, value, child) { - return Transform.scale( - scale: value, - child: ReportStatTile( - title: 'Rata-rata', - value: 'Rp 63.061', - icon: Icons.trending_up, - color: AppColor.warning, - change: '+5.1%', - animatedValue: 63061 * value, - ), - ); - }, - ), + + const SizedBox(height: 16), + + Row( + children: [ + Expanded( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 1200), + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: ReportStatTile( + title: 'Customers', + value: overview.totalCustomers.toString(), + icon: Icons.people, + color: AppColor.success, + animatedValue: overview.totalCustomers * value, + ), + ); + }, + ), + ), + const SizedBox(width: 16), + Expanded( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 1400), + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: ReportStatTile( + title: 'Void + Refund', + value: (overview.voidedOrders + overview.refundedOrders) + .toString(), + + icon: Icons.cancel, + color: AppColor.error, + animatedValue: + (overview.voidedOrders + overview.refundedOrders) * + value, + ), + ); + }, + ), + ), + ], ), ], ); diff --git a/lib/presentation/pages/report/widgets/report_action.dart b/lib/presentation/pages/report/widgets/report_action.dart deleted file mode 100644 index 44fb29c..0000000 --- a/lib/presentation/pages/report/widgets/report_action.dart +++ /dev/null @@ -1,136 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../../common/theme/theme.dart'; -import '../../../components/spacer/spacer.dart'; - -class ReportAction extends StatefulWidget { - const ReportAction({super.key}); - - @override - State createState() => _ReportActionState(); -} - -class _ReportActionState extends State { - final actions = [ - { - 'title': 'Laporan Detail Penjualan', - 'subtitle': 'Analisis mendalam transaksi harian', - 'icon': Icons.assignment, - 'color': AppColor.primary, - 'gradient': [AppColor.primary, AppColor.primaryLight], - }, - { - 'title': 'Monitor Stok Produk', - 'subtitle': 'Tracking inventory real-time', - 'icon': Icons.inventory_2, - 'color': AppColor.info, - 'gradient': [AppColor.info, const Color(0xFF64B5F6)], - }, - { - 'title': 'Analisis Keuangan', - 'subtitle': 'Profit, loss & cash flow analysis', - 'icon': Icons.account_balance_wallet, - 'color': AppColor.success, - 'gradient': [AppColor.success, AppColor.secondaryLight], - }, - ]; - - @override - Widget build(BuildContext context) { - return Column( - children: actions.map((action) { - return Container( - margin: const EdgeInsets.only(bottom: 16), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () {}, - borderRadius: BorderRadius.circular(20), - child: Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - (action['color'] as Color).withOpacity(0.1), - (action['color'] as Color).withOpacity(0.05), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: (action['color'] as Color).withOpacity(0.3), - width: 1.5, - ), - ), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: action['gradient'] as List, - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: (action['color'] as Color).withOpacity(0.3), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Icon( - action['icon'] as IconData, - color: AppColor.white, - size: 28, - ), - ), - const SizedBox(width: 20), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - action['title'] as String, - style: AppStyle.lg.copyWith( - color: AppColor.textPrimary, - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - const SpaceHeight(4), - Text( - action['subtitle'] as String, - style: AppStyle.sm.copyWith( - color: AppColor.textSecondary, - fontSize: 13, - ), - ), - ], - ), - ), - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: (action['color'] as Color).withOpacity(0.1), - borderRadius: BorderRadius.circular(10), - ), - child: Icon( - Icons.arrow_forward_ios, - color: action['color'] as Color, - size: 16, - ), - ), - ], - ), - ), - ), - ), - ); - }).toList(), - ); - } -} diff --git a/lib/presentation/pages/report/widgets/revenue_summary.dart b/lib/presentation/pages/report/widgets/revenue_summary.dart index 86ec191..c3603d9 100644 --- a/lib/presentation/pages/report/widgets/revenue_summary.dart +++ b/lib/presentation/pages/report/widgets/revenue_summary.dart @@ -1,11 +1,18 @@ import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; import '../../../components/spacer/spacer.dart'; class ReportRevenueSummary extends StatelessWidget { + final DashboardOverview overview; final Animation rotationAnimation; - const ReportRevenueSummary({super.key, required this.rotationAnimation}); + const ReportRevenueSummary({ + super.key, + required this.rotationAnimation, + required this.overview, + }); @override Widget build(BuildContext context) { @@ -106,51 +113,13 @@ class ReportRevenueSummary extends StatelessWidget { ), const Spacer(), Text( - 'Rp 15.450.000', + overview.totalSales.currencyFormatRp, style: AppStyle.h1.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.bold, letterSpacing: -1, ), ), - const SpaceHeight(8), - Row( - children: [ - Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, - ), - decoration: BoxDecoration( - color: AppColor.success.withOpacity(0.9), - borderRadius: BorderRadius.circular(20), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.trending_up, - color: AppColor.textWhite, - size: 16, - ), - SpaceWidth(4), - Text( - '+12.5%', - style: AppStyle.sm.copyWith( - color: AppColor.textWhite, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - const SpaceWidth(12), - Text( - 'dari periode sebelumnya', - style: AppStyle.sm.copyWith(color: AppColor.textWhite), - ), - ], - ), ], ), ), diff --git a/lib/presentation/pages/report/widgets/sales.dart b/lib/presentation/pages/report/widgets/sales.dart index e0b6f69..96b1d79 100644 --- a/lib/presentation/pages/report/widgets/sales.dart +++ b/lib/presentation/pages/report/widgets/sales.dart @@ -1,11 +1,15 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; - +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; import '../../../components/spacer/spacer.dart'; +import '../../../components/widgets/empty_widget.dart'; class ReportSales extends StatelessWidget { - const ReportSales({super.key}); + final List salesData; + + const ReportSales({super.key, required this.salesData}); @override Widget build(BuildContext context) { @@ -25,6 +29,7 @@ class ReportSales extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + // Header Section Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -32,16 +37,17 @@ class ReportSales extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Grafik Penjualan', + 'Sales Chart', style: AppStyle.xxl.copyWith( color: AppColor.textPrimary, - fontWeight: FontWeight.bold, ), ), const SpaceHeight(4), Text( - '7 hari terakhir', + salesData.isEmpty + ? 'No data available' + : '${salesData.length} days overview', style: AppStyle.md.copyWith(color: AppColor.textSecondary), ), ], @@ -60,233 +66,124 @@ class ReportSales extends StatelessWidget { ), ], ), + const SpaceHeight(20), - // Chart Container - Container( - height: 280, - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - AppColor.primary.withOpacity(0.05), - AppColor.backgroundLight, - ], - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: AppColor.primary.withOpacity(0.1), - width: 2, - ), - ), - child: LineChart( - LineChartData( - gridData: FlGridData( - show: true, - drawHorizontalLine: true, - drawVerticalLine: false, - horizontalInterval: 500000, - getDrawingHorizontalLine: (value) { - return FlLine( - color: AppColor.border.withOpacity(0.3), - strokeWidth: 1, - dashArray: [5, 5], - ); - }, - ), - titlesData: FlTitlesData( - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 60, - getTitlesWidget: (value, meta) { - return Text( - '${(value / 1000000).toStringAsFixed(1)}M', - style: AppStyle.sm.copyWith( - color: AppColor.textSecondary, - fontWeight: FontWeight.w500, - ), - ); - }, - ), - ), - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 32, - getTitlesWidget: (value, meta) { - const days = [ - 'Sen', - 'Sel', - 'Rab', - 'Kam', - 'Jum', - 'Sab', - 'Min', - ]; - if (value.toInt() >= 0 && value.toInt() < days.length) { - return Padding( - padding: const EdgeInsets.only(top: 8), - child: Text( - days[value.toInt()], - style: AppStyle.sm.copyWith( - color: AppColor.textSecondary, - fontWeight: FontWeight.w500, - ), - ), - ); - } - return const Text(''); - }, - ), - ), - rightTitles: AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - topTitles: AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - ), - borderData: FlBorderData(show: false), - minX: 0, - maxX: 6, - minY: 0, - maxY: 3000000, - lineBarsData: [ - // Main sales line - LineChartBarData( - spots: [ - const FlSpot(0, 1800000), // Senin - const FlSpot(1, 2200000), // Selasa - const FlSpot(2, 1900000), // Rabu - const FlSpot(3, 2600000), // Kamis - const FlSpot(4, 2300000), // Jumat - const FlSpot(5, 2800000), // Sabtu - const FlSpot(6, 2500000), // Minggu - ], - isCurved: true, - curveSmoothness: 0.35, - gradient: LinearGradient( - colors: [AppColor.primary, AppColor.primaryLight], - begin: Alignment.centerLeft, - end: Alignment.centerRight, - ), - barWidth: 4, - isStrokeCapRound: true, - belowBarData: BarAreaData( - show: true, - gradient: LinearGradient( - colors: [ - AppColor.primary.withOpacity(0.3), - AppColor.primary.withOpacity(0.1), - Colors.transparent, - ], - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - dotData: FlDotData( - show: true, - getDotPainter: (spot, percent, barData, index) { - return FlDotCirclePainter( - radius: 6, - color: AppColor.surface, - strokeWidth: 3, - strokeColor: AppColor.primary, - ); - }, - ), - ), - // Secondary line for comparison - LineChartBarData( - spots: [ - const FlSpot(0, 1500000), - const FlSpot(1, 1800000), - const FlSpot(2, 1600000), - const FlSpot(3, 2100000), - const FlSpot(4, 1900000), - const FlSpot(5, 2300000), - const FlSpot(6, 2100000), - ], - isCurved: true, - curveSmoothness: 0.35, - color: AppColor.success.withOpacity(0.7), - barWidth: 3, - isStrokeCapRound: true, - dashArray: [8, 4], - belowBarData: BarAreaData(show: false), - dotData: FlDotData( - show: true, - getDotPainter: (spot, percent, barData, index) { - return FlDotCirclePainter( - radius: 4, - color: AppColor.success, - strokeWidth: 2, - strokeColor: AppColor.surface, - ); - }, - ), - ), - ], - lineTouchData: LineTouchData( - enabled: true, - touchTooltipData: LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(12), - getTooltipItems: (List touchedBarSpots) { - return touchedBarSpots.map((barSpot) { - final flSpot = barSpot; - const days = [ - 'Senin', - 'Selasa', - 'Rabu', - 'Kamis', - 'Jumat', - 'Sabtu', - 'Minggu', - ]; + // Sales Summary Cards + if (salesData.isNotEmpty) ...[ + _buildSalesSummary(), + const SpaceHeight(20), + ], - return LineTooltipItem( - '${days[flSpot.x.toInt()]}\n', - const TextStyle( - color: AppColor.textWhite, - fontWeight: FontWeight.bold, - fontSize: 14, - ), - children: [ - TextSpan( - text: - 'Rp ${(flSpot.y / 1000000).toStringAsFixed(1)}M', - style: AppStyle.sm.copyWith( - color: AppColor.textWhite, - fontWeight: FontWeight.w500, - ), - ), - ], - ); - }).toList(); - }, + // Chart Container + salesData.isEmpty + ? _buildEmptyChart() + : Container( + height: 300, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.primary.withOpacity(0.05), + AppColor.backgroundLight, + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: AppColor.primary.withOpacity(0.1), + width: 2, + ), ), - touchCallback: - (FlTouchEvent event, LineTouchResponse? touchResponse) { - // Handle touch events here if needed - }, - handleBuiltInTouches: true, + child: _buildSalesChart(), ), - ), - ), - ), const SpaceHeight(16), // Legend + if (salesData.isNotEmpty) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [_buildLegendItem('Sales Data', AppColor.primary)], + ), + ], + ), + ); + } + + Widget _buildSalesSummary() { + final totalSales = salesData.fold(0, (sum, item) => sum + item.sales); + final totalOrders = salesData.fold( + 0, + (sum, item) => sum + item.orders, + ); + final totalItems = salesData.fold(0, (sum, item) => sum + item.items); + final totalNetSales = salesData.fold( + 0, + (sum, item) => sum + item.netSales, + ); + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.backgroundLight, + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColor.border.withOpacity(0.3), width: 1), + ), + child: Column( + children: [ Row( - mainAxisAlignment: MainAxisAlignment.center, children: [ - _buildLegendItem('Minggu Ini', AppColor.primary), - const SpaceWidth(24), - _buildLegendItem('Minggu Lalu', AppColor.success), + Expanded( + child: _buildSummaryItem( + 'Total Sales', + totalSales.currencyFormatRp, + Icons.attach_money, + AppColor.success, + ), + ), + Container( + width: 1, + height: 40, + color: AppColor.border.withOpacity(0.3), + margin: const EdgeInsets.symmetric(horizontal: 16), + ), + Expanded( + child: _buildSummaryItem( + 'Net Sales', + totalNetSales.currencyFormatRp, + Icons.trending_up, + AppColor.primary, + ), + ), + ], + ), + const SpaceHeight(16), + Row( + children: [ + Expanded( + child: _buildSummaryItem( + 'Total Orders', + totalOrders.toString(), + Icons.shopping_cart, + AppColor.info, + ), + ), + Container( + width: 1, + height: 40, + color: AppColor.border.withOpacity(0.3), + margin: const EdgeInsets.symmetric(horizontal: 16), + ), + Expanded( + child: _buildSummaryItem( + 'Total Items', + totalItems.toString(), + Icons.inventory, + AppColor.warning, + ), + ), ], ), ], @@ -294,6 +191,251 @@ class ReportSales extends StatelessWidget { ); } + Widget _buildSummaryItem( + String label, + String value, + IconData icon, + Color color, + ) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(icon, size: 16, color: color), + const SpaceWidth(6), + Text( + label, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + const SpaceHeight(6), + Text( + value, + style: AppStyle.md.copyWith( + color: color, + fontWeight: FontWeight.bold, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ); + } + + Widget _buildSalesChart() { + final maxValue = _getMaxValue(); + final spots = _generateSpots(salesData); + + return LineChart( + LineChartData( + gridData: FlGridData( + show: true, + drawHorizontalLine: true, + drawVerticalLine: false, + horizontalInterval: maxValue / 5, + getDrawingHorizontalLine: (value) { + return FlLine( + color: AppColor.border.withOpacity(0.3), + strokeWidth: 1, + dashArray: [5, 5], + ); + }, + ), + titlesData: FlTitlesData( + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 70, + getTitlesWidget: (value, meta) { + return Text( + _formatCurrency(value), + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ); + }, + ), + ), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 32, + getTitlesWidget: (value, meta) { + final index = value.toInt(); + if (index >= 0 && index < salesData.length) { + final date = DateTime.parse(salesData[index].date); + final dayName = _getDayName(date.weekday); + return Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + dayName, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ); + } + return const Text(''); + }, + ), + ), + rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + ), + borderData: FlBorderData(show: false), + minX: 0, + maxX: (salesData.length - 1).toDouble(), + minY: 0, + maxY: maxValue, + lineBarsData: [ + // Main sales line + LineChartBarData( + spots: spots, + isCurved: true, + curveSmoothness: 0.35, + gradient: LinearGradient( + colors: [AppColor.primary, AppColor.primaryLight], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + barWidth: 4, + isStrokeCapRound: true, + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + AppColor.primary.withOpacity(0.3), + AppColor.primary.withOpacity(0.1), + Colors.transparent, + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, index) { + return FlDotCirclePainter( + radius: 6, + color: AppColor.surface, + strokeWidth: 3, + strokeColor: AppColor.primary, + ); + }, + ), + ), + ], + lineTouchData: LineTouchData( + enabled: true, + touchTooltipData: LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(12), + getTooltipItems: (List touchedBarSpots) { + return touchedBarSpots + .map((barSpot) { + final index = barSpot.x.toInt(); + + if (index >= 0 && index < salesData.length) { + final sale = salesData[index]; + final date = DateTime.parse(sale.date); + final dayName = _getDayName(date.weekday); + + return LineTooltipItem( + '$dayName\n', + const TextStyle( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + children: [ + TextSpan( + text: 'Sales: ${sale.sales.currencyFormatRp}\n', + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.w500, + ), + ), + TextSpan( + text: 'Orders: ${sale.orders}\n', + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.w400, + ), + ), + TextSpan( + text: 'Net: ${sale.netSales.currencyFormatRp}', + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.w400, + ), + ), + ], + ); + } + return null; + }) + .where((item) => item != null) + .cast() + .toList(); + }, + ), + touchCallback: + (FlTouchEvent event, LineTouchResponse? touchResponse) { + // Handle touch events here if needed + }, + handleBuiltInTouches: true, + ), + ), + ); + } + + Widget _buildEmptyChart() { + return EmptyWidget( + title: 'No Sales Data', + message: 'Sales data will appear here once transactions are recorded', + emptyIcon: Icons.show_chart, + ); + } + + List _generateSpots(List data) { + return data.asMap().entries.map((entry) { + final index = entry.key; + final sale = entry.value; + return FlSpot(index.toDouble(), sale.sales.toDouble()); + }).toList(); + } + + double _getMaxValue() { + if (salesData.isEmpty) return 1000000; + + double maxValue = salesData + .map((e) => e.sales.toDouble()) + .reduce((a, b) => a > b ? a : b); + + // Add 20% padding to max value + return maxValue * 1.2; + } + + String _formatCurrency(double value) { + if (value >= 1000000) { + return '${(value / 1000000).toStringAsFixed(1)}M'; + } else if (value >= 1000) { + return '${(value / 1000).toStringAsFixed(0)}K'; + } + return value.toStringAsFixed(0); + } + + String _getDayName(int weekday) { + const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; + return days[weekday - 1]; + } + Widget _buildLegendItem(String label, Color color) { return Row( mainAxisSize: MainAxisSize.min, @@ -311,7 +453,6 @@ class ReportSales extends StatelessWidget { label, style: AppStyle.sm.copyWith( color: AppColor.textSecondary, - fontWeight: FontWeight.w500, ), ), diff --git a/lib/presentation/pages/report/widgets/stat_tile.dart b/lib/presentation/pages/report/widgets/stat_tile.dart index 863aab5..6452eac 100644 --- a/lib/presentation/pages/report/widgets/stat_tile.dart +++ b/lib/presentation/pages/report/widgets/stat_tile.dart @@ -7,7 +7,6 @@ class ReportStatTile extends StatelessWidget { final String value; final IconData icon; final Color color; - final String change; final double animatedValue; const ReportStatTile({ super.key, @@ -15,7 +14,6 @@ class ReportStatTile extends StatelessWidget { required this.value, required this.icon, required this.color, - required this.change, required this.animatedValue, }); @@ -53,20 +51,6 @@ class ReportStatTile extends StatelessWidget { child: Icon(icon, color: color, size: 24), ), const Spacer(), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: AppColor.success.withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - change, - style: AppStyle.sm.copyWith( - color: AppColor.success, - fontWeight: FontWeight.w700, - ), - ), - ), ], ), const SizedBox(height: 16), diff --git a/lib/presentation/pages/report/widgets/top_product.dart b/lib/presentation/pages/report/widgets/top_product.dart index 57404c3..7e914d9 100644 --- a/lib/presentation/pages/report/widgets/top_product.dart +++ b/lib/presentation/pages/report/widgets/top_product.dart @@ -1,10 +1,13 @@ import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; import '../../../components/spacer/spacer.dart'; class ReportTopProduct extends StatelessWidget { - const ReportTopProduct({super.key}); + final List products; + const ReportTopProduct({super.key, required this.products}); @override Widget build(BuildContext context) { @@ -59,39 +62,25 @@ class ReportTopProduct extends StatelessWidget { ], ), const SpaceHeight(20), - _buildEnhancedProductItem( - 'Kopi Americano', - 'Rp 25.000', - '145 terjual', - 1, - ), - _buildEnhancedProductItem( - 'Nasi Goreng Spesial', - 'Rp 35.000', - '98 terjual', - 2, - ), - _buildEnhancedProductItem( - 'Mie Ayam Bakso', - 'Rp 28.000', - '87 terjual', - 3, + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return _buildEnhancedProductItem(products[index], index + 1); + }, + itemCount: products.length, ), ], ), ); } - Widget _buildEnhancedProductItem( - String name, - String price, - String sold, - int rank, - ) { + Widget _buildEnhancedProductItem(DashboardTopProduct product, int rank) { final isFirst = rank == 1; + final isTopThree = rank <= 3; + return Container( margin: const EdgeInsets.only(bottom: 16), - padding: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: isFirst ? LinearGradient( @@ -102,100 +91,478 @@ class ReportTopProduct extends StatelessWidget { begin: Alignment.topLeft, end: Alignment.bottomRight, ) + : isTopThree + ? LinearGradient( + colors: [ + AppColor.primary.withOpacity(0.08), + AppColor.primary.withOpacity(0.03), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) : null, - color: isFirst ? null : AppColor.backgroundLight, - borderRadius: BorderRadius.circular(16), + color: isTopThree ? null : AppColor.white, + borderRadius: BorderRadius.circular(20), border: Border.all( - color: isFirst ? AppColor.warning.withOpacity(0.3) : AppColor.border, + color: isFirst + ? AppColor.warning.withOpacity(0.3) + : isTopThree + ? AppColor.primary.withOpacity(0.2) + : AppColor.border.withOpacity(0.3), width: isFirst ? 2 : 1, ), - ), - child: Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - gradient: isFirst - ? const LinearGradient( - colors: [AppColor.warning, Color(0xFFFFB74D)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ) - : LinearGradient( - colors: [ - AppColor.primary.withOpacity(0.8), - AppColor.primaryLight.withOpacity(0.6), - ], - ), - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: isFirst - ? AppColor.warning.withOpacity(0.3) - : AppColor.primary.withOpacity(0.2), - blurRadius: 8, - offset: const Offset(0, 4), - ), - ], - ), - child: Center( - child: isFirst - ? const Icon( - Icons.emoji_events, - color: AppColor.white, - size: 24, - ) - : Text( - rank.toString(), - style: AppStyle.xl.copyWith( - color: AppColor.white, - fontWeight: FontWeight.bold, - ), - ), - ), + boxShadow: [ + BoxShadow( + color: isFirst + ? AppColor.warning.withOpacity(0.15) + : isTopThree + ? AppColor.primary.withOpacity(0.1) + : Colors.black.withOpacity(0.04), + blurRadius: isFirst ? 16 : 12, + offset: const Offset(0, 4), + spreadRadius: isFirst ? -2 : -3, ), - const SpaceWidth(16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: AppStyle.lg.copyWith( - color: AppColor.textPrimary, - fontWeight: FontWeight.w600, + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Stack( + children: [ + // Top accent line for rank 1-3 + if (isTopThree) + Positioned( + top: 0, + left: 0, + right: 0, + child: Container( + height: 4, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: isFirst + ? [ + AppColor.warning, + AppColor.warning.withOpacity(0.7), + ] + : [ + AppColor.primary, + AppColor.primary.withOpacity(0.7), + ], + ), ), ), - const SpaceHeight(4), - Row( - children: [ - Icon( - Icons.shopping_cart, - size: 14, - color: AppColor.textSecondary, + ), + + // Main content + Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header with rank and product info + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Rank badge + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + gradient: isFirst + ? const LinearGradient( + colors: [AppColor.warning, Color(0xFFFFB74D)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : isTopThree + ? LinearGradient( + colors: [ + AppColor.primary, + AppColor.primary.withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : LinearGradient( + colors: [ + AppColor.textSecondary.withOpacity(0.8), + AppColor.textSecondary.withOpacity(0.6), + ], + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: isFirst + ? AppColor.warning.withOpacity(0.3) + : isTopThree + ? AppColor.primary.withOpacity(0.3) + : AppColor.textSecondary.withOpacity(0.2), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Center( + child: isFirst + ? const Icon( + Icons.emoji_events, + color: AppColor.white, + size: 28, + ) + : rank == 2 + ? const Icon( + Icons.workspace_premium, + color: AppColor.white, + size: 26, + ) + : rank == 3 + ? const Icon( + Icons.military_tech, + color: AppColor.white, + size: 26, + ) + : Text( + rank.toString(), + style: AppStyle.xl.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + ), + ), + + const SpaceWidth(16), + + // Product info + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + product.productName, + style: AppStyle.lg.copyWith( + color: AppColor.textPrimary, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SpaceHeight(6), + // Category badge + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 4, + ), + decoration: BoxDecoration( + color: isFirst + ? AppColor.warning.withOpacity(0.1) + : AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: isFirst + ? AppColor.warning.withOpacity(0.3) + : AppColor.primary.withOpacity(0.3), + width: 1, + ), + ), + child: Text( + product.categoryName, + style: AppStyle.xs.copyWith( + color: isFirst + ? AppColor.warning + : AppColor.primary, + fontWeight: FontWeight.w600, + letterSpacing: 0.5, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ], + ), + + const SpaceHeight(16), + + // Statistics section + Container( + padding: const EdgeInsets.all(14), + decoration: BoxDecoration( + color: AppColor.background.withOpacity(0.5), + borderRadius: BorderRadius.circular(14), + border: Border.all( + color: AppColor.border.withOpacity(0.2), + width: 1, + ), ), - const SpaceWidth(4), - Text( - sold, - style: AppStyle.sm.copyWith( - color: AppColor.textSecondary, + child: Column( + children: [ + // Revenue and Average Price + IntrinsicHeight( + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.attach_money, + size: 14, + color: AppColor.success, + ), + const SpaceWidth(3), + Flexible( + child: Text( + 'Revenue', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SpaceHeight(4), + Text( + product.revenue.currencyFormatRp, + style: AppStyle.sm.copyWith( + color: AppColor.success, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + + Container( + width: 1, + margin: const EdgeInsets.symmetric( + horizontal: 10, + ), + color: AppColor.border.withOpacity(0.3), + ), + + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Text( + 'Avg. Price', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + const SpaceWidth(3), + Icon( + Icons.trending_up, + size: 14, + color: AppColor.primary, + ), + ], + ), + const SpaceHeight(4), + Text( + product.averagePrice + .round() + .currencyFormatRp, + style: AppStyle.sm.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.end, + ), + ], + ), + ), + ], + ), + ), + + const SpaceHeight(10), + + // Quantity Sold and Order Count + IntrinsicHeight( + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.inventory, + size: 14, + color: AppColor.warning, + ), + const SpaceWidth(3), + Flexible( + child: Text( + 'Sold', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SpaceHeight(4), + Text( + '${product.quantitySold}', + style: AppStyle.sm.copyWith( + color: AppColor.warning, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + ], + ), + ), + + Container( + width: 1, + margin: const EdgeInsets.symmetric( + horizontal: 10, + ), + color: AppColor.border.withOpacity(0.3), + ), + + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Text( + 'Orders', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + const SpaceWidth(3), + Icon( + Icons.shopping_cart, + size: 14, + color: AppColor.info, + ), + ], + ), + const SpaceHeight(4), + Text( + '${product.orderCount}', + style: AppStyle.sm.copyWith( + color: AppColor.info, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + + // Performance indicator for top 3 + if (isTopThree) ...[ + const SpaceHeight(10), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: isFirst + ? [ + AppColor.warning.withOpacity(0.2), + AppColor.warning.withOpacity(0.1), + ] + : [ + AppColor.primary.withOpacity(0.2), + AppColor.primary.withOpacity(0.1), + ], + ), + borderRadius: BorderRadius.circular(10), + border: Border.all( + color: isFirst + ? AppColor.warning.withOpacity(0.3) + : AppColor.primary.withOpacity(0.3), + width: 1, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + isFirst ? Icons.star : Icons.trending_up, + size: 14, + color: isFirst + ? AppColor.warning + : AppColor.primary, + ), + const SpaceWidth(5), + Flexible( + child: Text( + isFirst ? 'Best Seller' : 'Top Performer', + style: AppStyle.xs.copyWith( + color: isFirst + ? AppColor.warning + : AppColor.primary, + fontWeight: FontWeight.bold, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], ), ), ], - ), - ], + ], + ), ), - ), - Text( - price, - style: AppStyle.lg.copyWith( - color: isFirst ? AppColor.warning : AppColor.primary, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ], + ], + ), ), ); } diff --git a/lib/presentation/router/app_router.gr.dart b/lib/presentation/router/app_router.gr.dart index b92b613..30d3060 100644 --- a/lib/presentation/router/app_router.gr.dart +++ b/lib/presentation/router/app_router.gr.dart @@ -57,7 +57,7 @@ class CustomerRoute extends _i18.PageRouteInfo { static _i18.PageInfo page = _i18.PageInfo( name, builder: (data) { - return const _i1.CustomerPage(); + return _i18.WrappedRoute(child: const _i1.CustomerPage()); }, ); }