Compare commits

...

6 Commits

Author SHA1 Message Date
efrilm
06d777290d feat: dashboard analytic range date 2025-08-18 17:35:03 +07:00
efrilm
aac3eecf95 feat: invetory range date 2025-08-18 17:27:36 +07:00
efrilm
fb2309ddb3 fix: range date 2025-08-18 17:07:15 +07:00
efrilm
a61b19e45c feat: product analytic range date 2025-08-18 17:06:41 +07:00
efrilm
ac8c2c0f54 feat: profit loss range date 2025-08-18 16:48:35 +07:00
efrilm
1f6e5e9a2b feat: sales range date 2025-08-18 16:43:07 +07:00
37 changed files with 2929 additions and 834 deletions

View File

@ -24,6 +24,9 @@ class DashboardAnalyticLoaderBloc
Emitter<DashboardAnalyticLoaderState> emit,
) {
return event.map(
rangeDateChanged: (e) async {
emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo));
},
fetched: (e) async {
emit(
state.copyWith(
@ -33,8 +36,8 @@ class DashboardAnalyticLoaderBloc
);
final result = await _repository.getDashboard(
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
dateFrom: state.dateFrom,
dateTo: state.dateTo,
);
var data = result.fold(

View File

@ -19,27 +19,34 @@ final _privateConstructorUsedError = UnsupportedError(
mixin _$DashboardAnalyticLoaderEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@ -74,6 +81,165 @@ class _$DashboardAnalyticLoaderEventCopyWithImpl<
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$RangeDateChangedImplCopyWith<$Res> {
factory _$$RangeDateChangedImplCopyWith(
_$RangeDateChangedImpl value,
$Res Function(_$RangeDateChangedImpl) then,
) = __$$RangeDateChangedImplCopyWithImpl<$Res>;
@useResult
$Res call({DateTime dateFrom, DateTime dateTo});
}
/// @nodoc
class __$$RangeDateChangedImplCopyWithImpl<$Res>
extends
_$DashboardAnalyticLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl>
implements _$$RangeDateChangedImplCopyWith<$Res> {
__$$RangeDateChangedImplCopyWithImpl(
_$RangeDateChangedImpl _value,
$Res Function(_$RangeDateChangedImpl) _then,
) : super(_value, _then);
/// Create a copy of DashboardAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? dateFrom = null, Object? dateTo = null}) {
return _then(
_$RangeDateChangedImpl(
null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
}
/// @nodoc
class _$RangeDateChangedImpl implements _RangeDateChanged {
const _$RangeDateChangedImpl(this.dateFrom, this.dateTo);
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'DashboardAnalyticLoaderEvent.rangeDateChanged(dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RangeDateChangedImpl &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
int get hashCode => Object.hash(runtimeType, dateFrom, dateTo);
/// Create a copy of DashboardAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
__$$RangeDateChangedImplCopyWithImpl<_$RangeDateChangedImpl>(
this,
_$identity,
);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) {
return rangeDateChanged(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) {
return rangeDateChanged?.call(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(dateFrom, dateTo);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) {
return rangeDateChanged(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return rangeDateChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(this);
}
return orElse();
}
}
abstract class _RangeDateChanged implements DashboardAnalyticLoaderEvent {
const factory _RangeDateChanged(
final DateTime dateFrom,
final DateTime dateTo,
) = _$RangeDateChangedImpl;
DateTime get dateFrom;
DateTime get dateTo;
/// Create a copy of DashboardAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$FetchedImplCopyWith<$Res> {
factory _$$FetchedImplCopyWith(
@ -116,19 +282,27 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({required TResult Function() fetched}) {
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) {
return fetched();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({TResult? Function()? fetched}) {
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) {
return fetched?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) {
@ -141,6 +315,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) {
return fetched(this);
@ -149,6 +324,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return fetched?.call(this);
@ -157,6 +333,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
@ -177,6 +354,8 @@ mixin _$DashboardAnalyticLoaderState {
Option<AnalyticFailure> get failureOptionDashboardAnalytic =>
throw _privateConstructorUsedError;
bool get isFetching => throw _privateConstructorUsedError;
DateTime get dateFrom => throw _privateConstructorUsedError;
DateTime get dateTo => throw _privateConstructorUsedError;
/// Create a copy of DashboardAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@ -200,6 +379,8 @@ abstract class $DashboardAnalyticLoaderStateCopyWith<$Res> {
DashboardAnalytic dashboardAnalytic,
Option<AnalyticFailure> failureOptionDashboardAnalytic,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
$DashboardAnalyticCopyWith<$Res> get dashboardAnalytic;
@ -226,6 +407,8 @@ class _$DashboardAnalyticLoaderStateCopyWithImpl<
Object? dashboardAnalytic = null,
Object? failureOptionDashboardAnalytic = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_value.copyWith(
@ -242,6 +425,14 @@ class _$DashboardAnalyticLoaderStateCopyWithImpl<
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
)
as $Val,
);
@ -271,6 +462,8 @@ abstract class _$$DashboardAnalyticLoaderStateImplCopyWith<$Res>
DashboardAnalytic dashboardAnalytic,
Option<AnalyticFailure> failureOptionDashboardAnalytic,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
@override
@ -298,6 +491,8 @@ class __$$DashboardAnalyticLoaderStateImplCopyWithImpl<$Res>
Object? dashboardAnalytic = null,
Object? failureOptionDashboardAnalytic = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_$DashboardAnalyticLoaderStateImpl(
@ -313,6 +508,14 @@ class __$$DashboardAnalyticLoaderStateImplCopyWithImpl<$Res>
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
@ -326,6 +529,8 @@ class _$DashboardAnalyticLoaderStateImpl
required this.dashboardAnalytic,
required this.failureOptionDashboardAnalytic,
this.isFetching = false,
required this.dateFrom,
required this.dateTo,
});
@override
@ -335,10 +540,14 @@ class _$DashboardAnalyticLoaderStateImpl
@override
@JsonKey()
final bool isFetching;
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'DashboardAnalyticLoaderState(dashboardAnalytic: $dashboardAnalytic, failureOptionDashboardAnalytic: $failureOptionDashboardAnalytic, isFetching: $isFetching)';
return 'DashboardAnalyticLoaderState(dashboardAnalytic: $dashboardAnalytic, failureOptionDashboardAnalytic: $failureOptionDashboardAnalytic, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
@ -355,7 +564,10 @@ class _$DashboardAnalyticLoaderStateImpl
other.failureOptionDashboardAnalytic ==
failureOptionDashboardAnalytic) &&
(identical(other.isFetching, isFetching) ||
other.isFetching == isFetching));
other.isFetching == isFetching) &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
@ -364,6 +576,8 @@ class _$DashboardAnalyticLoaderStateImpl
dashboardAnalytic,
failureOptionDashboardAnalytic,
isFetching,
dateFrom,
dateTo,
);
/// Create a copy of DashboardAnalyticLoaderState
@ -386,6 +600,8 @@ abstract class _DashboardAnalyticLoaderState
required final DashboardAnalytic dashboardAnalytic,
required final Option<AnalyticFailure> failureOptionDashboardAnalytic,
final bool isFetching,
required final DateTime dateFrom,
required final DateTime dateTo,
}) = _$DashboardAnalyticLoaderStateImpl;
@override
@ -394,6 +610,10 @@ abstract class _DashboardAnalyticLoaderState
Option<AnalyticFailure> get failureOptionDashboardAnalytic;
@override
bool get isFetching;
@override
DateTime get dateFrom;
@override
DateTime get dateTo;
/// Create a copy of DashboardAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.

View File

@ -2,5 +2,9 @@ part of 'dashboard_analytic_loader_bloc.dart';
@freezed
class DashboardAnalyticLoaderEvent with _$DashboardAnalyticLoaderEvent {
const factory DashboardAnalyticLoaderEvent.rangeDateChanged(
DateTime dateFrom,
DateTime dateTo,
) = _RangeDateChanged;
const factory DashboardAnalyticLoaderEvent.fetched() = _Fetched;
}

View File

@ -6,11 +6,15 @@ class DashboardAnalyticLoaderState with _$DashboardAnalyticLoaderState {
required DashboardAnalytic dashboardAnalytic,
required Option<AnalyticFailure> failureOptionDashboardAnalytic,
@Default(false) bool isFetching,
required DateTime dateFrom,
required DateTime dateTo,
}) = _DashboardAnalyticLoaderState;
factory DashboardAnalyticLoaderState.initial() =>
DashboardAnalyticLoaderState(
dashboardAnalytic: DashboardAnalytic.empty(),
failureOptionDashboardAnalytic: none(),
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
);
}

View File

@ -24,6 +24,9 @@ class InventoryAnalyticLoaderBloc
Emitter<InventoryAnalyticLoaderState> emit,
) {
return event.map(
rangeDateChanged: (e) async {
emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo));
},
fetched: (e) async {
emit(
state.copyWith(
@ -33,8 +36,8 @@ class InventoryAnalyticLoaderBloc
);
final result = await _repository.getInventory(
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
dateFrom: state.dateFrom,
dateTo: state.dateTo,
);
var data = result.fold(

View File

@ -19,27 +19,34 @@ final _privateConstructorUsedError = UnsupportedError(
mixin _$InventoryAnalyticLoaderEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@ -74,6 +81,165 @@ class _$InventoryAnalyticLoaderEventCopyWithImpl<
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$RangeDateChangedImplCopyWith<$Res> {
factory _$$RangeDateChangedImplCopyWith(
_$RangeDateChangedImpl value,
$Res Function(_$RangeDateChangedImpl) then,
) = __$$RangeDateChangedImplCopyWithImpl<$Res>;
@useResult
$Res call({DateTime dateFrom, DateTime dateTo});
}
/// @nodoc
class __$$RangeDateChangedImplCopyWithImpl<$Res>
extends
_$InventoryAnalyticLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl>
implements _$$RangeDateChangedImplCopyWith<$Res> {
__$$RangeDateChangedImplCopyWithImpl(
_$RangeDateChangedImpl _value,
$Res Function(_$RangeDateChangedImpl) _then,
) : super(_value, _then);
/// Create a copy of InventoryAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? dateFrom = null, Object? dateTo = null}) {
return _then(
_$RangeDateChangedImpl(
null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
}
/// @nodoc
class _$RangeDateChangedImpl implements _RangeDateChanged {
const _$RangeDateChangedImpl(this.dateFrom, this.dateTo);
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'InventoryAnalyticLoaderEvent.rangeDateChanged(dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RangeDateChangedImpl &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
int get hashCode => Object.hash(runtimeType, dateFrom, dateTo);
/// Create a copy of InventoryAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
__$$RangeDateChangedImplCopyWithImpl<_$RangeDateChangedImpl>(
this,
_$identity,
);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) {
return rangeDateChanged(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) {
return rangeDateChanged?.call(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(dateFrom, dateTo);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) {
return rangeDateChanged(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return rangeDateChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(this);
}
return orElse();
}
}
abstract class _RangeDateChanged implements InventoryAnalyticLoaderEvent {
const factory _RangeDateChanged(
final DateTime dateFrom,
final DateTime dateTo,
) = _$RangeDateChangedImpl;
DateTime get dateFrom;
DateTime get dateTo;
/// Create a copy of InventoryAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$FetchedImplCopyWith<$Res> {
factory _$$FetchedImplCopyWith(
@ -116,19 +282,27 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({required TResult Function() fetched}) {
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) {
return fetched();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({TResult? Function()? fetched}) {
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) {
return fetched?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) {
@ -141,6 +315,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) {
return fetched(this);
@ -149,6 +324,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return fetched?.call(this);
@ -157,6 +333,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
@ -177,6 +354,8 @@ mixin _$InventoryAnalyticLoaderState {
Option<AnalyticFailure> get failureOptionInventoryAnalytic =>
throw _privateConstructorUsedError;
bool get isFetching => throw _privateConstructorUsedError;
DateTime get dateFrom => throw _privateConstructorUsedError;
DateTime get dateTo => throw _privateConstructorUsedError;
/// Create a copy of InventoryAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@ -200,6 +379,8 @@ abstract class $InventoryAnalyticLoaderStateCopyWith<$Res> {
InventoryAnalytic inventoryAnalytic,
Option<AnalyticFailure> failureOptionInventoryAnalytic,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
$InventoryAnalyticCopyWith<$Res> get inventoryAnalytic;
@ -226,6 +407,8 @@ class _$InventoryAnalyticLoaderStateCopyWithImpl<
Object? inventoryAnalytic = null,
Object? failureOptionInventoryAnalytic = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_value.copyWith(
@ -242,6 +425,14 @@ class _$InventoryAnalyticLoaderStateCopyWithImpl<
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
)
as $Val,
);
@ -271,6 +462,8 @@ abstract class _$$InventoryAnalyticLoaderStateImplCopyWith<$Res>
InventoryAnalytic inventoryAnalytic,
Option<AnalyticFailure> failureOptionInventoryAnalytic,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
@override
@ -298,6 +491,8 @@ class __$$InventoryAnalyticLoaderStateImplCopyWithImpl<$Res>
Object? inventoryAnalytic = null,
Object? failureOptionInventoryAnalytic = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_$InventoryAnalyticLoaderStateImpl(
@ -313,6 +508,14 @@ class __$$InventoryAnalyticLoaderStateImplCopyWithImpl<$Res>
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
@ -326,6 +529,8 @@ class _$InventoryAnalyticLoaderStateImpl
required this.inventoryAnalytic,
required this.failureOptionInventoryAnalytic,
this.isFetching = false,
required this.dateFrom,
required this.dateTo,
});
@override
@ -335,10 +540,14 @@ class _$InventoryAnalyticLoaderStateImpl
@override
@JsonKey()
final bool isFetching;
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'InventoryAnalyticLoaderState(inventoryAnalytic: $inventoryAnalytic, failureOptionInventoryAnalytic: $failureOptionInventoryAnalytic, isFetching: $isFetching)';
return 'InventoryAnalyticLoaderState(inventoryAnalytic: $inventoryAnalytic, failureOptionInventoryAnalytic: $failureOptionInventoryAnalytic, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
@ -355,7 +564,10 @@ class _$InventoryAnalyticLoaderStateImpl
other.failureOptionInventoryAnalytic ==
failureOptionInventoryAnalytic) &&
(identical(other.isFetching, isFetching) ||
other.isFetching == isFetching));
other.isFetching == isFetching) &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
@ -364,6 +576,8 @@ class _$InventoryAnalyticLoaderStateImpl
inventoryAnalytic,
failureOptionInventoryAnalytic,
isFetching,
dateFrom,
dateTo,
);
/// Create a copy of InventoryAnalyticLoaderState
@ -386,6 +600,8 @@ abstract class _InventoryAnalyticLoaderState
required final InventoryAnalytic inventoryAnalytic,
required final Option<AnalyticFailure> failureOptionInventoryAnalytic,
final bool isFetching,
required final DateTime dateFrom,
required final DateTime dateTo,
}) = _$InventoryAnalyticLoaderStateImpl;
@override
@ -394,6 +610,10 @@ abstract class _InventoryAnalyticLoaderState
Option<AnalyticFailure> get failureOptionInventoryAnalytic;
@override
bool get isFetching;
@override
DateTime get dateFrom;
@override
DateTime get dateTo;
/// Create a copy of InventoryAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.

View File

@ -2,5 +2,9 @@ part of 'inventory_analytic_loader_bloc.dart';
@freezed
class InventoryAnalyticLoaderEvent with _$InventoryAnalyticLoaderEvent {
const factory InventoryAnalyticLoaderEvent.rangeDateChanged(
DateTime dateFrom,
DateTime dateTo,
) = _RangeDateChanged;
const factory InventoryAnalyticLoaderEvent.fetched() = _Fetched;
}

View File

@ -6,11 +6,15 @@ class InventoryAnalyticLoaderState with _$InventoryAnalyticLoaderState {
required InventoryAnalytic inventoryAnalytic,
required Option<AnalyticFailure> failureOptionInventoryAnalytic,
@Default(false) bool isFetching,
required DateTime dateFrom,
required DateTime dateTo,
}) = _InventoryAnalyticLoaderState;
factory InventoryAnalyticLoaderState.initial() =>
InventoryAnalyticLoaderState(
inventoryAnalytic: InventoryAnalytic.empty(),
failureOptionInventoryAnalytic: none(),
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
);
}

View File

@ -24,6 +24,9 @@ class ProductAnalyticLoaderBloc
Emitter<ProductAnalyticLoaderState> emit,
) {
return event.map(
rangeDateChanged: (e) async {
emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo));
},
fetched: (e) async {
emit(
state.copyWith(
@ -33,8 +36,8 @@ class ProductAnalyticLoaderBloc
);
final result = await _repository.getProduct(
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
dateFrom: state.dateFrom,
dateTo: state.dateTo,
);
var data = result.fold(

View File

@ -19,27 +19,34 @@ final _privateConstructorUsedError = UnsupportedError(
mixin _$ProductAnalyticLoaderEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@ -74,6 +81,165 @@ class _$ProductAnalyticLoaderEventCopyWithImpl<
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$RangeDateChangedImplCopyWith<$Res> {
factory _$$RangeDateChangedImplCopyWith(
_$RangeDateChangedImpl value,
$Res Function(_$RangeDateChangedImpl) then,
) = __$$RangeDateChangedImplCopyWithImpl<$Res>;
@useResult
$Res call({DateTime dateFrom, DateTime dateTo});
}
/// @nodoc
class __$$RangeDateChangedImplCopyWithImpl<$Res>
extends
_$ProductAnalyticLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl>
implements _$$RangeDateChangedImplCopyWith<$Res> {
__$$RangeDateChangedImplCopyWithImpl(
_$RangeDateChangedImpl _value,
$Res Function(_$RangeDateChangedImpl) _then,
) : super(_value, _then);
/// Create a copy of ProductAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? dateFrom = null, Object? dateTo = null}) {
return _then(
_$RangeDateChangedImpl(
null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
}
/// @nodoc
class _$RangeDateChangedImpl implements _RangeDateChanged {
const _$RangeDateChangedImpl(this.dateFrom, this.dateTo);
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'ProductAnalyticLoaderEvent.rangeDateChanged(dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RangeDateChangedImpl &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
int get hashCode => Object.hash(runtimeType, dateFrom, dateTo);
/// Create a copy of ProductAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
__$$RangeDateChangedImplCopyWithImpl<_$RangeDateChangedImpl>(
this,
_$identity,
);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) {
return rangeDateChanged(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) {
return rangeDateChanged?.call(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(dateFrom, dateTo);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) {
return rangeDateChanged(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return rangeDateChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(this);
}
return orElse();
}
}
abstract class _RangeDateChanged implements ProductAnalyticLoaderEvent {
const factory _RangeDateChanged(
final DateTime dateFrom,
final DateTime dateTo,
) = _$RangeDateChangedImpl;
DateTime get dateFrom;
DateTime get dateTo;
/// Create a copy of ProductAnalyticLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$FetchedImplCopyWith<$Res> {
factory _$$FetchedImplCopyWith(
@ -116,19 +282,27 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({required TResult Function() fetched}) {
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) {
return fetched();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({TResult? Function()? fetched}) {
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) {
return fetched?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) {
@ -141,6 +315,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) {
return fetched(this);
@ -149,6 +324,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return fetched?.call(this);
@ -157,6 +333,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
@ -177,6 +354,8 @@ mixin _$ProductAnalyticLoaderState {
Option<AnalyticFailure> get failureOptionProductAnalytic =>
throw _privateConstructorUsedError;
bool get isFetching => throw _privateConstructorUsedError;
DateTime get dateFrom => throw _privateConstructorUsedError;
DateTime get dateTo => throw _privateConstructorUsedError;
/// Create a copy of ProductAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.
@ -200,6 +379,8 @@ abstract class $ProductAnalyticLoaderStateCopyWith<$Res> {
ProductAnalytic productAnalytic,
Option<AnalyticFailure> failureOptionProductAnalytic,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
$ProductAnalyticCopyWith<$Res> get productAnalytic;
@ -226,6 +407,8 @@ class _$ProductAnalyticLoaderStateCopyWithImpl<
Object? productAnalytic = null,
Object? failureOptionProductAnalytic = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_value.copyWith(
@ -241,6 +424,14 @@ class _$ProductAnalyticLoaderStateCopyWithImpl<
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
)
as $Val,
);
@ -270,6 +461,8 @@ abstract class _$$ProductAnalyticLoaderStateImplCopyWith<$Res>
ProductAnalytic productAnalytic,
Option<AnalyticFailure> failureOptionProductAnalytic,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
@override
@ -297,6 +490,8 @@ class __$$ProductAnalyticLoaderStateImplCopyWithImpl<$Res>
Object? productAnalytic = null,
Object? failureOptionProductAnalytic = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_$ProductAnalyticLoaderStateImpl(
@ -312,6 +507,14 @@ class __$$ProductAnalyticLoaderStateImplCopyWithImpl<$Res>
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
@ -324,6 +527,8 @@ class _$ProductAnalyticLoaderStateImpl implements _ProductAnalyticLoaderState {
required this.productAnalytic,
required this.failureOptionProductAnalytic,
this.isFetching = false,
required this.dateFrom,
required this.dateTo,
});
@override
@ -333,10 +538,14 @@ class _$ProductAnalyticLoaderStateImpl implements _ProductAnalyticLoaderState {
@override
@JsonKey()
final bool isFetching;
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'ProductAnalyticLoaderState(productAnalytic: $productAnalytic, failureOptionProductAnalytic: $failureOptionProductAnalytic, isFetching: $isFetching)';
return 'ProductAnalyticLoaderState(productAnalytic: $productAnalytic, failureOptionProductAnalytic: $failureOptionProductAnalytic, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
@ -353,7 +562,10 @@ class _$ProductAnalyticLoaderStateImpl implements _ProductAnalyticLoaderState {
other.failureOptionProductAnalytic ==
failureOptionProductAnalytic) &&
(identical(other.isFetching, isFetching) ||
other.isFetching == isFetching));
other.isFetching == isFetching) &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
@ -362,6 +574,8 @@ class _$ProductAnalyticLoaderStateImpl implements _ProductAnalyticLoaderState {
productAnalytic,
failureOptionProductAnalytic,
isFetching,
dateFrom,
dateTo,
);
/// Create a copy of ProductAnalyticLoaderState
@ -382,6 +596,8 @@ abstract class _ProductAnalyticLoaderState
required final ProductAnalytic productAnalytic,
required final Option<AnalyticFailure> failureOptionProductAnalytic,
final bool isFetching,
required final DateTime dateFrom,
required final DateTime dateTo,
}) = _$ProductAnalyticLoaderStateImpl;
@override
@ -390,6 +606,10 @@ abstract class _ProductAnalyticLoaderState
Option<AnalyticFailure> get failureOptionProductAnalytic;
@override
bool get isFetching;
@override
DateTime get dateFrom;
@override
DateTime get dateTo;
/// Create a copy of ProductAnalyticLoaderState
/// with the given fields replaced by the non-null parameter values.

View File

@ -2,5 +2,9 @@ part of 'product_analytic_loader_bloc.dart';
@freezed
class ProductAnalyticLoaderEvent with _$ProductAnalyticLoaderEvent {
const factory ProductAnalyticLoaderEvent.rangeDateChanged(
DateTime dateFrom,
DateTime dateTo,
) = _RangeDateChanged;
const factory ProductAnalyticLoaderEvent.fetched() = _Fetched;
}

View File

@ -6,10 +6,14 @@ class ProductAnalyticLoaderState with _$ProductAnalyticLoaderState {
required ProductAnalytic productAnalytic,
required Option<AnalyticFailure> failureOptionProductAnalytic,
@Default(false) bool isFetching,
required DateTime dateFrom,
required DateTime dateTo,
}) = _ProductAnalyticLoaderState;
factory ProductAnalyticLoaderState.initial() => ProductAnalyticLoaderState(
productAnalytic: ProductAnalytic.empty(),
failureOptionProductAnalytic: none(),
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
);
}

View File

@ -24,12 +24,15 @@ class ProfitLossLoaderBloc
Emitter<ProfitLossLoaderState> emit,
) {
return event.map(
rangeDateChanged: (e) async {
emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo));
},
fetched: (e) async {
emit(state.copyWith(isFetching: true, failureOptionProfitLoss: none()));
final result = await _repository.getProfitLoss(
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
dateFrom: state.dateFrom,
dateTo: state.dateTo,
);
var data = result.fold(

View File

@ -19,27 +19,34 @@ final _privateConstructorUsedError = UnsupportedError(
mixin _$ProfitLossLoaderEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@ -70,6 +77,164 @@ class _$ProfitLossLoaderEventCopyWithImpl<
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$RangeDateChangedImplCopyWith<$Res> {
factory _$$RangeDateChangedImplCopyWith(
_$RangeDateChangedImpl value,
$Res Function(_$RangeDateChangedImpl) then,
) = __$$RangeDateChangedImplCopyWithImpl<$Res>;
@useResult
$Res call({DateTime dateFrom, DateTime dateTo});
}
/// @nodoc
class __$$RangeDateChangedImplCopyWithImpl<$Res>
extends _$ProfitLossLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl>
implements _$$RangeDateChangedImplCopyWith<$Res> {
__$$RangeDateChangedImplCopyWithImpl(
_$RangeDateChangedImpl _value,
$Res Function(_$RangeDateChangedImpl) _then,
) : super(_value, _then);
/// Create a copy of ProfitLossLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? dateFrom = null, Object? dateTo = null}) {
return _then(
_$RangeDateChangedImpl(
null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
}
/// @nodoc
class _$RangeDateChangedImpl implements _RangeDateChanged {
const _$RangeDateChangedImpl(this.dateFrom, this.dateTo);
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'ProfitLossLoaderEvent.rangeDateChanged(dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RangeDateChangedImpl &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
int get hashCode => Object.hash(runtimeType, dateFrom, dateTo);
/// Create a copy of ProfitLossLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
__$$RangeDateChangedImplCopyWithImpl<_$RangeDateChangedImpl>(
this,
_$identity,
);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) {
return rangeDateChanged(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) {
return rangeDateChanged?.call(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(dateFrom, dateTo);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) {
return rangeDateChanged(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return rangeDateChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(this);
}
return orElse();
}
}
abstract class _RangeDateChanged implements ProfitLossLoaderEvent {
const factory _RangeDateChanged(
final DateTime dateFrom,
final DateTime dateTo,
) = _$RangeDateChangedImpl;
DateTime get dateFrom;
DateTime get dateTo;
/// Create a copy of ProfitLossLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$FetchedImplCopyWith<$Res> {
factory _$$FetchedImplCopyWith(
@ -112,19 +277,27 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({required TResult Function() fetched}) {
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fetched,
}) {
return fetched();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({TResult? Function()? fetched}) {
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fetched,
}) {
return fetched?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fetched,
required TResult orElse(),
}) {
@ -137,6 +310,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fetched value) fetched,
}) {
return fetched(this);
@ -145,6 +319,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return fetched?.call(this);
@ -153,6 +328,7 @@ class _$FetchedImpl implements _Fetched {
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fetched value)? fetched,
required TResult orElse(),
}) {
@ -173,6 +349,8 @@ mixin _$ProfitLossLoaderState {
Option<AnalyticFailure> get failureOptionProfitLoss =>
throw _privateConstructorUsedError;
bool get isFetching => throw _privateConstructorUsedError;
DateTime get dateFrom => throw _privateConstructorUsedError;
DateTime get dateTo => throw _privateConstructorUsedError;
/// Create a copy of ProfitLossLoaderState
/// with the given fields replaced by the non-null parameter values.
@ -192,6 +370,8 @@ abstract class $ProfitLossLoaderStateCopyWith<$Res> {
ProfitLossAnalytic profitLoss,
Option<AnalyticFailure> failureOptionProfitLoss,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
$ProfitLossAnalyticCopyWith<$Res> get profitLoss;
@ -218,6 +398,8 @@ class _$ProfitLossLoaderStateCopyWithImpl<
Object? profitLoss = null,
Object? failureOptionProfitLoss = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_value.copyWith(
@ -233,6 +415,14 @@ class _$ProfitLossLoaderStateCopyWithImpl<
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
)
as $Val,
);
@ -262,6 +452,8 @@ abstract class _$$ProfitLossLoaderStateImplCopyWith<$Res>
ProfitLossAnalytic profitLoss,
Option<AnalyticFailure> failureOptionProfitLoss,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
@override
@ -286,6 +478,8 @@ class __$$ProfitLossLoaderStateImplCopyWithImpl<$Res>
Object? profitLoss = null,
Object? failureOptionProfitLoss = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_$ProfitLossLoaderStateImpl(
@ -301,6 +495,14 @@ class __$$ProfitLossLoaderStateImplCopyWithImpl<$Res>
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
@ -313,6 +515,8 @@ class _$ProfitLossLoaderStateImpl implements _ProfitLossLoaderState {
required this.profitLoss,
required this.failureOptionProfitLoss,
this.isFetching = false,
required this.dateFrom,
required this.dateTo,
});
@override
@ -322,10 +526,14 @@ class _$ProfitLossLoaderStateImpl implements _ProfitLossLoaderState {
@override
@JsonKey()
final bool isFetching;
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'ProfitLossLoaderState(profitLoss: $profitLoss, failureOptionProfitLoss: $failureOptionProfitLoss, isFetching: $isFetching)';
return 'ProfitLossLoaderState(profitLoss: $profitLoss, failureOptionProfitLoss: $failureOptionProfitLoss, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
@ -341,12 +549,21 @@ class _$ProfitLossLoaderStateImpl implements _ProfitLossLoaderState {
) ||
other.failureOptionProfitLoss == failureOptionProfitLoss) &&
(identical(other.isFetching, isFetching) ||
other.isFetching == isFetching));
other.isFetching == isFetching) &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
int get hashCode =>
Object.hash(runtimeType, profitLoss, failureOptionProfitLoss, isFetching);
int get hashCode => Object.hash(
runtimeType,
profitLoss,
failureOptionProfitLoss,
isFetching,
dateFrom,
dateTo,
);
/// Create a copy of ProfitLossLoaderState
/// with the given fields replaced by the non-null parameter values.
@ -366,6 +583,8 @@ abstract class _ProfitLossLoaderState implements ProfitLossLoaderState {
required final ProfitLossAnalytic profitLoss,
required final Option<AnalyticFailure> failureOptionProfitLoss,
final bool isFetching,
required final DateTime dateFrom,
required final DateTime dateTo,
}) = _$ProfitLossLoaderStateImpl;
@override
@ -374,6 +593,10 @@ abstract class _ProfitLossLoaderState implements ProfitLossLoaderState {
Option<AnalyticFailure> get failureOptionProfitLoss;
@override
bool get isFetching;
@override
DateTime get dateFrom;
@override
DateTime get dateTo;
/// Create a copy of ProfitLossLoaderState
/// with the given fields replaced by the non-null parameter values.

View File

@ -2,5 +2,9 @@ part of 'profit_loss_loader_bloc.dart';
@freezed
class ProfitLossLoaderEvent with _$ProfitLossLoaderEvent {
const factory ProfitLossLoaderEvent.rangeDateChanged(
DateTime dateFrom,
DateTime dateTo,
) = _RangeDateChanged;
const factory ProfitLossLoaderEvent.fetched() = _Fetched;
}

View File

@ -6,10 +6,14 @@ class ProfitLossLoaderState with _$ProfitLossLoaderState {
required ProfitLossAnalytic profitLoss,
required Option<AnalyticFailure> failureOptionProfitLoss,
@Default(false) bool isFetching,
required DateTime dateFrom,
required DateTime dateTo,
}) = _ProfitLossLoaderState;
factory ProfitLossLoaderState.initial() => ProfitLossLoaderState(
profitLoss: ProfitLossAnalytic.empty(),
failureOptionProfitLoss: none(),
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
);
}

View File

@ -21,19 +21,26 @@ class SalesLoaderBloc extends Bloc<SalesLoaderEvent, SalesLoaderState> {
Future<void> _onSalesLoaderEvent(
SalesLoaderEvent event,
Emitter<SalesLoaderState> emit,
) async {
emit(state.copyWith(isFetching: true, failureOptionSales: none()));
) {
return event.map(
rangeDateChanged: (e) async {
emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo));
},
fectched: (e) async {
emit(state.copyWith(isFetching: true, failureOptionSales: none()));
final result = await _analyticRepository.getSales(
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
final result = await _analyticRepository.getSales(
dateFrom: state.dateFrom,
dateTo: state.dateTo,
);
var data = result.fold(
(f) => state.copyWith(failureOptionSales: optionOf(f)),
(sales) => state.copyWith(sales: sales),
);
emit(data.copyWith(isFetching: false));
},
);
var data = result.fold(
(f) => state.copyWith(failureOptionSales: optionOf(f)),
(sales) => state.copyWith(sales: sales),
);
emit(data.copyWith(isFetching: false));
}
}

View File

@ -19,27 +19,34 @@ final _privateConstructorUsedError = UnsupportedError(
mixin _$SalesLoaderEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fectched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fectched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fectched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fectched value) fectched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fectched value)? fectched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fectched value)? fectched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@ -67,6 +74,164 @@ class _$SalesLoaderEventCopyWithImpl<$Res, $Val extends SalesLoaderEvent>
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$RangeDateChangedImplCopyWith<$Res> {
factory _$$RangeDateChangedImplCopyWith(
_$RangeDateChangedImpl value,
$Res Function(_$RangeDateChangedImpl) then,
) = __$$RangeDateChangedImplCopyWithImpl<$Res>;
@useResult
$Res call({DateTime dateFrom, DateTime dateTo});
}
/// @nodoc
class __$$RangeDateChangedImplCopyWithImpl<$Res>
extends _$SalesLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl>
implements _$$RangeDateChangedImplCopyWith<$Res> {
__$$RangeDateChangedImplCopyWithImpl(
_$RangeDateChangedImpl _value,
$Res Function(_$RangeDateChangedImpl) _then,
) : super(_value, _then);
/// Create a copy of SalesLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? dateFrom = null, Object? dateTo = null}) {
return _then(
_$RangeDateChangedImpl(
null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
}
/// @nodoc
class _$RangeDateChangedImpl implements _RangeDateChanged {
const _$RangeDateChangedImpl(this.dateFrom, this.dateTo);
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'SalesLoaderEvent.rangeDateChanged(dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RangeDateChangedImpl &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
int get hashCode => Object.hash(runtimeType, dateFrom, dateTo);
/// Create a copy of SalesLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
__$$RangeDateChangedImplCopyWithImpl<_$RangeDateChangedImpl>(
this,
_$identity,
);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fectched,
}) {
return rangeDateChanged(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fectched,
}) {
return rangeDateChanged?.call(dateFrom, dateTo);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fectched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(dateFrom, dateTo);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fectched value) fectched,
}) {
return rangeDateChanged(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fectched value)? fectched,
}) {
return rangeDateChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fectched value)? fectched,
required TResult orElse(),
}) {
if (rangeDateChanged != null) {
return rangeDateChanged(this);
}
return orElse();
}
}
abstract class _RangeDateChanged implements SalesLoaderEvent {
const factory _RangeDateChanged(
final DateTime dateFrom,
final DateTime dateTo,
) = _$RangeDateChangedImpl;
DateTime get dateFrom;
DateTime get dateTo;
/// Create a copy of SalesLoaderEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$FectchedImplCopyWith<$Res> {
factory _$$FectchedImplCopyWith(
@ -110,6 +275,8 @@ class _$FectchedImpl implements _Fectched {
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(DateTime dateFrom, DateTime dateTo)
rangeDateChanged,
required TResult Function() fectched,
}) {
return fectched();
@ -118,6 +285,7 @@ class _$FectchedImpl implements _Fectched {
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult? Function()? fectched,
}) {
return fectched?.call();
@ -126,6 +294,7 @@ class _$FectchedImpl implements _Fectched {
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
TResult Function()? fectched,
required TResult orElse(),
}) {
@ -138,6 +307,7 @@ class _$FectchedImpl implements _Fectched {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_RangeDateChanged value) rangeDateChanged,
required TResult Function(_Fectched value) fectched,
}) {
return fectched(this);
@ -146,6 +316,7 @@ class _$FectchedImpl implements _Fectched {
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
TResult? Function(_Fectched value)? fectched,
}) {
return fectched?.call(this);
@ -154,6 +325,7 @@ class _$FectchedImpl implements _Fectched {
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_RangeDateChanged value)? rangeDateChanged,
TResult Function(_Fectched value)? fectched,
required TResult orElse(),
}) {
@ -174,6 +346,8 @@ mixin _$SalesLoaderState {
Option<AnalyticFailure> get failureOptionSales =>
throw _privateConstructorUsedError;
bool get isFetching => throw _privateConstructorUsedError;
DateTime get dateFrom => throw _privateConstructorUsedError;
DateTime get dateTo => throw _privateConstructorUsedError;
/// Create a copy of SalesLoaderState
/// with the given fields replaced by the non-null parameter values.
@ -193,6 +367,8 @@ abstract class $SalesLoaderStateCopyWith<$Res> {
SalesAnalytic sales,
Option<AnalyticFailure> failureOptionSales,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
$SalesAnalyticCopyWith<$Res> get sales;
@ -216,6 +392,8 @@ class _$SalesLoaderStateCopyWithImpl<$Res, $Val extends SalesLoaderState>
Object? sales = null,
Object? failureOptionSales = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_value.copyWith(
@ -231,6 +409,14 @@ class _$SalesLoaderStateCopyWithImpl<$Res, $Val extends SalesLoaderState>
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
)
as $Val,
);
@ -260,6 +446,8 @@ abstract class _$$SalesLoaderStateImplCopyWith<$Res>
SalesAnalytic sales,
Option<AnalyticFailure> failureOptionSales,
bool isFetching,
DateTime dateFrom,
DateTime dateTo,
});
@override
@ -283,6 +471,8 @@ class __$$SalesLoaderStateImplCopyWithImpl<$Res>
Object? sales = null,
Object? failureOptionSales = null,
Object? isFetching = null,
Object? dateFrom = null,
Object? dateTo = null,
}) {
return _then(
_$SalesLoaderStateImpl(
@ -298,6 +488,14 @@ class __$$SalesLoaderStateImplCopyWithImpl<$Res>
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
dateFrom: null == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as DateTime,
dateTo: null == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
@ -310,6 +508,8 @@ class _$SalesLoaderStateImpl implements _SalesLoaderState {
required this.sales,
required this.failureOptionSales,
this.isFetching = false,
required this.dateFrom,
required this.dateTo,
});
@override
@ -319,10 +519,14 @@ class _$SalesLoaderStateImpl implements _SalesLoaderState {
@override
@JsonKey()
final bool isFetching;
@override
final DateTime dateFrom;
@override
final DateTime dateTo;
@override
String toString() {
return 'SalesLoaderState(sales: $sales, failureOptionSales: $failureOptionSales, isFetching: $isFetching)';
return 'SalesLoaderState(sales: $sales, failureOptionSales: $failureOptionSales, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
@ -334,12 +538,21 @@ class _$SalesLoaderStateImpl implements _SalesLoaderState {
(identical(other.failureOptionSales, failureOptionSales) ||
other.failureOptionSales == failureOptionSales) &&
(identical(other.isFetching, isFetching) ||
other.isFetching == isFetching));
other.isFetching == isFetching) &&
(identical(other.dateFrom, dateFrom) ||
other.dateFrom == dateFrom) &&
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
}
@override
int get hashCode =>
Object.hash(runtimeType, sales, failureOptionSales, isFetching);
int get hashCode => Object.hash(
runtimeType,
sales,
failureOptionSales,
isFetching,
dateFrom,
dateTo,
);
/// Create a copy of SalesLoaderState
/// with the given fields replaced by the non-null parameter values.
@ -358,6 +571,8 @@ abstract class _SalesLoaderState implements SalesLoaderState {
required final SalesAnalytic sales,
required final Option<AnalyticFailure> failureOptionSales,
final bool isFetching,
required final DateTime dateFrom,
required final DateTime dateTo,
}) = _$SalesLoaderStateImpl;
@override
@ -366,6 +581,10 @@ abstract class _SalesLoaderState implements SalesLoaderState {
Option<AnalyticFailure> get failureOptionSales;
@override
bool get isFetching;
@override
DateTime get dateFrom;
@override
DateTime get dateTo;
/// Create a copy of SalesLoaderState
/// with the given fields replaced by the non-null parameter values.

View File

@ -2,5 +2,9 @@ part of 'sales_loader_bloc.dart';
@freezed
class SalesLoaderEvent with _$SalesLoaderEvent {
const factory SalesLoaderEvent.rangeDateChanged(
DateTime dateFrom,
DateTime dateTo,
) = _RangeDateChanged;
const factory SalesLoaderEvent.fectched() = _Fectched;
}

View File

@ -6,10 +6,14 @@ class SalesLoaderState with _$SalesLoaderState {
required SalesAnalytic sales,
required Option<AnalyticFailure> failureOptionSales,
@Default(false) bool isFetching,
required DateTime dateFrom,
required DateTime dateTo,
}) = _SalesLoaderState;
factory SalesLoaderState.initial() => SalesLoaderState(
sales: SalesAnalytic.empty(),
failureOptionSales: none(),
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateTo: DateTime.now(),
);
}

View File

@ -5972,7 +5972,7 @@ mixin _$ProductAnalyticData {
String get categoryId => throw _privateConstructorUsedError;
String get categoryName => throw _privateConstructorUsedError;
int get quantitySold => throw _privateConstructorUsedError;
double get revenue => throw _privateConstructorUsedError;
int get revenue => throw _privateConstructorUsedError;
double get averagePrice => throw _privateConstructorUsedError;
int get orderCount => throw _privateConstructorUsedError;
@ -5996,7 +5996,7 @@ abstract class $ProductAnalyticDataCopyWith<$Res> {
String categoryId,
String categoryName,
int quantitySold,
double revenue,
int revenue,
double averagePrice,
int orderCount,
});
@ -6051,7 +6051,7 @@ class _$ProductAnalyticDataCopyWithImpl<$Res, $Val extends ProductAnalyticData>
revenue: null == revenue
? _value.revenue
: revenue // ignore: cast_nullable_to_non_nullable
as double,
as int,
averagePrice: null == averagePrice
? _value.averagePrice
: averagePrice // ignore: cast_nullable_to_non_nullable
@ -6081,7 +6081,7 @@ abstract class _$$ProductAnalyticDataImplCopyWith<$Res>
String categoryId,
String categoryName,
int quantitySold,
double revenue,
int revenue,
double averagePrice,
int orderCount,
});
@ -6135,7 +6135,7 @@ class __$$ProductAnalyticDataImplCopyWithImpl<$Res>
revenue: null == revenue
? _value.revenue
: revenue // ignore: cast_nullable_to_non_nullable
as double,
as int,
averagePrice: null == averagePrice
? _value.averagePrice
: averagePrice // ignore: cast_nullable_to_non_nullable
@ -6174,7 +6174,7 @@ class _$ProductAnalyticDataImpl implements _ProductAnalyticData {
@override
final int quantitySold;
@override
final double revenue;
final int revenue;
@override
final double averagePrice;
@override
@ -6239,7 +6239,7 @@ abstract class _ProductAnalyticData implements ProductAnalyticData {
required final String categoryId,
required final String categoryName,
required final int quantitySold,
required final double revenue,
required final int revenue,
required final double averagePrice,
required final int orderCount,
}) = _$ProductAnalyticDataImpl;
@ -6255,7 +6255,7 @@ abstract class _ProductAnalyticData implements ProductAnalyticData {
@override
int get quantitySold;
@override
double get revenue;
int get revenue;
@override
double get averagePrice;
@override

View File

@ -27,7 +27,7 @@ class ProductAnalyticData with _$ProductAnalyticData {
required String categoryId,
required String categoryName,
required int quantitySold,
required double revenue,
required int revenue,
required double averagePrice,
required int orderCount,
}) = _ProductAnalyticData;
@ -38,7 +38,7 @@ class ProductAnalyticData with _$ProductAnalyticData {
categoryId: '',
categoryName: '',
quantitySold: 0,
revenue: 0.0,
revenue: 0,
averagePrice: 0.0,
orderCount: 0,
);

View File

@ -6661,14 +6661,15 @@ ProductAnalyticDto _$ProductAnalyticDtoFromJson(Map<String, dynamic> json) {
/// @nodoc
mixin _$ProductAnalyticDto {
@JsonKey(name: 'organization_id')
String get organizationId => throw _privateConstructorUsedError;
String? get organizationId => throw _privateConstructorUsedError;
@JsonKey(name: 'outlet_id')
String get outletId => throw _privateConstructorUsedError;
String? get outletId => throw _privateConstructorUsedError;
@JsonKey(name: 'date_from')
String get dateFrom => throw _privateConstructorUsedError;
String? get dateFrom => throw _privateConstructorUsedError;
@JsonKey(name: 'date_to')
String get dateTo => throw _privateConstructorUsedError;
List<ProductAnalyticDataDto> get data => throw _privateConstructorUsedError;
String? get dateTo => throw _privateConstructorUsedError;
@JsonKey(name: 'data')
List<ProductAnalyticDataDto>? get data => throw _privateConstructorUsedError;
/// Serializes this ProductAnalyticDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@ -6688,11 +6689,11 @@ abstract class $ProductAnalyticDtoCopyWith<$Res> {
) = _$ProductAnalyticDtoCopyWithImpl<$Res, ProductAnalyticDto>;
@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,
List<ProductAnalyticDataDto> data,
@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: 'data') List<ProductAnalyticDataDto>? data,
});
}
@ -6711,34 +6712,34 @@ class _$ProductAnalyticDtoCopyWithImpl<$Res, $Val extends ProductAnalyticDto>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? organizationId = null,
Object? outletId = null,
Object? dateFrom = null,
Object? dateTo = null,
Object? data = null,
Object? organizationId = freezed,
Object? outletId = freezed,
Object? dateFrom = freezed,
Object? dateTo = freezed,
Object? data = freezed,
}) {
return _then(
_value.copyWith(
organizationId: null == organizationId
organizationId: freezed == organizationId
? _value.organizationId
: organizationId // ignore: cast_nullable_to_non_nullable
as String,
outletId: null == outletId
as String?,
outletId: freezed == outletId
? _value.outletId
: outletId // ignore: cast_nullable_to_non_nullable
as String,
dateFrom: null == dateFrom
as String?,
dateFrom: freezed == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as String,
dateTo: null == dateTo
as String?,
dateTo: freezed == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as String,
data: null == data
as String?,
data: freezed == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as List<ProductAnalyticDataDto>,
as List<ProductAnalyticDataDto>?,
)
as $Val,
);
@ -6755,11 +6756,11 @@ abstract class _$$ProductAnalyticDtoImplCopyWith<$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,
List<ProductAnalyticDataDto> data,
@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: 'data') List<ProductAnalyticDataDto>? data,
});
}
@ -6777,34 +6778,34 @@ class __$$ProductAnalyticDtoImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? organizationId = null,
Object? outletId = null,
Object? dateFrom = null,
Object? dateTo = null,
Object? data = null,
Object? organizationId = freezed,
Object? outletId = freezed,
Object? dateFrom = freezed,
Object? dateTo = freezed,
Object? data = freezed,
}) {
return _then(
_$ProductAnalyticDtoImpl(
organizationId: null == organizationId
organizationId: freezed == organizationId
? _value.organizationId
: organizationId // ignore: cast_nullable_to_non_nullable
as String,
outletId: null == outletId
as String?,
outletId: freezed == outletId
? _value.outletId
: outletId // ignore: cast_nullable_to_non_nullable
as String,
dateFrom: null == dateFrom
as String?,
dateFrom: freezed == dateFrom
? _value.dateFrom
: dateFrom // ignore: cast_nullable_to_non_nullable
as String,
dateTo: null == dateTo
as String?,
dateTo: freezed == dateTo
? _value.dateTo
: dateTo // ignore: cast_nullable_to_non_nullable
as String,
data: null == data
as String?,
data: freezed == data
? _value._data
: data // ignore: cast_nullable_to_non_nullable
as List<ProductAnalyticDataDto>,
as List<ProductAnalyticDataDto>?,
),
);
}
@ -6814,11 +6815,11 @@ class __$$ProductAnalyticDtoImplCopyWithImpl<$Res>
@JsonSerializable()
class _$ProductAnalyticDtoImpl extends _ProductAnalyticDto {
const _$ProductAnalyticDtoImpl({
@JsonKey(name: 'organization_id') required this.organizationId,
@JsonKey(name: 'outlet_id') required this.outletId,
@JsonKey(name: 'date_from') required this.dateFrom,
@JsonKey(name: 'date_to') required this.dateTo,
required final List<ProductAnalyticDataDto> data,
@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: 'data') final List<ProductAnalyticDataDto>? data,
}) : _data = data,
super._();
@ -6827,22 +6828,25 @@ class _$ProductAnalyticDtoImpl extends _ProductAnalyticDto {
@override
@JsonKey(name: 'organization_id')
final String organizationId;
final String? organizationId;
@override
@JsonKey(name: 'outlet_id')
final String outletId;
final String? outletId;
@override
@JsonKey(name: 'date_from')
final String dateFrom;
final String? dateFrom;
@override
@JsonKey(name: 'date_to')
final String dateTo;
final List<ProductAnalyticDataDto> _data;
final String? dateTo;
final List<ProductAnalyticDataDto>? _data;
@override
List<ProductAnalyticDataDto> get data {
@JsonKey(name: 'data')
List<ProductAnalyticDataDto>? get data {
final value = _data;
if (value == null) return null;
if (_data is EqualUnmodifiableListView) return _data;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_data);
return EqualUnmodifiableListView(value);
}
@override
@ -6895,11 +6899,11 @@ class _$ProductAnalyticDtoImpl extends _ProductAnalyticDto {
abstract class _ProductAnalyticDto extends ProductAnalyticDto {
const factory _ProductAnalyticDto({
@JsonKey(name: 'organization_id') required final String organizationId,
@JsonKey(name: 'outlet_id') required final String outletId,
@JsonKey(name: 'date_from') required final String dateFrom,
@JsonKey(name: 'date_to') required final String dateTo,
required final List<ProductAnalyticDataDto> data,
@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: 'data') final List<ProductAnalyticDataDto>? data,
}) = _$ProductAnalyticDtoImpl;
const _ProductAnalyticDto._() : super._();
@ -6908,18 +6912,19 @@ abstract class _ProductAnalyticDto extends ProductAnalyticDto {
@override
@JsonKey(name: 'organization_id')
String get organizationId;
String? get organizationId;
@override
@JsonKey(name: 'outlet_id')
String get outletId;
String? get outletId;
@override
@JsonKey(name: 'date_from')
String get dateFrom;
String? get dateFrom;
@override
@JsonKey(name: 'date_to')
String get dateTo;
String? get dateTo;
@override
List<ProductAnalyticDataDto> get data;
@JsonKey(name: 'data')
List<ProductAnalyticDataDto>? get data;
/// Create a copy of ProductAnalyticDto
/// with the given fields replaced by the non-null parameter values.
@ -6938,20 +6943,21 @@ ProductAnalyticDataDto _$ProductAnalyticDataDtoFromJson(
/// @nodoc
mixin _$ProductAnalyticDataDto {
@JsonKey(name: 'product_id')
String get productId => throw _privateConstructorUsedError;
String? get productId => throw _privateConstructorUsedError;
@JsonKey(name: 'product_name')
String get productName => throw _privateConstructorUsedError;
String? get productName => throw _privateConstructorUsedError;
@JsonKey(name: 'category_id')
String get categoryId => throw _privateConstructorUsedError;
String? get categoryId => throw _privateConstructorUsedError;
@JsonKey(name: 'category_name')
String get categoryName => throw _privateConstructorUsedError;
String? get categoryName => throw _privateConstructorUsedError;
@JsonKey(name: 'quantity_sold')
int get quantitySold => throw _privateConstructorUsedError;
double get revenue => throw _privateConstructorUsedError;
int? get quantitySold => throw _privateConstructorUsedError;
@JsonKey(name: 'revenue')
int? get revenue => throw _privateConstructorUsedError;
@JsonKey(name: 'average_price')
double get averagePrice => throw _privateConstructorUsedError;
double? get averagePrice => throw _privateConstructorUsedError;
@JsonKey(name: 'order_count')
int get orderCount => throw _privateConstructorUsedError;
int? get orderCount => throw _privateConstructorUsedError;
/// Serializes this ProductAnalyticDataDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@ -6971,14 +6977,14 @@ abstract class $ProductAnalyticDataDtoCopyWith<$Res> {
) = _$ProductAnalyticDataDtoCopyWithImpl<$Res, ProductAnalyticDataDto>;
@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,
double revenue,
@JsonKey(name: 'average_price') double averagePrice,
@JsonKey(name: 'order_count') int orderCount,
@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,
});
}
@ -7000,49 +7006,49 @@ class _$ProductAnalyticDataDtoCopyWithImpl<
@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,
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: null == productId
productId: freezed == productId
? _value.productId
: productId // ignore: cast_nullable_to_non_nullable
as String,
productName: null == productName
as String?,
productName: freezed == productName
? _value.productName
: productName // ignore: cast_nullable_to_non_nullable
as String,
categoryId: null == categoryId
as String?,
categoryId: freezed == categoryId
? _value.categoryId
: categoryId // ignore: cast_nullable_to_non_nullable
as String,
categoryName: null == categoryName
as String?,
categoryName: freezed == categoryName
? _value.categoryName
: categoryName // ignore: cast_nullable_to_non_nullable
as String,
quantitySold: null == quantitySold
as String?,
quantitySold: freezed == quantitySold
? _value.quantitySold
: quantitySold // ignore: cast_nullable_to_non_nullable
as int,
revenue: null == revenue
as int?,
revenue: freezed == revenue
? _value.revenue
: revenue // ignore: cast_nullable_to_non_nullable
as double,
averagePrice: null == averagePrice
as int?,
averagePrice: freezed == averagePrice
? _value.averagePrice
: averagePrice // ignore: cast_nullable_to_non_nullable
as double,
orderCount: null == orderCount
as double?,
orderCount: freezed == orderCount
? _value.orderCount
: orderCount // ignore: cast_nullable_to_non_nullable
as int,
as int?,
)
as $Val,
);
@ -7059,14 +7065,14 @@ abstract class _$$ProductAnalyticDataDtoImplCopyWith<$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,
double revenue,
@JsonKey(name: 'average_price') double averagePrice,
@JsonKey(name: 'order_count') int orderCount,
@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,
});
}
@ -7085,49 +7091,49 @@ class __$$ProductAnalyticDataDtoImplCopyWithImpl<$Res>
@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,
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(
_$ProductAnalyticDataDtoImpl(
productId: null == productId
productId: freezed == productId
? _value.productId
: productId // ignore: cast_nullable_to_non_nullable
as String,
productName: null == productName
as String?,
productName: freezed == productName
? _value.productName
: productName // ignore: cast_nullable_to_non_nullable
as String,
categoryId: null == categoryId
as String?,
categoryId: freezed == categoryId
? _value.categoryId
: categoryId // ignore: cast_nullable_to_non_nullable
as String,
categoryName: null == categoryName
as String?,
categoryName: freezed == categoryName
? _value.categoryName
: categoryName // ignore: cast_nullable_to_non_nullable
as String,
quantitySold: null == quantitySold
as String?,
quantitySold: freezed == quantitySold
? _value.quantitySold
: quantitySold // ignore: cast_nullable_to_non_nullable
as int,
revenue: null == revenue
as int?,
revenue: freezed == revenue
? _value.revenue
: revenue // ignore: cast_nullable_to_non_nullable
as double,
averagePrice: null == averagePrice
as int?,
averagePrice: freezed == averagePrice
? _value.averagePrice
: averagePrice // ignore: cast_nullable_to_non_nullable
as double,
orderCount: null == orderCount
as double?,
orderCount: freezed == orderCount
? _value.orderCount
: orderCount // ignore: cast_nullable_to_non_nullable
as int,
as int?,
),
);
}
@ -7137,14 +7143,14 @@ class __$$ProductAnalyticDataDtoImplCopyWithImpl<$Res>
@JsonSerializable()
class _$ProductAnalyticDataDtoImpl extends _ProductAnalyticDataDto {
const _$ProductAnalyticDataDtoImpl({
@JsonKey(name: 'product_id') required this.productId,
@JsonKey(name: 'product_name') required this.productName,
@JsonKey(name: 'category_id') required this.categoryId,
@JsonKey(name: 'category_name') required this.categoryName,
@JsonKey(name: 'quantity_sold') required this.quantitySold,
required this.revenue,
@JsonKey(name: 'average_price') required this.averagePrice,
@JsonKey(name: 'order_count') required this.orderCount,
@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 _$ProductAnalyticDataDtoImpl.fromJson(Map<String, dynamic> json) =>
@ -7152,27 +7158,28 @@ class _$ProductAnalyticDataDtoImpl extends _ProductAnalyticDataDto {
@override
@JsonKey(name: 'product_id')
final String productId;
final String? productId;
@override
@JsonKey(name: 'product_name')
final String productName;
final String? productName;
@override
@JsonKey(name: 'category_id')
final String categoryId;
final String? categoryId;
@override
@JsonKey(name: 'category_name')
final String categoryName;
final String? categoryName;
@override
@JsonKey(name: 'quantity_sold')
final int quantitySold;
final int? quantitySold;
@override
final double revenue;
@JsonKey(name: 'revenue')
final int? revenue;
@override
@JsonKey(name: 'average_price')
final double averagePrice;
final double? averagePrice;
@override
@JsonKey(name: 'order_count')
final int orderCount;
final int? orderCount;
@override
String toString() {
@ -7235,14 +7242,14 @@ class _$ProductAnalyticDataDtoImpl extends _ProductAnalyticDataDto {
abstract class _ProductAnalyticDataDto extends ProductAnalyticDataDto {
const factory _ProductAnalyticDataDto({
@JsonKey(name: 'product_id') required final String productId,
@JsonKey(name: 'product_name') required final String productName,
@JsonKey(name: 'category_id') required final String categoryId,
@JsonKey(name: 'category_name') required final String categoryName,
@JsonKey(name: 'quantity_sold') required final int quantitySold,
required final double revenue,
@JsonKey(name: 'average_price') required final double averagePrice,
@JsonKey(name: 'order_count') required final int orderCount,
@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,
}) = _$ProductAnalyticDataDtoImpl;
const _ProductAnalyticDataDto._() : super._();
@ -7251,27 +7258,28 @@ abstract class _ProductAnalyticDataDto extends ProductAnalyticDataDto {
@override
@JsonKey(name: 'product_id')
String get productId;
String? get productId;
@override
@JsonKey(name: 'product_name')
String get productName;
String? get productName;
@override
@JsonKey(name: 'category_id')
String get categoryId;
String? get categoryId;
@override
@JsonKey(name: 'category_name')
String get categoryName;
String? get categoryName;
@override
@JsonKey(name: 'quantity_sold')
int get quantitySold;
int? get quantitySold;
@override
double get revenue;
@JsonKey(name: 'revenue')
int? get revenue;
@override
@JsonKey(name: 'average_price')
double get averagePrice;
double? get averagePrice;
@override
@JsonKey(name: 'order_count')
int get orderCount;
int? get orderCount;
/// Create a copy of ProductAnalyticDataDto
/// with the given fields replaced by the non-null parameter values.

View File

@ -521,12 +521,12 @@ Map<String, dynamic> _$$DashboardRecentSaleDtoImplToJson(
_$ProductAnalyticDtoImpl _$$ProductAnalyticDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProductAnalyticDtoImpl(
organizationId: json['organization_id'] as String,
outletId: json['outlet_id'] as String,
dateFrom: json['date_from'] as String,
dateTo: json['date_to'] as String,
data: (json['data'] as List<dynamic>)
.map((e) => ProductAnalyticDataDto.fromJson(e as Map<String, dynamic>))
organizationId: json['organization_id'] as String?,
outletId: json['outlet_id'] as String?,
dateFrom: json['date_from'] as String?,
dateTo: json['date_to'] as String?,
data: (json['data'] as List<dynamic>?)
?.map((e) => ProductAnalyticDataDto.fromJson(e as Map<String, dynamic>))
.toList(),
);
@ -543,14 +543,14 @@ Map<String, dynamic> _$$ProductAnalyticDtoImplToJson(
_$ProductAnalyticDataDtoImpl _$$ProductAnalyticDataDtoImplFromJson(
Map<String, dynamic> json,
) => _$ProductAnalyticDataDtoImpl(
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).toDouble(),
averagePrice: (json['average_price'] as num).toDouble(),
orderCount: (json['order_count'] as num).toInt(),
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<String, dynamic> _$$ProductAnalyticDataDtoImplToJson(

View File

@ -5,22 +5,22 @@ class ProductAnalyticDto with _$ProductAnalyticDto {
const ProductAnalyticDto._();
const factory ProductAnalyticDto({
@JsonKey(name: 'organization_id') required String organizationId,
@JsonKey(name: 'outlet_id') required String outletId,
@JsonKey(name: 'date_from') required String dateFrom,
@JsonKey(name: 'date_to') required String dateTo,
required List<ProductAnalyticDataDto> data,
@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: 'data') List<ProductAnalyticDataDto>? data,
}) = _ProductAnalyticDto;
factory ProductAnalyticDto.fromJson(Map<String, dynamic> json) =>
_$ProductAnalyticDtoFromJson(json);
ProductAnalytic toDomain() => ProductAnalytic(
organizationId: organizationId,
outletId: outletId,
dateFrom: dateFrom,
dateTo: dateTo,
data: data.map((e) => e.toDomain()).toList(),
organizationId: organizationId ?? "",
outletId: outletId ?? "",
dateFrom: dateFrom ?? "",
dateTo: dateTo ?? "",
data: data?.map((e) => e.toDomain()).toList() ?? [],
);
}
@ -29,27 +29,27 @@ class ProductAnalyticDataDto with _$ProductAnalyticDataDto {
const ProductAnalyticDataDto._();
const factory ProductAnalyticDataDto({
@JsonKey(name: 'product_id') required String productId,
@JsonKey(name: 'product_name') required String productName,
@JsonKey(name: 'category_id') required String categoryId,
@JsonKey(name: 'category_name') required String categoryName,
@JsonKey(name: 'quantity_sold') required int quantitySold,
required double revenue,
@JsonKey(name: 'average_price') required double averagePrice,
@JsonKey(name: 'order_count') required int orderCount,
@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,
}) = _ProductAnalyticDataDto;
factory ProductAnalyticDataDto.fromJson(Map<String, dynamic> json) =>
_$ProductAnalyticDataDtoFromJson(json);
ProductAnalyticData toDomain() => ProductAnalyticData(
productId: productId,
productName: productName,
categoryId: categoryId,
categoryName: categoryName,
quantitySold: quantitySold,
revenue: revenue,
averagePrice: averagePrice,
orderCount: orderCount,
productId: productId ?? "",
productName: productName ?? "",
categoryId: categoryId ?? "",
categoryName: categoryName ?? "",
quantitySold: quantitySold ?? 0,
revenue: revenue ?? 0,
averagePrice: averagePrice ?? 0,
orderCount: orderCount ?? 0,
);
}

View File

@ -130,6 +130,9 @@ extension GetItInjectableX on _i174.GetIt {
() => _i115.ApiClient(gh<_i361.Dio>(), gh<_i6.Env>()),
);
gh.factory<_i6.Env>(() => _i6.ProdEnv(), registerFor: {_prod});
gh.factory<_i130.OrderRemoteDataProvider>(
() => _i130.OrderRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i333.CategoryRemoteDataProvider>(
() => _i333.CategoryRemoteDataProvider(gh<_i115.ApiClient>()),
);
@ -145,9 +148,6 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i1006.CustomerRemoteDataProvider>(
() => _i1006.CustomerRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i130.OrderRemoteDataProvider>(
() => _i130.OrderRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i48.ICustomerRepository>(
() => _i550.CustomerRepository(gh<_i1006.CustomerRemoteDataProvider>()),
);
@ -184,26 +184,26 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i889.SalesLoaderBloc>(
() => _i889.SalesLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i11.ProfitLossLoaderBloc>(
() => _i11.ProfitLossLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i1038.CategoryAnalyticLoaderBloc>(
() => _i1038.CategoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
gh.factory<_i221.ProductAnalyticLoaderBloc>(
() => _i221.ProductAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i785.InventoryAnalyticLoaderBloc>(
() => _i785.InventoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i516.DashboardAnalyticLoaderBloc>(
() => _i516.DashboardAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i221.ProductAnalyticLoaderBloc>(
() => _i221.ProductAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i552.PaymentMethodAnalyticLoaderBloc>(
() => _i552.PaymentMethodAnalyticLoaderBloc(
gh<_i477.IAnalyticRepository>(),
),
);
gh.factory<_i1038.CategoryAnalyticLoaderBloc>(
() => _i1038.CategoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i11.ProfitLossLoaderBloc>(
() => _i11.ProfitLossLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i516.DashboardAnalyticLoaderBloc>(
() => _i516.DashboardAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i775.LoginFormBloc>(
() => _i775.LoginFormBloc(gh<_i49.IAuthRepository>()),
);

View File

@ -0,0 +1,363 @@
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
class DateRangePickerBottomSheet {
static Future<DateRangePickerSelectionChangedArgs?> show({
required BuildContext context,
String title = 'Pilih Rentang Tanggal',
DateTime? initialStartDate,
DateTime? initialEndDate,
DateTime? minDate,
DateTime? maxDate,
String confirmText = 'Pilih',
String cancelText = 'Batal',
Color primaryColor = Colors.blue,
Function(DateTime? startDate, DateTime? endDate)? onChanged,
}) async {
return await showModalBottomSheet<DateRangePickerSelectionChangedArgs?>(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
isDismissible: false,
enableDrag: false,
builder: (BuildContext context) => _DateRangePickerBottomSheet(
title: title,
initialStartDate: initialStartDate,
initialEndDate: initialEndDate,
minDate: minDate,
maxDate: maxDate,
confirmText: confirmText,
cancelText: cancelText,
primaryColor: primaryColor,
onChanged: onChanged,
),
);
}
}
class _DateRangePickerBottomSheet extends StatefulWidget {
final String title;
final DateTime? initialStartDate;
final DateTime? initialEndDate;
final DateTime? minDate;
final DateTime? maxDate;
final String confirmText;
final String cancelText;
final Color primaryColor;
final Function(DateTime? startDate, DateTime? endDate)? onChanged;
const _DateRangePickerBottomSheet({
required this.title,
this.initialStartDate,
this.initialEndDate,
this.minDate,
this.maxDate,
required this.confirmText,
required this.cancelText,
required this.primaryColor,
this.onChanged,
});
@override
State<_DateRangePickerBottomSheet> createState() =>
_DateRangePickerBottomSheetState();
}
class _DateRangePickerBottomSheetState
extends State<_DateRangePickerBottomSheet>
with TickerProviderStateMixin {
DateRangePickerSelectionChangedArgs? _selectionChangedArgs;
late AnimationController _animationController;
late Animation<double> _slideAnimation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
_slideAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
CurvedAnimation(parent: _animationController, curve: Curves.easeOutCubic),
);
_animationController.forward();
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _onSelectionChanged(DateRangePickerSelectionChangedArgs args) {
setState(() {
_selectionChangedArgs = args;
});
}
String _getSelectionText() {
if (_selectionChangedArgs?.value is PickerDateRange) {
final PickerDateRange range = _selectionChangedArgs!.value;
if (range.startDate != null && range.endDate != null) {
return '${_formatDate(range.startDate!)} - ${_formatDate(range.endDate!)}';
} else if (range.startDate != null) {
return _formatDate(range.startDate!);
}
}
return 'Belum ada tanggal dipilih';
}
String _formatDate(DateTime date) {
final months = [
'Jan',
'Feb',
'Mar',
'Apr',
'Mei',
'Jun',
'Jul',
'Agu',
'Sep',
'Okt',
'Nov',
'Des',
];
return '${date.day} ${months[date.month - 1]} ${date.year}';
}
bool get _isValidSelection {
if (_selectionChangedArgs?.value is PickerDateRange) {
final PickerDateRange range = _selectionChangedArgs!.value;
return range.startDate != null && range.endDate != null;
}
return false;
}
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
final bottomSheetHeight = screenHeight * 0.75;
return AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return Transform.translate(
offset: Offset(0, _slideAnimation.value * bottomSheetHeight),
child: Container(
height: bottomSheetHeight,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Drag Handle
Container(
margin: const EdgeInsets.only(top: 12, bottom: 8),
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(2),
),
),
// Content
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
children: [
// Selection Info
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: widget.primaryColor.withOpacity(0.08),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: widget.primaryColor.withOpacity(0.2),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tanggal Terpilih:',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: widget.primaryColor,
),
),
const SizedBox(height: 6),
Text(
_getSelectionText(),
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
),
],
),
),
const SizedBox(height: 20),
// Date Picker
Container(
height: 320,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.grey.withOpacity(0.2),
),
),
child: SfDateRangePicker(
onSelectionChanged: _onSelectionChanged,
selectionMode: DateRangePickerSelectionMode.range,
initialSelectedRange:
(widget.initialStartDate != null &&
widget.initialEndDate != null)
? PickerDateRange(
widget.initialStartDate,
widget.initialEndDate,
)
: null,
minDate: widget.minDate,
maxDate: widget.maxDate,
startRangeSelectionColor: widget.primaryColor,
endRangeSelectionColor: widget.primaryColor,
rangeSelectionColor: widget.primaryColor
.withOpacity(0.2),
todayHighlightColor: widget.primaryColor,
headerStyle: DateRangePickerHeaderStyle(
backgroundColor: Colors.transparent,
textAlign: TextAlign.center,
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
monthViewSettings: DateRangePickerMonthViewSettings(
viewHeaderStyle: DateRangePickerViewHeaderStyle(
backgroundColor: Colors.grey.withOpacity(0.1),
textStyle: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: widget.primaryColor,
),
),
),
selectionTextStyle: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14,
),
rangeTextStyle: TextStyle(
color: widget.primaryColor,
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
),
],
),
),
),
// Bottom Fixed Action Buttons
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
border: Border(
top: BorderSide(
color: Colors.grey.withOpacity(0.2),
width: 1,
),
),
),
child: SafeArea(
child: Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () => Navigator.of(context).pop(),
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
side: BorderSide(color: Colors.grey.shade400),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: Text(
widget.cancelText,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: Colors.grey,
),
),
),
),
const SizedBox(width: 16),
Expanded(
child: ElevatedButton(
onPressed: _isValidSelection
? () {
// Call onChanged when confirm button is pressed
if (widget.onChanged != null &&
_selectionChangedArgs?.value
is PickerDateRange) {
final PickerDateRange range =
_selectionChangedArgs!.value;
widget.onChanged!(
range.startDate,
range.endDate,
);
}
Navigator.of(
context,
).pop(_selectionChangedArgs);
}
: null,
style: ElevatedButton.styleFrom(
backgroundColor: widget.primaryColor,
padding: const EdgeInsets.symmetric(vertical: 16),
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
disabledBackgroundColor: Colors.grey.shade300,
),
child: Text(
widget.confirmText,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: _isValidSelection
? Colors.white
: Colors.grey.shade600,
),
),
),
),
],
),
),
),
],
),
),
);
},
);
}
}

View File

@ -0,0 +1,531 @@
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
import '../../../common/theme/theme.dart';
import '../bottom_sheet/date_range_bottom_sheet.dart';
class DateRangePickerField extends StatefulWidget {
final String? label;
final String placeholder;
final DateTime? startDate;
final DateTime? endDate;
final DateTime? minDate;
final DateTime? maxDate;
final Function(DateTime? startDate, DateTime? endDate)? onChanged;
final Color primaryColor;
final bool enabled;
final String? errorText;
final EdgeInsetsGeometry? padding;
final TextStyle? textStyle;
final TextStyle? placeholderStyle;
final BoxDecoration? decoration;
final double height;
const DateRangePickerField({
Key? key,
this.label,
this.placeholder = 'Pilih rentang tanggal',
this.startDate,
this.endDate,
this.minDate,
this.maxDate,
this.onChanged,
this.primaryColor = AppColor.primary,
this.enabled = true,
this.errorText,
this.padding,
this.textStyle,
this.placeholderStyle,
this.decoration,
this.height = 52.0,
}) : super(key: key);
@override
State<DateRangePickerField> createState() => _DateRangePickerFieldState();
}
class _DateRangePickerFieldState extends State<DateRangePickerField> {
bool _isPressed = false;
String get _displayText {
if (widget.startDate != null && widget.endDate != null) {
return '${_formatDate(widget.startDate!)} - ${_formatDate(widget.endDate!)}';
} else if (widget.startDate != null) {
return _formatDate(widget.startDate!);
}
return widget.placeholder;
}
bool get _hasValue {
return widget.startDate != null || widget.endDate != null;
}
String _formatDate(DateTime date) {
final months = [
'Jan',
'Feb',
'Mar',
'Apr',
'Mei',
'Jun',
'Jul',
'Agu',
'Sep',
'Okt',
'Nov',
'Des',
];
return '${date.day} ${months[date.month - 1]} ${date.year}';
}
Future<void> _showDateRangePicker() async {
if (!widget.enabled) return;
final result = await DateRangePickerBottomSheet.show(
context: context,
title: widget.label ?? 'Pilih Rentang Tanggal',
initialStartDate: widget.startDate,
initialEndDate: widget.endDate,
minDate: widget.minDate,
maxDate: widget.maxDate,
primaryColor: widget.primaryColor,
onChanged: widget.onChanged,
);
if (result != null && widget.onChanged != null) {
if (result.value is PickerDateRange) {
final PickerDateRange range = result.value;
widget.onChanged!(range.startDate, range.endDate);
}
}
}
@override
Widget build(BuildContext context) {
final hasError = widget.errorText != null && widget.errorText!.isNotEmpty;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
// Label
if (widget.label != null) ...[
Text(
widget.label!,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: hasError ? AppColor.error : AppColor.textSecondary,
),
),
const SizedBox(height: 8),
],
// Input Field
GestureDetector(
onTap: _showDateRangePicker,
onTapDown: widget.enabled
? (_) => setState(() => _isPressed = true)
: null,
onTapUp: widget.enabled
? (_) => setState(() => _isPressed = false)
: null,
onTapCancel: widget.enabled
? () => setState(() => _isPressed = false)
: null,
child: AnimatedContainer(
duration: const Duration(milliseconds: 150),
height: widget.height,
padding:
widget.padding ?? const EdgeInsets.symmetric(horizontal: 16),
decoration:
widget.decoration ??
BoxDecoration(
color: widget.enabled
? (_isPressed ? AppColor.backgroundLight : AppColor.white)
: AppColor.background,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: hasError
? AppColor.error
: (_isPressed ? widget.primaryColor : AppColor.border),
width: _isPressed ? 2 : 1,
),
boxShadow: _isPressed && widget.enabled
? [
BoxShadow(
color: widget.primaryColor.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
]
: null,
),
child: Row(
children: [
// Date Text
Expanded(
child: Text(
_displayText,
style:
widget.textStyle ??
TextStyle(
fontSize: 15,
fontWeight: _hasValue
? FontWeight.w500
: FontWeight.w400,
color: widget.enabled
? (_hasValue
? AppColor.textPrimary
: AppColor.textSecondary)
: AppColor.textLight,
),
),
),
// Calendar Icon
Container(
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
color: widget.primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
Icons.calendar_today_rounded,
size: 20,
color: widget.enabled
? widget.primaryColor
: AppColor.textLight,
),
),
],
),
),
),
// Error Text
if (hasError) ...[
const SizedBox(height: 6),
Text(
widget.errorText!,
style: TextStyle(
fontSize: 12,
color: AppColor.error,
fontWeight: FontWeight.w400,
),
),
],
],
);
}
}
// Variasi dengan style yang berbeda
class DateRangePickerFieldOutlined extends StatefulWidget {
final String? label;
final String placeholder;
final DateTime? startDate;
final DateTime? endDate;
final DateTime? minDate;
final DateTime? maxDate;
final Function(DateTime? startDate, DateTime? endDate)? onChanged;
final Color primaryColor;
final bool enabled;
final String? errorText;
const DateRangePickerFieldOutlined({
Key? key,
this.label,
this.placeholder = 'Pilih rentang tanggal',
this.startDate,
this.endDate,
this.minDate,
this.maxDate,
this.onChanged,
this.primaryColor = AppColor.primary,
this.enabled = true,
this.errorText,
}) : super(key: key);
@override
State<DateRangePickerFieldOutlined> createState() =>
_DateRangePickerFieldOutlinedState();
}
class _DateRangePickerFieldOutlinedState
extends State<DateRangePickerFieldOutlined> {
bool _isFocused = false;
String get _displayText {
if (widget.startDate != null && widget.endDate != null) {
return '${_formatDate(widget.startDate!)} - ${_formatDate(widget.endDate!)}';
} else if (widget.startDate != null) {
return _formatDate(widget.startDate!);
}
return widget.placeholder;
}
bool get _hasValue {
return widget.startDate != null || widget.endDate != null;
}
String _formatDate(DateTime date) {
final months = [
'Jan',
'Feb',
'Mar',
'Apr',
'Mei',
'Jun',
'Jul',
'Agu',
'Sep',
'Okt',
'Nov',
'Des',
];
return '${date.day} ${months[date.month - 1]} ${date.year}';
}
Future<void> _showDateRangePicker() async {
if (!widget.enabled) return;
setState(() => _isFocused = true);
final result = await DateRangePickerBottomSheet.show(
context: context,
title: widget.label ?? 'Pilih Rentang Tanggal',
initialStartDate: widget.startDate,
initialEndDate: widget.endDate,
minDate: widget.minDate,
maxDate: widget.maxDate,
primaryColor: widget.primaryColor,
onChanged: widget.onChanged,
);
setState(() => _isFocused = false);
if (result != null && widget.onChanged != null) {
if (result.value is PickerDateRange) {
final PickerDateRange range = result.value;
widget.onChanged!(range.startDate, range.endDate);
}
}
}
@override
Widget build(BuildContext context) {
final hasError = widget.errorText != null && widget.errorText!.isNotEmpty;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: _showDateRangePicker,
child: Container(
height: 56,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: hasError
? AppColor.error
: (_isFocused || _hasValue
? widget.primaryColor
: AppColor.border),
width: _isFocused ? 2 : 1,
),
),
child: Row(
children: [
const SizedBox(width: 16),
// Date Text
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (widget.label != null && (_isFocused || _hasValue))
Text(
widget.label!,
style: TextStyle(
fontSize: 12,
color: hasError
? AppColor.error
: widget.primaryColor,
fontWeight: FontWeight.w500,
),
),
Text(
_hasValue
? _displayText
: (widget.label ?? widget.placeholder),
style: TextStyle(
fontSize: _hasValue ? 16 : 16,
fontWeight: FontWeight.w400,
color: widget.enabled
? (_hasValue
? AppColor.textPrimary
: AppColor.textSecondary)
: AppColor.textLight,
),
),
],
),
),
// Calendar Icon
Padding(
padding: const EdgeInsets.only(right: 16),
child: Icon(
Icons.calendar_today_rounded,
size: 24,
color: widget.enabled
? (_isFocused
? widget.primaryColor
: AppColor.textSecondary)
: AppColor.textLight,
),
),
],
),
),
),
// Error Text
if (hasError) ...[
const SizedBox(height: 6),
Padding(
padding: const EdgeInsets.only(left: 16),
child: Text(
widget.errorText!,
style: TextStyle(
fontSize: 12,
color: AppColor.error,
fontWeight: FontWeight.w400,
),
),
),
],
],
);
}
}
// Usage Example Widget
class DateRangePickerExample extends StatefulWidget {
@override
_DateRangePickerExampleState createState() => _DateRangePickerExampleState();
}
class _DateRangePickerExampleState extends State<DateRangePickerExample> {
DateTime? _startDate;
DateTime? _endDate;
DateTime? _startDate2;
DateTime? _endDate2;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Date Range Picker Example'),
backgroundColor: AppColor.primary,
foregroundColor: AppColor.white,
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Default Style',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColor.textPrimary,
),
),
const SizedBox(height: 16),
DateRangePickerField(
label: 'Periode Laporan',
placeholder: 'Pilih tanggal mulai - selesai',
startDate: _startDate,
endDate: _endDate,
primaryColor: AppColor.primary,
onChanged: (start, end) {
setState(() {
_startDate = start;
_endDate = end;
});
},
),
const SizedBox(height: 32),
Text(
'Outlined Style',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColor.textPrimary,
),
),
const SizedBox(height: 16),
DateRangePickerFieldOutlined(
label: 'Rentang Waktu',
placeholder: 'Pilih rentang tanggal',
startDate: _startDate2,
endDate: _endDate2,
primaryColor: AppColor.secondary,
onChanged: (start, end) {
setState(() {
_startDate2 = start;
_endDate2 = end;
});
},
),
const SizedBox(height: 24),
// Display selected dates
if (_startDate != null ||
_endDate != null ||
_startDate2 != null ||
_endDate2 != null)
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColor.background,
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Selected Dates:',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
const SizedBox(height: 8),
if (_startDate != null)
Text(
'Default: ${_startDate!} - ${_endDate ?? 'Not selected'}',
),
if (_startDate2 != null)
Text(
'Outlined: ${_startDate2!} - ${_endDate2 ?? 'Not selected'}',
),
],
),
),
],
),
),
);
}
}

View File

@ -10,6 +10,7 @@ import '../../../common/theme/theme.dart';
import '../../../domain/analytic/analytic.dart';
import '../../../injection.dart';
import '../../components/appbar/appbar.dart';
import '../../components/field/date_range_picker_field.dart';
import 'widgets/cash_flow.dart';
import 'widgets/category.dart';
import 'widgets/product.dart';
@ -50,14 +51,6 @@ class _FinancePageState extends State<FinancePage>
late Animation<double> _fadeAnimation;
late Animation<double> _scaleAnimation;
String selectedPeriod = 'Hari ini';
final List<String> periods = [
'Hari ini',
'Minggu ini',
'Bulan ini',
'Tahun ini',
];
@override
void initState() {
super.initState();
@ -113,136 +106,108 @@ class _FinancePageState extends State<FinancePage>
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.background,
body: BlocBuilder<ProfitLossLoaderBloc, ProfitLossLoaderState>(
builder: (context, state) {
return CustomScrollView(
slivers: [
// SliverAppBar with animated background
SliverAppBar(
expandedHeight: 120,
floating: false,
pinned: true,
backgroundColor: AppColor.primary,
elevation: 0,
flexibleSpace: CustomAppBar(title: 'Keuangan'),
),
// Header dengan filter periode
SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
child: _buildPeriodSelector(),
),
),
// Summary Cards
SliverToBoxAdapter(
child: SlideTransition(
position: _slideAnimation,
child: _buildSummaryCards(state.profitLoss.summary),
),
),
// Cash Flow Analysis
SliverToBoxAdapter(
child: ScaleTransition(
scale: _scaleAnimation,
child: FinanceCashFlow(dailyData: state.profitLoss.data),
),
),
// Profit Loss Detail
SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
child: FinanceProfitLoss(data: state.profitLoss.summary),
),
),
BlocBuilder<
CategoryAnalyticLoaderBloc,
CategoryAnalyticLoaderState
>(
builder: (context, stateCategory) {
return SliverToBoxAdapter(
child: SlideTransition(
position: _slideAnimation,
child: FinanceCategory(
categories: stateCategory.categoryAnalytic.data,
),
),
);
},
),
// Product Analysis Section
SliverToBoxAdapter(
child: SlideTransition(
position: _slideAnimation,
child: _buildProductAnalysis(state.profitLoss.productData),
),
),
// Transaction Categories
// Bottom spacing
const SliverToBoxAdapter(child: SizedBox(height: 100)),
],
body: BlocListener<ProfitLossLoaderBloc, ProfitLossLoaderState>(
listenWhen: (previous, current) =>
previous.dateFrom != current.dateFrom ||
previous.dateTo != current.dateTo,
listener: (context, state) {
context.read<ProfitLossLoaderBloc>().add(
ProfitLossLoaderEvent.fetched(),
);
},
),
);
}
child: BlocBuilder<ProfitLossLoaderBloc, ProfitLossLoaderState>(
builder: (context, state) {
return CustomScrollView(
slivers: [
// SliverAppBar with animated background
SliverAppBar(
expandedHeight: 120,
floating: false,
pinned: true,
backgroundColor: AppColor.primary,
elevation: 0,
flexibleSpace: CustomAppBar(title: 'Keuangan'),
),
Widget _buildPeriodSelector() {
return Container(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: AppColor.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColor.border),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: selectedPeriod,
isExpanded: true,
icon: const Icon(
LineIcons.angleDown,
color: AppColor.primary,
// Header dengan filter periode
SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: DateRangePickerField(
maxDate: DateTime.now(),
startDate: state.dateFrom,
endDate: state.dateTo,
onChanged: (startDate, endDate) {
context.read<ProfitLossLoaderBloc>().add(
ProfitLossLoaderEvent.rangeDateChanged(
startDate!,
endDate!,
),
);
},
),
),
),
style: AppStyle.md,
items: periods.map((String period) {
return DropdownMenuItem<String>(
value: period,
child: Text(period),
),
// Summary Cards
SliverToBoxAdapter(
child: SlideTransition(
position: _slideAnimation,
child: _buildSummaryCards(state.profitLoss.summary),
),
),
// Cash Flow Analysis
SliverToBoxAdapter(
child: ScaleTransition(
scale: _scaleAnimation,
child: FinanceCashFlow(dailyData: state.profitLoss.data),
),
),
// Profit Loss Detail
SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
child: FinanceProfitLoss(data: state.profitLoss.summary),
),
),
BlocBuilder<
CategoryAnalyticLoaderBloc,
CategoryAnalyticLoaderState
>(
builder: (context, stateCategory) {
return SliverToBoxAdapter(
child: SlideTransition(
position: _slideAnimation,
child: FinanceCategory(
categories: stateCategory.categoryAnalytic.data,
),
),
);
}).toList(),
onChanged: (String? newValue) {
setState(() {
selectedPeriod = newValue!;
});
},
),
),
),
),
const SizedBox(width: 12),
Container(
decoration: BoxDecoration(
color: AppColor.primary,
borderRadius: BorderRadius.circular(12),
),
child: IconButton(
onPressed: () {},
icon: const Icon(LineIcons.calendar, color: AppColor.white),
),
),
],
// Product Analysis Section
SliverToBoxAdapter(
child: SlideTransition(
position: _slideAnimation,
child: _buildProductAnalysis(state.profitLoss.productData),
),
),
// Transaction Categories
// Bottom spacing
const SliverToBoxAdapter(child: SizedBox(height: 100)),
],
);
},
),
),
);
}

View File

@ -107,120 +107,143 @@ class _InventoryPageState extends State<InventoryPage>
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.background,
body:
BlocBuilder<
InventoryAnalyticLoaderBloc,
InventoryAnalyticLoaderState
>(
builder: (context, state) {
return FadeTransition(
opacity: _fadeAnimation,
child: SlideTransition(
position: _slideAnimation,
child: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
_buildSliverAppBar(),
SliverPersistentHeader(
pinned: true,
delegate: InventorySliverTabBarDelegate(
tabBar: TabBar(
controller: _tabController,
indicator: BoxDecoration(
gradient: LinearGradient(
colors: AppColor.primaryGradient,
begin: Alignment.topLeft,
end: Alignment.bottomRight,
return BlocListener<
InventoryAnalyticLoaderBloc,
InventoryAnalyticLoaderState
>(
listenWhen: (previous, current) =>
previous.dateFrom != current.dateFrom ||
previous.dateTo != current.dateTo,
listener: (context, state) {
context.read<InventoryAnalyticLoaderBloc>().add(
InventoryAnalyticLoaderEvent.fetched(),
);
},
child: Scaffold(
backgroundColor: AppColor.background,
body:
BlocBuilder<
InventoryAnalyticLoaderBloc,
InventoryAnalyticLoaderState
>(
builder: (context, state) {
return FadeTransition(
opacity: _fadeAnimation,
child: SlideTransition(
position: _slideAnimation,
child: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
_buildSliverAppBar(),
SliverPersistentHeader(
pinned: true,
delegate: InventorySliverTabBarDelegate(
startDate: state.dateFrom,
endDate: state.dateTo,
onDateRangeChanged: (startDate, endDate) {
context.read<InventoryAnalyticLoaderBloc>().add(
InventoryAnalyticLoaderEvent.rangeDateChanged(
startDate!,
endDate!,
),
);
},
tabBar: TabBar(
controller: _tabController,
indicator: BoxDecoration(
gradient: LinearGradient(
colors: AppColor.primaryGradient,
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: AppColor.primary.withOpacity(0.3),
blurRadius: 12,
offset: const Offset(0, 4),
),
],
),
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: AppColor.primary.withOpacity(0.3),
blurRadius: 12,
offset: const Offset(0, 4),
indicatorSize: TabBarIndicatorSize.tab,
indicatorPadding: const EdgeInsets.all(6),
labelColor: AppColor.textWhite,
unselectedLabelColor: AppColor.textSecondary,
labelStyle: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 13,
),
unselectedLabelStyle: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 13,
),
dividerColor: Colors.transparent,
splashFactory: NoSplash.splashFactory,
overlayColor: MaterialStateProperty.all(
Colors.transparent,
),
tabs: [
Tab(
height: 40,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
child: const Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(
Icons.inventory_2_rounded,
size: 16,
),
SizedBox(width: 6),
Text('Produk'),
],
),
),
),
Tab(
height: 40,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
child: const Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(
Icons.restaurant_menu_rounded,
size: 16,
),
SizedBox(width: 6),
Text('Bahan'),
],
),
),
),
],
),
indicatorSize: TabBarIndicatorSize.tab,
indicatorPadding: const EdgeInsets.all(6),
labelColor: AppColor.textWhite,
unselectedLabelColor: AppColor.textSecondary,
labelStyle: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 13,
),
unselectedLabelStyle: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 13,
),
dividerColor: Colors.transparent,
splashFactory: NoSplash.splashFactory,
overlayColor: MaterialStateProperty.all(
Colors.transparent,
),
tabs: [
Tab(
height: 40,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
child: const Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(
Icons.inventory_2_rounded,
size: 16,
),
SizedBox(width: 6),
Text('Produk'),
],
),
),
),
Tab(
height: 40,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
child: const Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(
Icons.restaurant_menu_rounded,
size: 16,
),
SizedBox(width: 6),
Text('Bahan'),
],
),
),
),
],
),
),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
_buildProductTab(state.inventoryAnalytic),
_buildIngredientTab(state.inventoryAnalytic),
],
];
},
body: TabBarView(
controller: _tabController,
children: [
_buildProductTab(state.inventoryAnalytic),
_buildIngredientTab(state.inventoryAnalytic),
],
),
),
),
),
);
},
),
);
},
),
),
);
}

View File

@ -1,17 +1,26 @@
import 'package:flutter/material.dart';
import '../../../../common/theme/theme.dart';
import '../../../components/field/date_range_picker_field.dart';
class InventorySliverTabBarDelegate extends SliverPersistentHeaderDelegate {
final TabBar tabBar;
final DateTime? startDate;
final DateTime? endDate;
final Function(DateTime?, DateTime?)? onDateRangeChanged;
InventorySliverTabBarDelegate({required this.tabBar});
InventorySliverTabBarDelegate({
required this.tabBar,
this.startDate,
this.endDate,
this.onDateRangeChanged,
});
@override
double get minExtent => 60;
double get minExtent => 120; // Increased height to accommodate date picker
@override
double get maxExtent => 60;
double get maxExtent => 120;
@override
Widget build(
@ -31,22 +40,40 @@ class InventorySliverTabBarDelegate extends SliverPersistentHeaderDelegate {
],
),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
child: Container(
decoration: BoxDecoration(
color: AppColor.background,
borderRadius: BorderRadius.circular(30),
border: Border.all(
color: AppColor.primary.withOpacity(0.1),
width: 1,
child: Column(
children: [
// Date Range Picker Section
if (onDateRangeChanged != null)
Expanded(
child: DateRangePickerField(
maxDate: DateTime.now(),
startDate: startDate,
endDate: endDate,
onChanged: onDateRangeChanged!,
),
),
const SizedBox(height: 8),
// Tab Bar Section
Container(
decoration: BoxDecoration(
color: AppColor.background,
borderRadius: BorderRadius.circular(30),
border: Border.all(
color: AppColor.primary.withOpacity(0.1),
width: 1,
),
),
child: tabBar,
),
),
child: tabBar,
],
),
);
}
@override
bool shouldRebuild(InventorySliverTabBarDelegate oldDelegate) {
return false;
return oldDelegate.startDate != startDate ||
oldDelegate.endDate != endDate ||
oldDelegate.tabBar != tabBar;
}
}

View File

@ -1,16 +1,28 @@
import 'package:flutter/material.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart';
import '../../../../common/theme/theme.dart';
import '../../../../domain/analytic/analytic.dart';
import '../../../../injection.dart';
import '../../../components/appbar/appbar.dart';
import '../../../components/field/date_range_picker_field.dart';
@RoutePage()
class ProductAnalyticPage extends StatefulWidget {
class ProductAnalyticPage extends StatefulWidget implements AutoRouteWrapper {
const ProductAnalyticPage({super.key});
@override
State<ProductAnalyticPage> createState() => _ProductAnalyticPageState();
@override
Widget wrappedRoute(BuildContext context) => BlocProvider(
create: (context) =>
getIt<ProductAnalyticLoaderBloc>()
..add(ProductAnalyticLoaderEvent.fetched()),
child: this,
);
}
class _ProductAnalyticPageState extends State<ProductAnalyticPage>
@ -20,66 +32,6 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
late Animation<double> _fadeAnimation;
late Animation<Offset> _slideAnimation;
// Sample data untuk demo
final ProductAnalytic sampleData = ProductAnalytic(
organizationId: "org_123",
outletId: "outlet_456",
dateFrom: "2024-01-01",
dateTo: "2024-01-31",
data: [
ProductAnalyticData(
productId: "prod_1",
productName: "Nasi Goreng Spesial",
categoryId: "cat_1",
categoryName: "Makanan Utama",
quantitySold: 145,
revenue: 2175000.0,
averagePrice: 15000.0,
orderCount: 98,
),
ProductAnalyticData(
productId: "prod_2",
productName: "Es Teh Manis",
categoryId: "cat_2",
categoryName: "Minuman",
quantitySold: 230,
revenue: 1150000.0,
averagePrice: 5000.0,
orderCount: 180,
),
ProductAnalyticData(
productId: "prod_3",
productName: "Ayam Bakar",
categoryId: "cat_1",
categoryName: "Makanan Utama",
quantitySold: 89,
revenue: 2225000.0,
averagePrice: 25000.0,
orderCount: 75,
),
ProductAnalyticData(
productId: "prod_4",
productName: "Cappuccino",
categoryId: "cat_2",
categoryName: "Minuman",
quantitySold: 67,
revenue: 1005000.0,
averagePrice: 15000.0,
orderCount: 52,
),
ProductAnalyticData(
productId: "prod_5",
productName: "Pisang Goreng",
categoryId: "cat_3",
categoryName: "Snack",
quantitySold: 156,
revenue: 780000.0,
averagePrice: 5000.0,
orderCount: 134,
),
],
);
@override
void initState() {
super.initState();
@ -126,13 +78,52 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.background,
body: CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
_buildSliverAppBar(),
_buildSummarySection(),
_buildProductsList(),
],
body: BlocListener<ProductAnalyticLoaderBloc, ProductAnalyticLoaderState>(
listenWhen: (previous, current) =>
previous.dateFrom != current.dateFrom ||
previous.dateTo != current.dateTo,
listener: (context, state) {
context.read<ProductAnalyticLoaderBloc>().add(
ProductAnalyticLoaderEvent.fetched(),
);
},
child:
BlocBuilder<ProductAnalyticLoaderBloc, ProductAnalyticLoaderState>(
builder: (context, state) {
return CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
_buildSliverAppBar(),
SliverToBoxAdapter(
child: SlideTransition(
position: _slideAnimation,
child: FadeTransition(
opacity: _fadeAnimation,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: DateRangePickerField(
maxDate: DateTime.now(),
startDate: state.dateFrom,
endDate: state.dateTo,
onChanged: (startDate, endDate) {
context.read<ProductAnalyticLoaderBloc>().add(
ProductAnalyticLoaderEvent.rangeDateChanged(
startDate!,
endDate!,
),
);
},
),
),
),
),
),
_buildSummarySection(state.productAnalytic),
_buildProductsList(state.productAnalytic),
],
);
},
),
),
);
}
@ -161,7 +152,7 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
}
// SUMMARY SECTION
Widget _buildSummarySection() {
Widget _buildSummarySection(ProductAnalytic productAnalytic) {
return SliverToBoxAdapter(
child: FadeTransition(
opacity: _fadeAnimation,
@ -169,7 +160,7 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
position: _slideAnimation,
child: Container(
margin: const EdgeInsets.all(16),
child: _buildSummaryCards(sampleData.data),
child: _buildSummaryCards(productAnalytic.data),
),
),
),
@ -177,7 +168,7 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
}
// PRODUCTS LIST
Widget _buildProductsList() {
Widget _buildProductsList(ProductAnalytic productAnalytic) {
return SliverPadding(
padding: const EdgeInsets.all(16),
sliver: SliverList(
@ -198,12 +189,16 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
offset: Offset(0, 50 * (1 - animValue)),
child: Opacity(
opacity: animValue,
child: _buildProductCard(sampleData.data[index], index),
child: _buildProductCard(
productAnalytic,
productAnalytic.data[index],
index,
),
),
);
},
);
}, childCount: sampleData.data.length),
}, childCount: productAnalytic.data.length),
),
);
}
@ -330,7 +325,11 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
}
// PRODUCT CARD - NEW CLEAN LAYOUT
Widget _buildProductCard(ProductAnalyticData product, int index) {
Widget _buildProductCard(
ProductAnalytic productAnalytic,
ProductAnalyticData product,
int index,
) {
return TweenAnimationBuilder<double>(
tween: Tween<double>(begin: 0.0, end: 1.0),
duration: Duration(milliseconds: 600 + (index * 100)),
@ -344,9 +343,9 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
opacity: clampedValue,
child: Container(
margin: EdgeInsets.only(
bottom: index == sampleData.data.length - 1 ? 0 : 16,
bottom: index == productAnalytic.data.length - 1 ? 0 : 16,
),
child: _buildCardContent(product, index),
child: _buildCardContent(productAnalytic, product, index),
),
),
);
@ -354,7 +353,11 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
);
}
Widget _buildCardContent(ProductAnalyticData product, int index) {
Widget _buildCardContent(
ProductAnalytic productAnalytic,
ProductAnalyticData product,
int index,
) {
return Container(
decoration: BoxDecoration(
color: AppColor.white,
@ -383,7 +386,7 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
child: Column(
children: [
_buildCardHeader(product, index),
_buildCardBody(product),
_buildCardBody(productAnalytic, product),
],
),
),
@ -410,8 +413,11 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
);
}
Widget _buildCardBody(ProductAnalyticData product) {
final index = sampleData.data.indexOf(product);
Widget _buildCardBody(
ProductAnalytic productAnalytic,
ProductAnalyticData product,
) {
final index = productAnalytic.data.indexOf(product);
return Padding(
padding: const EdgeInsets.all(24),
@ -546,7 +552,7 @@ class _ProductAnalyticPageState extends State<ProductAnalyticPage>
),
const SizedBox(height: 8),
Text(
_formatCurrency(product.revenue),
_formatCurrency(product.revenue.toDouble()),
style: _getTextStyle(
AppStyle.xl,
color: AppColor.success,

View File

@ -9,6 +9,7 @@ import '../../../common/theme/theme.dart';
import '../../../injection.dart';
import '../../components/appbar/appbar.dart';
import '../../components/button/button.dart';
import '../../components/field/date_range_picker_field.dart';
import '../../components/spacer/spacer.dart';
import 'widgets/payment_method.dart';
import 'widgets/quick_stats.dart';
@ -87,78 +88,120 @@ class _ReportPageState extends State<ReportPage> with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.background,
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,
return BlocListener<
DashboardAnalyticLoaderBloc,
DashboardAnalyticLoaderState
>(
listenWhen: (previous, current) =>
previous.dateFrom != current.dateFrom ||
previous.dateTo != current.dateTo,
listener: (context, state) {
context.read<DashboardAnalyticLoaderBloc>().add(
DashboardAnalyticLoaderEvent.fetched(),
);
},
child: Scaffold(
backgroundColor: AppColor.background,
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),
],
),
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(
SliverToBoxAdapter(
child: SlideTransition(
position: _slideAnimation,
child: 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),
],
child: Padding(
padding: const EdgeInsets.all(16.0),
child: DateRangePickerField(
maxDate: DateTime.now(),
startDate: state.dateFrom,
endDate: state.dateTo,
onChanged: (startDate, endDate) {
context.read<DashboardAnalyticLoaderBloc>().add(
DashboardAnalyticLoaderEvent.rangeDateChanged(
startDate!,
endDate!,
),
);
},
),
),
),
]),
),
),
),
],
);
},
),
// 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),
],
),
),
),
]),
),
),
],
);
},
),
),
);
}
}

View File

@ -10,6 +10,7 @@ import '../../../common/theme/theme.dart';
import '../../../domain/analytic/analytic.dart';
import '../../../injection.dart';
import '../../components/appbar/appbar.dart';
import '../../components/field/date_range_picker_field.dart';
import '../../components/spacer/spacer.dart';
import 'widgets/summary_card.dart';
@ -79,143 +80,125 @@ class _SalesPageState extends State<SalesPage> with TickerProviderStateMixin {
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.background,
body: BlocBuilder<SalesLoaderBloc, SalesLoaderState>(
builder: (context, state) {
return CustomScrollView(
slivers: [
// App Bar
SliverAppBar(
expandedHeight: 120,
floating: false,
pinned: true,
backgroundColor: AppColor.primary,
flexibleSpace: CustomAppBar(title: 'Penjualan'),
),
// Date Range Header
SliverToBoxAdapter(
child: SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: state.isFetching
? _buildDateRangeShimmer()
: _buildDateRangeHeader(),
),
body: BlocListener<SalesLoaderBloc, SalesLoaderState>(
listenWhen: (previous, current) =>
previous.dateFrom != current.dateFrom ||
previous.dateTo != current.dateTo,
listener: (context, state) {
context.read<SalesLoaderBloc>().add(SalesLoaderEvent.fectched());
},
child: BlocBuilder<SalesLoaderBloc, SalesLoaderState>(
builder: (context, state) {
return CustomScrollView(
slivers: [
// App Bar
SliverAppBar(
expandedHeight: 120,
floating: false,
pinned: true,
backgroundColor: AppColor.primary,
flexibleSpace: CustomAppBar(title: 'Penjualan'),
),
),
// Summary Cards
SliverToBoxAdapter(
child: SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Summary',
style: AppStyle.xxl.copyWith(
fontWeight: FontWeight.bold,
color: AppColor.textPrimary,
),
),
const SpaceHeight(16),
state.isFetching
? _buildSummaryShimmer()
: _buildSummaryCards(state),
],
),
),
),
),
),
// Net Sales Card
SliverToBoxAdapter(
child: SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: state.isFetching
? _buildNetSalesShimmer()
: _buildNetSalesCard(state),
),
),
),
// Daily Sales Section Header
SliverToBoxAdapter(
child: SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
child: Text(
'Daily Breakdown',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: AppColor.textPrimary,
// Date Range Header
SliverToBoxAdapter(
child: SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: DateRangePickerField(
maxDate: DateTime.now(),
startDate: state.dateFrom,
endDate: state.dateTo,
onChanged: (startDate, endDate) {
context.read<SalesLoaderBloc>().add(
SalesLoaderEvent.rangeDateChanged(
startDate!,
endDate!,
),
);
},
),
),
),
),
),
),
// Daily Sales List
state.isFetching
? _buildDailySalesShimmer()
: _buildDailySalesList(state),
// Bottom Padding
const SliverToBoxAdapter(child: SpaceHeight(32)),
],
);
},
),
);
}
// Shimmer Components
Widget _buildDateRangeShimmer() {
return Container(
margin: const EdgeInsets.all(16),
child: Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Container(
width: 20,
height: 20,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
// Summary Cards
SliverToBoxAdapter(
child: SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Summary',
style: AppStyle.xxl.copyWith(
fontWeight: FontWeight.bold,
color: AppColor.textPrimary,
),
),
const SpaceHeight(16),
state.isFetching
? _buildSummaryShimmer()
: _buildSummaryCards(state),
],
),
),
),
),
),
),
SpaceWidth(8),
Container(
width: 150,
height: 16,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
// Net Sales Card
SliverToBoxAdapter(
child: SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: state.isFetching
? _buildNetSalesShimmer()
: _buildNetSalesCard(state),
),
),
),
),
],
),
// Daily Sales Section Header
SliverToBoxAdapter(
child: SlideTransition(
position: slideAnimation,
child: FadeTransition(
opacity: fadeAnimation,
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
child: Text(
'Daily Breakdown',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: AppColor.textPrimary,
),
),
),
),
),
),
// Daily Sales List
state.isFetching
? _buildDailySalesShimmer()
: _buildDailySalesList(state),
// Bottom Padding
const SliverToBoxAdapter(child: SpaceHeight(32)),
],
);
},
),
),
);
@ -415,38 +398,6 @@ class _SalesPageState extends State<SalesPage> with TickerProviderStateMixin {
);
}
// Original Components (preserved)
Widget _buildDateRangeHeader() {
return Container(
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
color: AppColor.surface,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Row(
children: [
Icon(Icons.date_range, color: AppColor.primary, size: 20),
SpaceWidth(8),
Text(
'Aug 1 - Aug 15, 2025',
style: AppStyle.md.copyWith(
color: AppColor.textPrimary,
fontWeight: FontWeight.w500,
),
),
],
),
);
}
Widget _buildSummaryCards(SalesLoaderState state) {
return Column(
children: [

View File

@ -321,7 +321,7 @@ class ProductAnalyticRoute extends _i20.PageRouteInfo<void> {
static _i20.PageInfo page = _i20.PageInfo(
name,
builder: (data) {
return const _i12.ProductAnalyticPage();
return _i20.WrappedRoute(child: const _i12.ProductAnalyticPage());
},
);
}

View File

@ -1218,6 +1218,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.1"
syncfusion_flutter_core:
dependency: transitive
description:
name: syncfusion_flutter_core
sha256: ce02ce65f51db8e29edc9d2225872d927e001bd2b13c2490d176563bbb046fc7
url: "https://pub.dev"
source: hosted
version: "30.2.5"
syncfusion_flutter_datepicker:
dependency: "direct main"
description:
name: syncfusion_flutter_datepicker
sha256: e8df9f4777df15db11929f20cbe98e4249fe08208e7107bcb4ad889aa1ba2bbf
url: "https://pub.dev"
source: hosted
version: "30.2.5"
synchronized:
dependency: transitive
description:
@ -1388,4 +1404,4 @@ packages:
version: "3.1.3"
sdks:
dart: ">=3.8.1 <4.0.0"
flutter: ">=3.27.4"
flutter: ">=3.29.0"

View File

@ -42,6 +42,7 @@ dependencies:
loader_overlay: ^5.0.0
shimmer: ^3.0.0
cached_network_image: ^3.4.1
syncfusion_flutter_datepicker: ^30.2.5
dev_dependencies:
flutter_test: