diff --git a/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart new file mode 100644 index 0000000..3848d7e --- /dev/null +++ b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart @@ -0,0 +1,50 @@ +import 'package:dartz/dartz.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/analytic/analytic.dart'; +import '../../../domain/analytic/repositories/i_analytic_repository.dart'; + +part 'inventory_analytic_loader_event.dart'; +part 'inventory_analytic_loader_state.dart'; +part 'inventory_analytic_loader_bloc.freezed.dart'; + +@injectable +class InventoryAnalyticLoaderBloc + extends Bloc { + final IAnalyticRepository _repository; + InventoryAnalyticLoaderBloc(this._repository) + : super(InventoryAnalyticLoaderState.initial()) { + on(_onInventoryAnalyticLoaderEvent); + } + + Future _onInventoryAnalyticLoaderEvent( + InventoryAnalyticLoaderEvent event, + Emitter emit, + ) { + return event.map( + fetched: (e) async { + emit( + state.copyWith( + isFetching: true, + failureOptionInventoryAnalytic: none(), + ), + ); + + final result = await _repository.getInventory( + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionInventoryAnalytic: optionOf(f)), + (inventoryAnalytic) => + state.copyWith(inventoryAnalytic: inventoryAnalytic), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.freezed.dart b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.freezed.dart new file mode 100644 index 0000000..a069165 --- /dev/null +++ b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.freezed.dart @@ -0,0 +1,406 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'inventory_analytic_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models', +); + +/// @nodoc +mixin _$InventoryAnalyticLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryAnalyticLoaderEventCopyWith<$Res> { + factory $InventoryAnalyticLoaderEventCopyWith( + InventoryAnalyticLoaderEvent value, + $Res Function(InventoryAnalyticLoaderEvent) then, + ) = + _$InventoryAnalyticLoaderEventCopyWithImpl< + $Res, + InventoryAnalyticLoaderEvent + >; +} + +/// @nodoc +class _$InventoryAnalyticLoaderEventCopyWithImpl< + $Res, + $Val extends InventoryAnalyticLoaderEvent +> + implements $InventoryAnalyticLoaderEventCopyWith<$Res> { + _$InventoryAnalyticLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$InventoryAnalyticLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'InventoryAnalyticLoaderEvent.fetched()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$FetchedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({required TResult Function() fetched}) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({TResult? Function()? fetched}) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements InventoryAnalyticLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$InventoryAnalyticLoaderState { + InventoryAnalytic get inventoryAnalytic => throw _privateConstructorUsedError; + Option get failureOptionInventoryAnalytic => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryAnalyticLoaderStateCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryAnalyticLoaderStateCopyWith<$Res> { + factory $InventoryAnalyticLoaderStateCopyWith( + InventoryAnalyticLoaderState value, + $Res Function(InventoryAnalyticLoaderState) then, + ) = + _$InventoryAnalyticLoaderStateCopyWithImpl< + $Res, + InventoryAnalyticLoaderState + >; + @useResult + $Res call({ + InventoryAnalytic inventoryAnalytic, + Option failureOptionInventoryAnalytic, + bool isFetching, + }); + + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic; +} + +/// @nodoc +class _$InventoryAnalyticLoaderStateCopyWithImpl< + $Res, + $Val extends InventoryAnalyticLoaderState +> + implements $InventoryAnalyticLoaderStateCopyWith<$Res> { + _$InventoryAnalyticLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? inventoryAnalytic = null, + Object? failureOptionInventoryAnalytic = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + inventoryAnalytic: null == inventoryAnalytic + ? _value.inventoryAnalytic + : inventoryAnalytic // ignore: cast_nullable_to_non_nullable + as InventoryAnalytic, + failureOptionInventoryAnalytic: + null == failureOptionInventoryAnalytic + ? _value.failureOptionInventoryAnalytic + : failureOptionInventoryAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic { + return $InventoryAnalyticCopyWith<$Res>(_value.inventoryAnalytic, (value) { + return _then(_value.copyWith(inventoryAnalytic: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$InventoryAnalyticLoaderStateImplCopyWith<$Res> + implements $InventoryAnalyticLoaderStateCopyWith<$Res> { + factory _$$InventoryAnalyticLoaderStateImplCopyWith( + _$InventoryAnalyticLoaderStateImpl value, + $Res Function(_$InventoryAnalyticLoaderStateImpl) then, + ) = __$$InventoryAnalyticLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + InventoryAnalytic inventoryAnalytic, + Option failureOptionInventoryAnalytic, + bool isFetching, + }); + + @override + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic; +} + +/// @nodoc +class __$$InventoryAnalyticLoaderStateImplCopyWithImpl<$Res> + extends + _$InventoryAnalyticLoaderStateCopyWithImpl< + $Res, + _$InventoryAnalyticLoaderStateImpl + > + implements _$$InventoryAnalyticLoaderStateImplCopyWith<$Res> { + __$$InventoryAnalyticLoaderStateImplCopyWithImpl( + _$InventoryAnalyticLoaderStateImpl _value, + $Res Function(_$InventoryAnalyticLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? inventoryAnalytic = null, + Object? failureOptionInventoryAnalytic = null, + Object? isFetching = null, + }) { + return _then( + _$InventoryAnalyticLoaderStateImpl( + inventoryAnalytic: null == inventoryAnalytic + ? _value.inventoryAnalytic + : inventoryAnalytic // ignore: cast_nullable_to_non_nullable + as InventoryAnalytic, + failureOptionInventoryAnalytic: null == failureOptionInventoryAnalytic + ? _value.failureOptionInventoryAnalytic + : failureOptionInventoryAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$InventoryAnalyticLoaderStateImpl + implements _InventoryAnalyticLoaderState { + const _$InventoryAnalyticLoaderStateImpl({ + required this.inventoryAnalytic, + required this.failureOptionInventoryAnalytic, + this.isFetching = false, + }); + + @override + final InventoryAnalytic inventoryAnalytic; + @override + final Option failureOptionInventoryAnalytic; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'InventoryAnalyticLoaderState(inventoryAnalytic: $inventoryAnalytic, failureOptionInventoryAnalytic: $failureOptionInventoryAnalytic, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryAnalyticLoaderStateImpl && + (identical(other.inventoryAnalytic, inventoryAnalytic) || + other.inventoryAnalytic == inventoryAnalytic) && + (identical( + other.failureOptionInventoryAnalytic, + failureOptionInventoryAnalytic, + ) || + other.failureOptionInventoryAnalytic == + failureOptionInventoryAnalytic) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + inventoryAnalytic, + failureOptionInventoryAnalytic, + isFetching, + ); + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryAnalyticLoaderStateImplCopyWith< + _$InventoryAnalyticLoaderStateImpl + > + get copyWith => + __$$InventoryAnalyticLoaderStateImplCopyWithImpl< + _$InventoryAnalyticLoaderStateImpl + >(this, _$identity); +} + +abstract class _InventoryAnalyticLoaderState + implements InventoryAnalyticLoaderState { + const factory _InventoryAnalyticLoaderState({ + required final InventoryAnalytic inventoryAnalytic, + required final Option failureOptionInventoryAnalytic, + final bool isFetching, + }) = _$InventoryAnalyticLoaderStateImpl; + + @override + InventoryAnalytic get inventoryAnalytic; + @override + Option get failureOptionInventoryAnalytic; + @override + bool get isFetching; + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryAnalyticLoaderStateImplCopyWith< + _$InventoryAnalyticLoaderStateImpl + > + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_event.dart b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_event.dart new file mode 100644 index 0000000..121d123 --- /dev/null +++ b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_event.dart @@ -0,0 +1,6 @@ +part of 'inventory_analytic_loader_bloc.dart'; + +@freezed +class InventoryAnalyticLoaderEvent with _$InventoryAnalyticLoaderEvent { + const factory InventoryAnalyticLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_state.dart b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_state.dart new file mode 100644 index 0000000..2cdd303 --- /dev/null +++ b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_state.dart @@ -0,0 +1,16 @@ +part of 'inventory_analytic_loader_bloc.dart'; + +@freezed +class InventoryAnalyticLoaderState with _$InventoryAnalyticLoaderState { + const factory InventoryAnalyticLoaderState({ + required InventoryAnalytic inventoryAnalytic, + required Option failureOptionInventoryAnalytic, + @Default(false) bool isFetching, + }) = _InventoryAnalyticLoaderState; + + factory InventoryAnalyticLoaderState.initial() => + InventoryAnalyticLoaderState( + inventoryAnalytic: InventoryAnalytic.empty(), + failureOptionInventoryAnalytic: None(), + ); +} diff --git a/lib/common/url/api_path.dart b/lib/common/url/api_path.dart index dc970fb..ad89d04 100644 --- a/lib/common/url/api_path.dart +++ b/lib/common/url/api_path.dart @@ -8,6 +8,10 @@ class ApiPath { static const String profitLossAnalytic = '/api/v1/analytics/profit-loss'; static const String categoryAnalytic = '/api/v1/analytics/categories'; + // Inventory + static const String inventoryReportDetail = + '/api/v1/inventory/report/details'; + // Category static const String category = '/api/v1/categories'; diff --git a/lib/domain/analytic/analytic.dart b/lib/domain/analytic/analytic.dart index 8933596..13925fe 100644 --- a/lib/domain/analytic/analytic.dart +++ b/lib/domain/analytic/analytic.dart @@ -7,4 +7,5 @@ part 'analytic.freezed.dart'; part 'entities/sales_analytic_entity.dart'; part 'entities/profit_loss_analytic_entity.dart'; part 'entities/category_analytic_entity.dart'; +part 'entities/inventory_analytic_entity.dart'; part 'failures/analytic_failure.dart'; diff --git a/lib/domain/analytic/analytic.freezed.dart b/lib/domain/analytic/analytic.freezed.dart index 0291711..6e221e6 100644 --- a/lib/domain/analytic/analytic.freezed.dart +++ b/lib/domain/analytic/analytic.freezed.dart @@ -2803,6 +2803,1448 @@ abstract class _CategoryAnalyticItem implements CategoryAnalyticItem { get copyWith => throw _privateConstructorUsedError; } +/// @nodoc +mixin _$InventoryAnalytic { + InventorySummary get summary => throw _privateConstructorUsedError; + List get products => throw _privateConstructorUsedError; + List get ingredients => + throw _privateConstructorUsedError; + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryAnalyticCopyWith<$Res> { + factory $InventoryAnalyticCopyWith( + InventoryAnalytic value, + $Res Function(InventoryAnalytic) then, + ) = _$InventoryAnalyticCopyWithImpl<$Res, InventoryAnalytic>; + @useResult + $Res call({ + InventorySummary summary, + List products, + List ingredients, + }); + + $InventorySummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class _$InventoryAnalyticCopyWithImpl<$Res, $Val extends InventoryAnalytic> + implements $InventoryAnalyticCopyWith<$Res> { + _$InventoryAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = null, + Object? products = null, + Object? ingredients = null, + }) { + return _then( + _value.copyWith( + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as InventorySummary, + products: null == products + ? _value.products + : products // ignore: cast_nullable_to_non_nullable + as List, + ingredients: null == ingredients + ? _value.ingredients + : ingredients // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $InventorySummaryCopyWith<$Res> get summary { + return $InventorySummaryCopyWith<$Res>(_value.summary, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$InventoryAnalyticImplCopyWith<$Res> + implements $InventoryAnalyticCopyWith<$Res> { + factory _$$InventoryAnalyticImplCopyWith( + _$InventoryAnalyticImpl value, + $Res Function(_$InventoryAnalyticImpl) then, + ) = __$$InventoryAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + InventorySummary summary, + List products, + List ingredients, + }); + + @override + $InventorySummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class __$$InventoryAnalyticImplCopyWithImpl<$Res> + extends _$InventoryAnalyticCopyWithImpl<$Res, _$InventoryAnalyticImpl> + implements _$$InventoryAnalyticImplCopyWith<$Res> { + __$$InventoryAnalyticImplCopyWithImpl( + _$InventoryAnalyticImpl _value, + $Res Function(_$InventoryAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = null, + Object? products = null, + Object? ingredients = null, + }) { + return _then( + _$InventoryAnalyticImpl( + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as InventorySummary, + products: null == products + ? _value._products + : products // ignore: cast_nullable_to_non_nullable + as List, + ingredients: null == ingredients + ? _value._ingredients + : ingredients // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$InventoryAnalyticImpl implements _InventoryAnalytic { + const _$InventoryAnalyticImpl({ + required this.summary, + required final List products, + required final List ingredients, + }) : _products = products, + _ingredients = ingredients; + + @override + final InventorySummary summary; + final List _products; + @override + List get products { + if (_products is EqualUnmodifiableListView) return _products; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_products); + } + + final List _ingredients; + @override + List get ingredients { + if (_ingredients is EqualUnmodifiableListView) return _ingredients; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_ingredients); + } + + @override + String toString() { + return 'InventoryAnalytic(summary: $summary, products: $products, ingredients: $ingredients)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryAnalyticImpl && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._products, _products) && + const DeepCollectionEquality().equals( + other._ingredients, + _ingredients, + )); + } + + @override + int get hashCode => Object.hash( + runtimeType, + summary, + const DeepCollectionEquality().hash(_products), + const DeepCollectionEquality().hash(_ingredients), + ); + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryAnalyticImplCopyWith<_$InventoryAnalyticImpl> get copyWith => + __$$InventoryAnalyticImplCopyWithImpl<_$InventoryAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _InventoryAnalytic implements InventoryAnalytic { + const factory _InventoryAnalytic({ + required final InventorySummary summary, + required final List products, + required final List ingredients, + }) = _$InventoryAnalyticImpl; + + @override + InventorySummary get summary; + @override + List get products; + @override + List get ingredients; + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryAnalyticImplCopyWith<_$InventoryAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$InventorySummary { + int get totalProducts => throw _privateConstructorUsedError; + int get totalIngredients => throw _privateConstructorUsedError; + int get totalValue => throw _privateConstructorUsedError; + int get lowStockProducts => throw _privateConstructorUsedError; + int get lowStockIngredients => throw _privateConstructorUsedError; + int get zeroStockProducts => throw _privateConstructorUsedError; + int get zeroStockIngredients => throw _privateConstructorUsedError; + int get totalSoldProducts => throw _privateConstructorUsedError; + int get totalSoldIngredients => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get outletName => throw _privateConstructorUsedError; + String get generatedAt => throw _privateConstructorUsedError; + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventorySummaryCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventorySummaryCopyWith<$Res> { + factory $InventorySummaryCopyWith( + InventorySummary value, + $Res Function(InventorySummary) then, + ) = _$InventorySummaryCopyWithImpl<$Res, InventorySummary>; + @useResult + $Res call({ + int totalProducts, + int totalIngredients, + int totalValue, + int lowStockProducts, + int lowStockIngredients, + int zeroStockProducts, + int zeroStockIngredients, + int totalSoldProducts, + int totalSoldIngredients, + String outletId, + String outletName, + String generatedAt, + }); +} + +/// @nodoc +class _$InventorySummaryCopyWithImpl<$Res, $Val extends InventorySummary> + implements $InventorySummaryCopyWith<$Res> { + _$InventorySummaryCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalProducts = null, + Object? totalIngredients = null, + Object? totalValue = null, + Object? lowStockProducts = null, + Object? lowStockIngredients = null, + Object? zeroStockProducts = null, + Object? zeroStockIngredients = null, + Object? totalSoldProducts = null, + Object? totalSoldIngredients = null, + Object? outletId = null, + Object? outletName = null, + Object? generatedAt = null, + }) { + return _then( + _value.copyWith( + totalProducts: null == totalProducts + ? _value.totalProducts + : totalProducts // ignore: cast_nullable_to_non_nullable + as int, + totalIngredients: null == totalIngredients + ? _value.totalIngredients + : totalIngredients // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + lowStockProducts: null == lowStockProducts + ? _value.lowStockProducts + : lowStockProducts // ignore: cast_nullable_to_non_nullable + as int, + lowStockIngredients: null == lowStockIngredients + ? _value.lowStockIngredients + : lowStockIngredients // ignore: cast_nullable_to_non_nullable + as int, + zeroStockProducts: null == zeroStockProducts + ? _value.zeroStockProducts + : zeroStockProducts // ignore: cast_nullable_to_non_nullable + as int, + zeroStockIngredients: null == zeroStockIngredients + ? _value.zeroStockIngredients + : zeroStockIngredients // ignore: cast_nullable_to_non_nullable + as int, + totalSoldProducts: null == totalSoldProducts + ? _value.totalSoldProducts + : totalSoldProducts // ignore: cast_nullable_to_non_nullable + as int, + totalSoldIngredients: null == totalSoldIngredients + ? _value.totalSoldIngredients + : totalSoldIngredients // ignore: cast_nullable_to_non_nullable + as int, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + outletName: null == outletName + ? _value.outletName + : outletName // ignore: cast_nullable_to_non_nullable + as String, + generatedAt: null == generatedAt + ? _value.generatedAt + : generatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventorySummaryImplCopyWith<$Res> + implements $InventorySummaryCopyWith<$Res> { + factory _$$InventorySummaryImplCopyWith( + _$InventorySummaryImpl value, + $Res Function(_$InventorySummaryImpl) then, + ) = __$$InventorySummaryImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + int totalProducts, + int totalIngredients, + int totalValue, + int lowStockProducts, + int lowStockIngredients, + int zeroStockProducts, + int zeroStockIngredients, + int totalSoldProducts, + int totalSoldIngredients, + String outletId, + String outletName, + String generatedAt, + }); +} + +/// @nodoc +class __$$InventorySummaryImplCopyWithImpl<$Res> + extends _$InventorySummaryCopyWithImpl<$Res, _$InventorySummaryImpl> + implements _$$InventorySummaryImplCopyWith<$Res> { + __$$InventorySummaryImplCopyWithImpl( + _$InventorySummaryImpl _value, + $Res Function(_$InventorySummaryImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalProducts = null, + Object? totalIngredients = null, + Object? totalValue = null, + Object? lowStockProducts = null, + Object? lowStockIngredients = null, + Object? zeroStockProducts = null, + Object? zeroStockIngredients = null, + Object? totalSoldProducts = null, + Object? totalSoldIngredients = null, + Object? outletId = null, + Object? outletName = null, + Object? generatedAt = null, + }) { + return _then( + _$InventorySummaryImpl( + totalProducts: null == totalProducts + ? _value.totalProducts + : totalProducts // ignore: cast_nullable_to_non_nullable + as int, + totalIngredients: null == totalIngredients + ? _value.totalIngredients + : totalIngredients // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + lowStockProducts: null == lowStockProducts + ? _value.lowStockProducts + : lowStockProducts // ignore: cast_nullable_to_non_nullable + as int, + lowStockIngredients: null == lowStockIngredients + ? _value.lowStockIngredients + : lowStockIngredients // ignore: cast_nullable_to_non_nullable + as int, + zeroStockProducts: null == zeroStockProducts + ? _value.zeroStockProducts + : zeroStockProducts // ignore: cast_nullable_to_non_nullable + as int, + zeroStockIngredients: null == zeroStockIngredients + ? _value.zeroStockIngredients + : zeroStockIngredients // ignore: cast_nullable_to_non_nullable + as int, + totalSoldProducts: null == totalSoldProducts + ? _value.totalSoldProducts + : totalSoldProducts // ignore: cast_nullable_to_non_nullable + as int, + totalSoldIngredients: null == totalSoldIngredients + ? _value.totalSoldIngredients + : totalSoldIngredients // ignore: cast_nullable_to_non_nullable + as int, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + outletName: null == outletName + ? _value.outletName + : outletName // ignore: cast_nullable_to_non_nullable + as String, + generatedAt: null == generatedAt + ? _value.generatedAt + : generatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$InventorySummaryImpl implements _InventorySummary { + const _$InventorySummaryImpl({ + required this.totalProducts, + required this.totalIngredients, + required this.totalValue, + required this.lowStockProducts, + required this.lowStockIngredients, + required this.zeroStockProducts, + required this.zeroStockIngredients, + required this.totalSoldProducts, + required this.totalSoldIngredients, + required this.outletId, + required this.outletName, + required this.generatedAt, + }); + + @override + final int totalProducts; + @override + final int totalIngredients; + @override + final int totalValue; + @override + final int lowStockProducts; + @override + final int lowStockIngredients; + @override + final int zeroStockProducts; + @override + final int zeroStockIngredients; + @override + final int totalSoldProducts; + @override + final int totalSoldIngredients; + @override + final String outletId; + @override + final String outletName; + @override + final String generatedAt; + + @override + String toString() { + return 'InventorySummary(totalProducts: $totalProducts, totalIngredients: $totalIngredients, totalValue: $totalValue, lowStockProducts: $lowStockProducts, lowStockIngredients: $lowStockIngredients, zeroStockProducts: $zeroStockProducts, zeroStockIngredients: $zeroStockIngredients, totalSoldProducts: $totalSoldProducts, totalSoldIngredients: $totalSoldIngredients, outletId: $outletId, outletName: $outletName, generatedAt: $generatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventorySummaryImpl && + (identical(other.totalProducts, totalProducts) || + other.totalProducts == totalProducts) && + (identical(other.totalIngredients, totalIngredients) || + other.totalIngredients == totalIngredients) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.lowStockProducts, lowStockProducts) || + other.lowStockProducts == lowStockProducts) && + (identical(other.lowStockIngredients, lowStockIngredients) || + other.lowStockIngredients == lowStockIngredients) && + (identical(other.zeroStockProducts, zeroStockProducts) || + other.zeroStockProducts == zeroStockProducts) && + (identical(other.zeroStockIngredients, zeroStockIngredients) || + other.zeroStockIngredients == zeroStockIngredients) && + (identical(other.totalSoldProducts, totalSoldProducts) || + other.totalSoldProducts == totalSoldProducts) && + (identical(other.totalSoldIngredients, totalSoldIngredients) || + other.totalSoldIngredients == totalSoldIngredients) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.outletName, outletName) || + other.outletName == outletName) && + (identical(other.generatedAt, generatedAt) || + other.generatedAt == generatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + totalProducts, + totalIngredients, + totalValue, + lowStockProducts, + lowStockIngredients, + zeroStockProducts, + zeroStockIngredients, + totalSoldProducts, + totalSoldIngredients, + outletId, + outletName, + generatedAt, + ); + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventorySummaryImplCopyWith<_$InventorySummaryImpl> get copyWith => + __$$InventorySummaryImplCopyWithImpl<_$InventorySummaryImpl>( + this, + _$identity, + ); +} + +abstract class _InventorySummary implements InventorySummary { + const factory _InventorySummary({ + required final int totalProducts, + required final int totalIngredients, + required final int totalValue, + required final int lowStockProducts, + required final int lowStockIngredients, + required final int zeroStockProducts, + required final int zeroStockIngredients, + required final int totalSoldProducts, + required final int totalSoldIngredients, + required final String outletId, + required final String outletName, + required final String generatedAt, + }) = _$InventorySummaryImpl; + + @override + int get totalProducts; + @override + int get totalIngredients; + @override + int get totalValue; + @override + int get lowStockProducts; + @override + int get lowStockIngredients; + @override + int get zeroStockProducts; + @override + int get zeroStockIngredients; + @override + int get totalSoldProducts; + @override + int get totalSoldIngredients; + @override + String get outletId; + @override + String get outletName; + @override + String get generatedAt; + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventorySummaryImplCopyWith<_$InventorySummaryImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$InventoryProduct { + String get id => throw _privateConstructorUsedError; + String get productId => throw _privateConstructorUsedError; + String get productName => throw _privateConstructorUsedError; + String get categoryName => throw _privateConstructorUsedError; + int get quantity => throw _privateConstructorUsedError; + int get reorderLevel => throw _privateConstructorUsedError; + int get unitCost => throw _privateConstructorUsedError; + int get totalValue => throw _privateConstructorUsedError; + int get totalIn => throw _privateConstructorUsedError; + int get totalOut => throw _privateConstructorUsedError; + bool get isLowStock => throw _privateConstructorUsedError; + bool get isZeroStock => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryProductCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryProductCopyWith<$Res> { + factory $InventoryProductCopyWith( + InventoryProduct value, + $Res Function(InventoryProduct) then, + ) = _$InventoryProductCopyWithImpl<$Res, InventoryProduct>; + @useResult + $Res call({ + String id, + String productId, + String productName, + String categoryName, + int quantity, + int reorderLevel, + int unitCost, + int totalValue, + int totalIn, + int totalOut, + bool isLowStock, + bool isZeroStock, + String updatedAt, + }); +} + +/// @nodoc +class _$InventoryProductCopyWithImpl<$Res, $Val extends InventoryProduct> + implements $InventoryProductCopyWith<$Res> { + _$InventoryProductCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? productId = null, + Object? productName = null, + Object? categoryName = null, + Object? quantity = null, + Object? reorderLevel = null, + Object? unitCost = null, + Object? totalValue = null, + Object? totalIn = null, + Object? totalOut = null, + Object? isLowStock = null, + Object? isZeroStock = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + reorderLevel: null == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int, + unitCost: null == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + totalIn: null == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int, + totalOut: null == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int, + isLowStock: null == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool, + isZeroStock: null == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventoryProductImplCopyWith<$Res> + implements $InventoryProductCopyWith<$Res> { + factory _$$InventoryProductImplCopyWith( + _$InventoryProductImpl value, + $Res Function(_$InventoryProductImpl) then, + ) = __$$InventoryProductImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String productId, + String productName, + String categoryName, + int quantity, + int reorderLevel, + int unitCost, + int totalValue, + int totalIn, + int totalOut, + bool isLowStock, + bool isZeroStock, + String updatedAt, + }); +} + +/// @nodoc +class __$$InventoryProductImplCopyWithImpl<$Res> + extends _$InventoryProductCopyWithImpl<$Res, _$InventoryProductImpl> + implements _$$InventoryProductImplCopyWith<$Res> { + __$$InventoryProductImplCopyWithImpl( + _$InventoryProductImpl _value, + $Res Function(_$InventoryProductImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? productId = null, + Object? productName = null, + Object? categoryName = null, + Object? quantity = null, + Object? reorderLevel = null, + Object? unitCost = null, + Object? totalValue = null, + Object? totalIn = null, + Object? totalOut = null, + Object? isLowStock = null, + Object? isZeroStock = null, + Object? updatedAt = null, + }) { + return _then( + _$InventoryProductImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + reorderLevel: null == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int, + unitCost: null == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + totalIn: null == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int, + totalOut: null == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int, + isLowStock: null == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool, + isZeroStock: null == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$InventoryProductImpl implements _InventoryProduct { + const _$InventoryProductImpl({ + required this.id, + required this.productId, + required this.productName, + required this.categoryName, + required this.quantity, + required this.reorderLevel, + required this.unitCost, + required this.totalValue, + required this.totalIn, + required this.totalOut, + required this.isLowStock, + required this.isZeroStock, + required this.updatedAt, + }); + + @override + final String id; + @override + final String productId; + @override + final String productName; + @override + final String categoryName; + @override + final int quantity; + @override + final int reorderLevel; + @override + final int unitCost; + @override + final int totalValue; + @override + final int totalIn; + @override + final int totalOut; + @override + final bool isLowStock; + @override + final bool isZeroStock; + @override + final String updatedAt; + + @override + String toString() { + return 'InventoryProduct(id: $id, productId: $productId, productName: $productName, categoryName: $categoryName, quantity: $quantity, reorderLevel: $reorderLevel, unitCost: $unitCost, totalValue: $totalValue, totalIn: $totalIn, totalOut: $totalOut, isLowStock: $isLowStock, isZeroStock: $isZeroStock, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryProductImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.reorderLevel, reorderLevel) || + other.reorderLevel == reorderLevel) && + (identical(other.unitCost, unitCost) || + other.unitCost == unitCost) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.totalIn, totalIn) || other.totalIn == totalIn) && + (identical(other.totalOut, totalOut) || + other.totalOut == totalOut) && + (identical(other.isLowStock, isLowStock) || + other.isLowStock == isLowStock) && + (identical(other.isZeroStock, isZeroStock) || + other.isZeroStock == isZeroStock) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + productId, + productName, + categoryName, + quantity, + reorderLevel, + unitCost, + totalValue, + totalIn, + totalOut, + isLowStock, + isZeroStock, + updatedAt, + ); + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryProductImplCopyWith<_$InventoryProductImpl> get copyWith => + __$$InventoryProductImplCopyWithImpl<_$InventoryProductImpl>( + this, + _$identity, + ); +} + +abstract class _InventoryProduct implements InventoryProduct { + const factory _InventoryProduct({ + required final String id, + required final String productId, + required final String productName, + required final String categoryName, + required final int quantity, + required final int reorderLevel, + required final int unitCost, + required final int totalValue, + required final int totalIn, + required final int totalOut, + required final bool isLowStock, + required final bool isZeroStock, + required final String updatedAt, + }) = _$InventoryProductImpl; + + @override + String get id; + @override + String get productId; + @override + String get productName; + @override + String get categoryName; + @override + int get quantity; + @override + int get reorderLevel; + @override + int get unitCost; + @override + int get totalValue; + @override + int get totalIn; + @override + int get totalOut; + @override + bool get isLowStock; + @override + bool get isZeroStock; + @override + String get updatedAt; + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryProductImplCopyWith<_$InventoryProductImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$InventoryIngredient { + String get id => throw _privateConstructorUsedError; + String get ingredientId => throw _privateConstructorUsedError; + String get ingredientName => throw _privateConstructorUsedError; + String get unitName => throw _privateConstructorUsedError; + int get quantity => throw _privateConstructorUsedError; + int get reorderLevel => throw _privateConstructorUsedError; + int get unitCost => throw _privateConstructorUsedError; + int get totalValue => throw _privateConstructorUsedError; + int get totalIn => throw _privateConstructorUsedError; + int get totalOut => throw _privateConstructorUsedError; + bool get isLowStock => throw _privateConstructorUsedError; + bool get isZeroStock => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryIngredientCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryIngredientCopyWith<$Res> { + factory $InventoryIngredientCopyWith( + InventoryIngredient value, + $Res Function(InventoryIngredient) then, + ) = _$InventoryIngredientCopyWithImpl<$Res, InventoryIngredient>; + @useResult + $Res call({ + String id, + String ingredientId, + String ingredientName, + String unitName, + int quantity, + int reorderLevel, + int unitCost, + int totalValue, + int totalIn, + int totalOut, + bool isLowStock, + bool isZeroStock, + String updatedAt, + }); +} + +/// @nodoc +class _$InventoryIngredientCopyWithImpl<$Res, $Val extends InventoryIngredient> + implements $InventoryIngredientCopyWith<$Res> { + _$InventoryIngredientCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? ingredientId = null, + Object? ingredientName = null, + Object? unitName = null, + Object? quantity = null, + Object? reorderLevel = null, + Object? unitCost = null, + Object? totalValue = null, + Object? totalIn = null, + Object? totalOut = null, + Object? isLowStock = null, + Object? isZeroStock = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + ingredientId: null == ingredientId + ? _value.ingredientId + : ingredientId // ignore: cast_nullable_to_non_nullable + as String, + ingredientName: null == ingredientName + ? _value.ingredientName + : ingredientName // ignore: cast_nullable_to_non_nullable + as String, + unitName: null == unitName + ? _value.unitName + : unitName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + reorderLevel: null == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int, + unitCost: null == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + totalIn: null == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int, + totalOut: null == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int, + isLowStock: null == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool, + isZeroStock: null == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventoryIngredientImplCopyWith<$Res> + implements $InventoryIngredientCopyWith<$Res> { + factory _$$InventoryIngredientImplCopyWith( + _$InventoryIngredientImpl value, + $Res Function(_$InventoryIngredientImpl) then, + ) = __$$InventoryIngredientImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String ingredientId, + String ingredientName, + String unitName, + int quantity, + int reorderLevel, + int unitCost, + int totalValue, + int totalIn, + int totalOut, + bool isLowStock, + bool isZeroStock, + String updatedAt, + }); +} + +/// @nodoc +class __$$InventoryIngredientImplCopyWithImpl<$Res> + extends _$InventoryIngredientCopyWithImpl<$Res, _$InventoryIngredientImpl> + implements _$$InventoryIngredientImplCopyWith<$Res> { + __$$InventoryIngredientImplCopyWithImpl( + _$InventoryIngredientImpl _value, + $Res Function(_$InventoryIngredientImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? ingredientId = null, + Object? ingredientName = null, + Object? unitName = null, + Object? quantity = null, + Object? reorderLevel = null, + Object? unitCost = null, + Object? totalValue = null, + Object? totalIn = null, + Object? totalOut = null, + Object? isLowStock = null, + Object? isZeroStock = null, + Object? updatedAt = null, + }) { + return _then( + _$InventoryIngredientImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + ingredientId: null == ingredientId + ? _value.ingredientId + : ingredientId // ignore: cast_nullable_to_non_nullable + as String, + ingredientName: null == ingredientName + ? _value.ingredientName + : ingredientName // ignore: cast_nullable_to_non_nullable + as String, + unitName: null == unitName + ? _value.unitName + : unitName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + reorderLevel: null == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int, + unitCost: null == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + totalIn: null == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int, + totalOut: null == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int, + isLowStock: null == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool, + isZeroStock: null == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$InventoryIngredientImpl implements _InventoryIngredient { + const _$InventoryIngredientImpl({ + required this.id, + required this.ingredientId, + required this.ingredientName, + required this.unitName, + required this.quantity, + required this.reorderLevel, + required this.unitCost, + required this.totalValue, + required this.totalIn, + required this.totalOut, + required this.isLowStock, + required this.isZeroStock, + required this.updatedAt, + }); + + @override + final String id; + @override + final String ingredientId; + @override + final String ingredientName; + @override + final String unitName; + @override + final int quantity; + @override + final int reorderLevel; + @override + final int unitCost; + @override + final int totalValue; + @override + final int totalIn; + @override + final int totalOut; + @override + final bool isLowStock; + @override + final bool isZeroStock; + @override + final String updatedAt; + + @override + String toString() { + return 'InventoryIngredient(id: $id, ingredientId: $ingredientId, ingredientName: $ingredientName, unitName: $unitName, quantity: $quantity, reorderLevel: $reorderLevel, unitCost: $unitCost, totalValue: $totalValue, totalIn: $totalIn, totalOut: $totalOut, isLowStock: $isLowStock, isZeroStock: $isZeroStock, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryIngredientImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.ingredientId, ingredientId) || + other.ingredientId == ingredientId) && + (identical(other.ingredientName, ingredientName) || + other.ingredientName == ingredientName) && + (identical(other.unitName, unitName) || + other.unitName == unitName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.reorderLevel, reorderLevel) || + other.reorderLevel == reorderLevel) && + (identical(other.unitCost, unitCost) || + other.unitCost == unitCost) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.totalIn, totalIn) || other.totalIn == totalIn) && + (identical(other.totalOut, totalOut) || + other.totalOut == totalOut) && + (identical(other.isLowStock, isLowStock) || + other.isLowStock == isLowStock) && + (identical(other.isZeroStock, isZeroStock) || + other.isZeroStock == isZeroStock) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + ingredientId, + ingredientName, + unitName, + quantity, + reorderLevel, + unitCost, + totalValue, + totalIn, + totalOut, + isLowStock, + isZeroStock, + updatedAt, + ); + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryIngredientImplCopyWith<_$InventoryIngredientImpl> get copyWith => + __$$InventoryIngredientImplCopyWithImpl<_$InventoryIngredientImpl>( + this, + _$identity, + ); +} + +abstract class _InventoryIngredient implements InventoryIngredient { + const factory _InventoryIngredient({ + required final String id, + required final String ingredientId, + required final String ingredientName, + required final String unitName, + required final int quantity, + required final int reorderLevel, + required final int unitCost, + required final int totalValue, + required final int totalIn, + required final int totalOut, + required final bool isLowStock, + required final bool isZeroStock, + required final String updatedAt, + }) = _$InventoryIngredientImpl; + + @override + String get id; + @override + String get ingredientId; + @override + String get ingredientName; + @override + String get unitName; + @override + int get quantity; + @override + int get reorderLevel; + @override + int get unitCost; + @override + int get totalValue; + @override + int get totalIn; + @override + int get totalOut; + @override + bool get isLowStock; + @override + bool get isZeroStock; + @override + String get updatedAt; + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryIngredientImplCopyWith<_$InventoryIngredientImpl> get copyWith => + throw _privateConstructorUsedError; +} + /// @nodoc mixin _$AnalyticFailure { @optionalTypeArgs diff --git a/lib/domain/analytic/entities/inventory_analytic_entity.dart b/lib/domain/analytic/entities/inventory_analytic_entity.dart new file mode 100644 index 0000000..00d373c --- /dev/null +++ b/lib/domain/analytic/entities/inventory_analytic_entity.dart @@ -0,0 +1,119 @@ +part of '../analytic.dart'; + +@freezed +class InventoryAnalytic with _$InventoryAnalytic { + const factory InventoryAnalytic({ + required InventorySummary summary, + required List products, + required List ingredients, + }) = _InventoryAnalytic; + + factory InventoryAnalytic.empty() => InventoryAnalytic( + summary: InventorySummary.empty(), + products: [], + ingredients: [], + ); +} + +@freezed +class InventorySummary with _$InventorySummary { + const factory InventorySummary({ + required int totalProducts, + required int totalIngredients, + required int totalValue, + required int lowStockProducts, + required int lowStockIngredients, + required int zeroStockProducts, + required int zeroStockIngredients, + required int totalSoldProducts, + required int totalSoldIngredients, + required String outletId, + required String outletName, + required String generatedAt, + }) = _InventorySummary; + + factory InventorySummary.empty() => const InventorySummary( + totalProducts: 0, + totalIngredients: 0, + totalValue: 0, + lowStockProducts: 0, + lowStockIngredients: 0, + zeroStockProducts: 0, + zeroStockIngredients: 0, + totalSoldProducts: 0, + totalSoldIngredients: 0, + outletId: "", + outletName: "", + generatedAt: "", + ); +} + +@freezed +class InventoryProduct with _$InventoryProduct { + const factory InventoryProduct({ + required String id, + required String productId, + required String productName, + required String categoryName, + required int quantity, + required int reorderLevel, + required int unitCost, + required int totalValue, + required int totalIn, + required int totalOut, + required bool isLowStock, + required bool isZeroStock, + required String updatedAt, + }) = _InventoryProduct; + + factory InventoryProduct.empty() => const InventoryProduct( + id: "", + productId: "", + productName: "", + categoryName: "", + quantity: 0, + reorderLevel: 0, + unitCost: 0, + totalValue: 0, + totalIn: 0, + totalOut: 0, + isLowStock: false, + isZeroStock: false, + updatedAt: "", + ); +} + +@freezed +class InventoryIngredient with _$InventoryIngredient { + const factory InventoryIngredient({ + required String id, + required String ingredientId, + required String ingredientName, + required String unitName, + required int quantity, + required int reorderLevel, + required int unitCost, + required int totalValue, + required int totalIn, + required int totalOut, + required bool isLowStock, + required bool isZeroStock, + required String updatedAt, + }) = _InventoryIngredient; + + factory InventoryIngredient.empty() => const InventoryIngredient( + id: "", + ingredientId: "", + ingredientName: "", + unitName: "", + quantity: 0, + reorderLevel: 0, + unitCost: 0, + totalValue: 0, + totalIn: 0, + totalOut: 0, + isLowStock: false, + isZeroStock: false, + updatedAt: "", + ); +} diff --git a/lib/domain/analytic/repositories/i_analytic_repository.dart b/lib/domain/analytic/repositories/i_analytic_repository.dart index cb7826a..fb45141 100644 --- a/lib/domain/analytic/repositories/i_analytic_repository.dart +++ b/lib/domain/analytic/repositories/i_analytic_repository.dart @@ -17,4 +17,9 @@ abstract class IAnalyticRepository { required DateTime dateFrom, required DateTime dateTo, }); + + Future> getInventory({ + required DateTime dateFrom, + required DateTime dateTo, + }); } diff --git a/lib/infrastructure/analytic/analytic_dtos.dart b/lib/infrastructure/analytic/analytic_dtos.dart index a812a02..35e7062 100644 --- a/lib/infrastructure/analytic/analytic_dtos.dart +++ b/lib/infrastructure/analytic/analytic_dtos.dart @@ -8,3 +8,4 @@ part 'analytic_dtos.g.dart'; part 'dto/sales_analytic_dto.dart'; part 'dto/profit_loss_analytic_dto.dart'; part 'dto/category_analytic_dto.dart'; +part 'dto/inventory_analytic_dto.dart'; diff --git a/lib/infrastructure/analytic/analytic_dtos.freezed.dart b/lib/infrastructure/analytic/analytic_dtos.freezed.dart index eee2978..d51b773 100644 --- a/lib/infrastructure/analytic/analytic_dtos.freezed.dart +++ b/lib/infrastructure/analytic/analytic_dtos.freezed.dart @@ -3258,3 +3258,1667 @@ abstract class _CategoryAnalyticItemDto extends CategoryAnalyticItemDto { _$$CategoryAnalyticItemDtoImplCopyWith<_$CategoryAnalyticItemDtoImpl> get copyWith => throw _privateConstructorUsedError; } + +InventoryAnalyticDto _$InventoryAnalyticDtoFromJson(Map json) { + return _InventoryAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$InventoryAnalyticDto { + @JsonKey(name: "summary") + InventorySummaryDto? get summary => throw _privateConstructorUsedError; + @JsonKey(name: "products") + List? get products => throw _privateConstructorUsedError; + @JsonKey(name: "ingredients") + List? get ingredients => + throw _privateConstructorUsedError; + + /// Serializes this InventoryAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryAnalyticDtoCopyWith<$Res> { + factory $InventoryAnalyticDtoCopyWith( + InventoryAnalyticDto value, + $Res Function(InventoryAnalyticDto) then, + ) = _$InventoryAnalyticDtoCopyWithImpl<$Res, InventoryAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: "summary") InventorySummaryDto? summary, + @JsonKey(name: "products") List? products, + @JsonKey(name: "ingredients") List? ingredients, + }); + + $InventorySummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class _$InventoryAnalyticDtoCopyWithImpl< + $Res, + $Val extends InventoryAnalyticDto +> + implements $InventoryAnalyticDtoCopyWith<$Res> { + _$InventoryAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = freezed, + Object? products = freezed, + Object? ingredients = freezed, + }) { + return _then( + _value.copyWith( + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as InventorySummaryDto?, + products: freezed == products + ? _value.products + : products // ignore: cast_nullable_to_non_nullable + as List?, + ingredients: freezed == ingredients + ? _value.ingredients + : ingredients // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $InventorySummaryDtoCopyWith<$Res>? get summary { + if (_value.summary == null) { + return null; + } + + return $InventorySummaryDtoCopyWith<$Res>(_value.summary!, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$InventoryAnalyticDtoImplCopyWith<$Res> + implements $InventoryAnalyticDtoCopyWith<$Res> { + factory _$$InventoryAnalyticDtoImplCopyWith( + _$InventoryAnalyticDtoImpl value, + $Res Function(_$InventoryAnalyticDtoImpl) then, + ) = __$$InventoryAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "summary") InventorySummaryDto? summary, + @JsonKey(name: "products") List? products, + @JsonKey(name: "ingredients") List? ingredients, + }); + + @override + $InventorySummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class __$$InventoryAnalyticDtoImplCopyWithImpl<$Res> + extends _$InventoryAnalyticDtoCopyWithImpl<$Res, _$InventoryAnalyticDtoImpl> + implements _$$InventoryAnalyticDtoImplCopyWith<$Res> { + __$$InventoryAnalyticDtoImplCopyWithImpl( + _$InventoryAnalyticDtoImpl _value, + $Res Function(_$InventoryAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = freezed, + Object? products = freezed, + Object? ingredients = freezed, + }) { + return _then( + _$InventoryAnalyticDtoImpl( + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as InventorySummaryDto?, + products: freezed == products + ? _value._products + : products // ignore: cast_nullable_to_non_nullable + as List?, + ingredients: freezed == ingredients + ? _value._ingredients + : ingredients // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$InventoryAnalyticDtoImpl extends _InventoryAnalyticDto { + const _$InventoryAnalyticDtoImpl({ + @JsonKey(name: "summary") this.summary, + @JsonKey(name: "products") final List? products, + @JsonKey(name: "ingredients") + final List? ingredients, + }) : _products = products, + _ingredients = ingredients, + super._(); + + factory _$InventoryAnalyticDtoImpl.fromJson(Map json) => + _$$InventoryAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: "summary") + final InventorySummaryDto? summary; + final List? _products; + @override + @JsonKey(name: "products") + List? get products { + final value = _products; + if (value == null) return null; + if (_products is EqualUnmodifiableListView) return _products; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _ingredients; + @override + @JsonKey(name: "ingredients") + List? get ingredients { + final value = _ingredients; + if (value == null) return null; + if (_ingredients is EqualUnmodifiableListView) return _ingredients; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'InventoryAnalyticDto(summary: $summary, products: $products, ingredients: $ingredients)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryAnalyticDtoImpl && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._products, _products) && + const DeepCollectionEquality().equals( + other._ingredients, + _ingredients, + )); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + summary, + const DeepCollectionEquality().hash(_products), + const DeepCollectionEquality().hash(_ingredients), + ); + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryAnalyticDtoImplCopyWith<_$InventoryAnalyticDtoImpl> + get copyWith => + __$$InventoryAnalyticDtoImplCopyWithImpl<_$InventoryAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$InventoryAnalyticDtoImplToJson(this); + } +} + +abstract class _InventoryAnalyticDto extends InventoryAnalyticDto { + const factory _InventoryAnalyticDto({ + @JsonKey(name: "summary") final InventorySummaryDto? summary, + @JsonKey(name: "products") final List? products, + @JsonKey(name: "ingredients") + final List? ingredients, + }) = _$InventoryAnalyticDtoImpl; + const _InventoryAnalyticDto._() : super._(); + + factory _InventoryAnalyticDto.fromJson(Map json) = + _$InventoryAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: "summary") + InventorySummaryDto? get summary; + @override + @JsonKey(name: "products") + List? get products; + @override + @JsonKey(name: "ingredients") + List? get ingredients; + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryAnalyticDtoImplCopyWith<_$InventoryAnalyticDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +InventorySummaryDto _$InventorySummaryDtoFromJson(Map json) { + return _InventorySummaryDto.fromJson(json); +} + +/// @nodoc +mixin _$InventorySummaryDto { + @JsonKey(name: "total_products") + int? get totalProducts => throw _privateConstructorUsedError; + @JsonKey(name: "total_ingredients") + int? get totalIngredients => throw _privateConstructorUsedError; + @JsonKey(name: "total_value") + int? get totalValue => throw _privateConstructorUsedError; + @JsonKey(name: "low_stock_products") + int? get lowStockProducts => throw _privateConstructorUsedError; + @JsonKey(name: "low_stock_ingredients") + int? get lowStockIngredients => throw _privateConstructorUsedError; + @JsonKey(name: "zero_stock_products") + int? get zeroStockProducts => throw _privateConstructorUsedError; + @JsonKey(name: "zero_stock_ingredients") + int? get zeroStockIngredients => throw _privateConstructorUsedError; + @JsonKey(name: "total_sold_products") + int? get totalSoldProducts => throw _privateConstructorUsedError; + @JsonKey(name: "total_sold_ingredients") + int? get totalSoldIngredients => throw _privateConstructorUsedError; + @JsonKey(name: "outlet_id") + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: "outlet_name") + String? get outletName => throw _privateConstructorUsedError; + @JsonKey(name: "generated_at") + String? get generatedAt => throw _privateConstructorUsedError; + + /// Serializes this InventorySummaryDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventorySummaryDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventorySummaryDtoCopyWith<$Res> { + factory $InventorySummaryDtoCopyWith( + InventorySummaryDto value, + $Res Function(InventorySummaryDto) then, + ) = _$InventorySummaryDtoCopyWithImpl<$Res, InventorySummaryDto>; + @useResult + $Res call({ + @JsonKey(name: "total_products") int? totalProducts, + @JsonKey(name: "total_ingredients") int? totalIngredients, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "low_stock_products") int? lowStockProducts, + @JsonKey(name: "low_stock_ingredients") int? lowStockIngredients, + @JsonKey(name: "zero_stock_products") int? zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") int? zeroStockIngredients, + @JsonKey(name: "total_sold_products") int? totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") int? totalSoldIngredients, + @JsonKey(name: "outlet_id") String? outletId, + @JsonKey(name: "outlet_name") String? outletName, + @JsonKey(name: "generated_at") String? generatedAt, + }); +} + +/// @nodoc +class _$InventorySummaryDtoCopyWithImpl<$Res, $Val extends InventorySummaryDto> + implements $InventorySummaryDtoCopyWith<$Res> { + _$InventorySummaryDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalProducts = freezed, + Object? totalIngredients = freezed, + Object? totalValue = freezed, + Object? lowStockProducts = freezed, + Object? lowStockIngredients = freezed, + Object? zeroStockProducts = freezed, + Object? zeroStockIngredients = freezed, + Object? totalSoldProducts = freezed, + Object? totalSoldIngredients = freezed, + Object? outletId = freezed, + Object? outletName = freezed, + Object? generatedAt = freezed, + }) { + return _then( + _value.copyWith( + totalProducts: freezed == totalProducts + ? _value.totalProducts + : totalProducts // ignore: cast_nullable_to_non_nullable + as int?, + totalIngredients: freezed == totalIngredients + ? _value.totalIngredients + : totalIngredients // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + lowStockProducts: freezed == lowStockProducts + ? _value.lowStockProducts + : lowStockProducts // ignore: cast_nullable_to_non_nullable + as int?, + lowStockIngredients: freezed == lowStockIngredients + ? _value.lowStockIngredients + : lowStockIngredients // ignore: cast_nullable_to_non_nullable + as int?, + zeroStockProducts: freezed == zeroStockProducts + ? _value.zeroStockProducts + : zeroStockProducts // ignore: cast_nullable_to_non_nullable + as int?, + zeroStockIngredients: freezed == zeroStockIngredients + ? _value.zeroStockIngredients + : zeroStockIngredients // ignore: cast_nullable_to_non_nullable + as int?, + totalSoldProducts: freezed == totalSoldProducts + ? _value.totalSoldProducts + : totalSoldProducts // ignore: cast_nullable_to_non_nullable + as int?, + totalSoldIngredients: freezed == totalSoldIngredients + ? _value.totalSoldIngredients + : totalSoldIngredients // ignore: cast_nullable_to_non_nullable + as int?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + outletName: freezed == outletName + ? _value.outletName + : outletName // ignore: cast_nullable_to_non_nullable + as String?, + generatedAt: freezed == generatedAt + ? _value.generatedAt + : generatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventorySummaryDtoImplCopyWith<$Res> + implements $InventorySummaryDtoCopyWith<$Res> { + factory _$$InventorySummaryDtoImplCopyWith( + _$InventorySummaryDtoImpl value, + $Res Function(_$InventorySummaryDtoImpl) then, + ) = __$$InventorySummaryDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "total_products") int? totalProducts, + @JsonKey(name: "total_ingredients") int? totalIngredients, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "low_stock_products") int? lowStockProducts, + @JsonKey(name: "low_stock_ingredients") int? lowStockIngredients, + @JsonKey(name: "zero_stock_products") int? zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") int? zeroStockIngredients, + @JsonKey(name: "total_sold_products") int? totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") int? totalSoldIngredients, + @JsonKey(name: "outlet_id") String? outletId, + @JsonKey(name: "outlet_name") String? outletName, + @JsonKey(name: "generated_at") String? generatedAt, + }); +} + +/// @nodoc +class __$$InventorySummaryDtoImplCopyWithImpl<$Res> + extends _$InventorySummaryDtoCopyWithImpl<$Res, _$InventorySummaryDtoImpl> + implements _$$InventorySummaryDtoImplCopyWith<$Res> { + __$$InventorySummaryDtoImplCopyWithImpl( + _$InventorySummaryDtoImpl _value, + $Res Function(_$InventorySummaryDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalProducts = freezed, + Object? totalIngredients = freezed, + Object? totalValue = freezed, + Object? lowStockProducts = freezed, + Object? lowStockIngredients = freezed, + Object? zeroStockProducts = freezed, + Object? zeroStockIngredients = freezed, + Object? totalSoldProducts = freezed, + Object? totalSoldIngredients = freezed, + Object? outletId = freezed, + Object? outletName = freezed, + Object? generatedAt = freezed, + }) { + return _then( + _$InventorySummaryDtoImpl( + totalProducts: freezed == totalProducts + ? _value.totalProducts + : totalProducts // ignore: cast_nullable_to_non_nullable + as int?, + totalIngredients: freezed == totalIngredients + ? _value.totalIngredients + : totalIngredients // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + lowStockProducts: freezed == lowStockProducts + ? _value.lowStockProducts + : lowStockProducts // ignore: cast_nullable_to_non_nullable + as int?, + lowStockIngredients: freezed == lowStockIngredients + ? _value.lowStockIngredients + : lowStockIngredients // ignore: cast_nullable_to_non_nullable + as int?, + zeroStockProducts: freezed == zeroStockProducts + ? _value.zeroStockProducts + : zeroStockProducts // ignore: cast_nullable_to_non_nullable + as int?, + zeroStockIngredients: freezed == zeroStockIngredients + ? _value.zeroStockIngredients + : zeroStockIngredients // ignore: cast_nullable_to_non_nullable + as int?, + totalSoldProducts: freezed == totalSoldProducts + ? _value.totalSoldProducts + : totalSoldProducts // ignore: cast_nullable_to_non_nullable + as int?, + totalSoldIngredients: freezed == totalSoldIngredients + ? _value.totalSoldIngredients + : totalSoldIngredients // ignore: cast_nullable_to_non_nullable + as int?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + outletName: freezed == outletName + ? _value.outletName + : outletName // ignore: cast_nullable_to_non_nullable + as String?, + generatedAt: freezed == generatedAt + ? _value.generatedAt + : generatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$InventorySummaryDtoImpl implements _InventorySummaryDto { + const _$InventorySummaryDtoImpl({ + @JsonKey(name: "total_products") this.totalProducts, + @JsonKey(name: "total_ingredients") this.totalIngredients, + @JsonKey(name: "total_value") this.totalValue, + @JsonKey(name: "low_stock_products") this.lowStockProducts, + @JsonKey(name: "low_stock_ingredients") this.lowStockIngredients, + @JsonKey(name: "zero_stock_products") this.zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") this.zeroStockIngredients, + @JsonKey(name: "total_sold_products") this.totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") this.totalSoldIngredients, + @JsonKey(name: "outlet_id") this.outletId, + @JsonKey(name: "outlet_name") this.outletName, + @JsonKey(name: "generated_at") this.generatedAt, + }); + + factory _$InventorySummaryDtoImpl.fromJson(Map json) => + _$$InventorySummaryDtoImplFromJson(json); + + @override + @JsonKey(name: "total_products") + final int? totalProducts; + @override + @JsonKey(name: "total_ingredients") + final int? totalIngredients; + @override + @JsonKey(name: "total_value") + final int? totalValue; + @override + @JsonKey(name: "low_stock_products") + final int? lowStockProducts; + @override + @JsonKey(name: "low_stock_ingredients") + final int? lowStockIngredients; + @override + @JsonKey(name: "zero_stock_products") + final int? zeroStockProducts; + @override + @JsonKey(name: "zero_stock_ingredients") + final int? zeroStockIngredients; + @override + @JsonKey(name: "total_sold_products") + final int? totalSoldProducts; + @override + @JsonKey(name: "total_sold_ingredients") + final int? totalSoldIngredients; + @override + @JsonKey(name: "outlet_id") + final String? outletId; + @override + @JsonKey(name: "outlet_name") + final String? outletName; + @override + @JsonKey(name: "generated_at") + final String? generatedAt; + + @override + String toString() { + return 'InventorySummaryDto(totalProducts: $totalProducts, totalIngredients: $totalIngredients, totalValue: $totalValue, lowStockProducts: $lowStockProducts, lowStockIngredients: $lowStockIngredients, zeroStockProducts: $zeroStockProducts, zeroStockIngredients: $zeroStockIngredients, totalSoldProducts: $totalSoldProducts, totalSoldIngredients: $totalSoldIngredients, outletId: $outletId, outletName: $outletName, generatedAt: $generatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventorySummaryDtoImpl && + (identical(other.totalProducts, totalProducts) || + other.totalProducts == totalProducts) && + (identical(other.totalIngredients, totalIngredients) || + other.totalIngredients == totalIngredients) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.lowStockProducts, lowStockProducts) || + other.lowStockProducts == lowStockProducts) && + (identical(other.lowStockIngredients, lowStockIngredients) || + other.lowStockIngredients == lowStockIngredients) && + (identical(other.zeroStockProducts, zeroStockProducts) || + other.zeroStockProducts == zeroStockProducts) && + (identical(other.zeroStockIngredients, zeroStockIngredients) || + other.zeroStockIngredients == zeroStockIngredients) && + (identical(other.totalSoldProducts, totalSoldProducts) || + other.totalSoldProducts == totalSoldProducts) && + (identical(other.totalSoldIngredients, totalSoldIngredients) || + other.totalSoldIngredients == totalSoldIngredients) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.outletName, outletName) || + other.outletName == outletName) && + (identical(other.generatedAt, generatedAt) || + other.generatedAt == generatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + totalProducts, + totalIngredients, + totalValue, + lowStockProducts, + lowStockIngredients, + zeroStockProducts, + zeroStockIngredients, + totalSoldProducts, + totalSoldIngredients, + outletId, + outletName, + generatedAt, + ); + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventorySummaryDtoImplCopyWith<_$InventorySummaryDtoImpl> get copyWith => + __$$InventorySummaryDtoImplCopyWithImpl<_$InventorySummaryDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$InventorySummaryDtoImplToJson(this); + } +} + +abstract class _InventorySummaryDto implements InventorySummaryDto { + const factory _InventorySummaryDto({ + @JsonKey(name: "total_products") final int? totalProducts, + @JsonKey(name: "total_ingredients") final int? totalIngredients, + @JsonKey(name: "total_value") final int? totalValue, + @JsonKey(name: "low_stock_products") final int? lowStockProducts, + @JsonKey(name: "low_stock_ingredients") final int? lowStockIngredients, + @JsonKey(name: "zero_stock_products") final int? zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") final int? zeroStockIngredients, + @JsonKey(name: "total_sold_products") final int? totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") final int? totalSoldIngredients, + @JsonKey(name: "outlet_id") final String? outletId, + @JsonKey(name: "outlet_name") final String? outletName, + @JsonKey(name: "generated_at") final String? generatedAt, + }) = _$InventorySummaryDtoImpl; + + factory _InventorySummaryDto.fromJson(Map json) = + _$InventorySummaryDtoImpl.fromJson; + + @override + @JsonKey(name: "total_products") + int? get totalProducts; + @override + @JsonKey(name: "total_ingredients") + int? get totalIngredients; + @override + @JsonKey(name: "total_value") + int? get totalValue; + @override + @JsonKey(name: "low_stock_products") + int? get lowStockProducts; + @override + @JsonKey(name: "low_stock_ingredients") + int? get lowStockIngredients; + @override + @JsonKey(name: "zero_stock_products") + int? get zeroStockProducts; + @override + @JsonKey(name: "zero_stock_ingredients") + int? get zeroStockIngredients; + @override + @JsonKey(name: "total_sold_products") + int? get totalSoldProducts; + @override + @JsonKey(name: "total_sold_ingredients") + int? get totalSoldIngredients; + @override + @JsonKey(name: "outlet_id") + String? get outletId; + @override + @JsonKey(name: "outlet_name") + String? get outletName; + @override + @JsonKey(name: "generated_at") + String? get generatedAt; + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventorySummaryDtoImplCopyWith<_$InventorySummaryDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +InventoryProductDto _$InventoryProductDtoFromJson(Map json) { + return _InventoryProductDto.fromJson(json); +} + +/// @nodoc +mixin _$InventoryProductDto { + @JsonKey(name: "id") + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: "product_id") + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: "product_name") + String? get productName => throw _privateConstructorUsedError; + @JsonKey(name: "category_name") + String? get categoryName => throw _privateConstructorUsedError; + @JsonKey(name: "quantity") + int? get quantity => throw _privateConstructorUsedError; + @JsonKey(name: "reorder_level") + int? get reorderLevel => throw _privateConstructorUsedError; + @JsonKey(name: "unit_cost") + int? get unitCost => throw _privateConstructorUsedError; + @JsonKey(name: "total_value") + int? get totalValue => throw _privateConstructorUsedError; + @JsonKey(name: "total_in") + int? get totalIn => throw _privateConstructorUsedError; + @JsonKey(name: "total_out") + int? get totalOut => throw _privateConstructorUsedError; + @JsonKey(name: "is_low_stock") + bool? get isLowStock => throw _privateConstructorUsedError; + @JsonKey(name: "is_zero_stock") + bool? get isZeroStock => throw _privateConstructorUsedError; + @JsonKey(name: "updated_at") + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this InventoryProductDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryProductDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryProductDtoCopyWith<$Res> { + factory $InventoryProductDtoCopyWith( + InventoryProductDto value, + $Res Function(InventoryProductDto) then, + ) = _$InventoryProductDtoCopyWithImpl<$Res, InventoryProductDto>; + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "product_id") String? productId, + @JsonKey(name: "product_name") String? productName, + @JsonKey(name: "category_name") String? categoryName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class _$InventoryProductDtoCopyWithImpl<$Res, $Val extends InventoryProductDto> + implements $InventoryProductDtoCopyWith<$Res> { + _$InventoryProductDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? productId = freezed, + Object? productName = freezed, + Object? categoryName = freezed, + Object? quantity = freezed, + Object? reorderLevel = freezed, + Object? unitCost = freezed, + Object? totalValue = freezed, + Object? totalIn = freezed, + Object? totalOut = freezed, + Object? isLowStock = freezed, + Object? isZeroStock = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + reorderLevel: freezed == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int?, + unitCost: freezed == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + totalIn: freezed == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int?, + totalOut: freezed == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int?, + isLowStock: freezed == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool?, + isZeroStock: freezed == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventoryProductDtoImplCopyWith<$Res> + implements $InventoryProductDtoCopyWith<$Res> { + factory _$$InventoryProductDtoImplCopyWith( + _$InventoryProductDtoImpl value, + $Res Function(_$InventoryProductDtoImpl) then, + ) = __$$InventoryProductDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "product_id") String? productId, + @JsonKey(name: "product_name") String? productName, + @JsonKey(name: "category_name") String? categoryName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class __$$InventoryProductDtoImplCopyWithImpl<$Res> + extends _$InventoryProductDtoCopyWithImpl<$Res, _$InventoryProductDtoImpl> + implements _$$InventoryProductDtoImplCopyWith<$Res> { + __$$InventoryProductDtoImplCopyWithImpl( + _$InventoryProductDtoImpl _value, + $Res Function(_$InventoryProductDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? productId = freezed, + Object? productName = freezed, + Object? categoryName = freezed, + Object? quantity = freezed, + Object? reorderLevel = freezed, + Object? unitCost = freezed, + Object? totalValue = freezed, + Object? totalIn = freezed, + Object? totalOut = freezed, + Object? isLowStock = freezed, + Object? isZeroStock = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$InventoryProductDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + reorderLevel: freezed == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int?, + unitCost: freezed == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + totalIn: freezed == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int?, + totalOut: freezed == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int?, + isLowStock: freezed == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool?, + isZeroStock: freezed == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$InventoryProductDtoImpl implements _InventoryProductDto { + const _$InventoryProductDtoImpl({ + @JsonKey(name: "id") this.id, + @JsonKey(name: "product_id") this.productId, + @JsonKey(name: "product_name") this.productName, + @JsonKey(name: "category_name") this.categoryName, + @JsonKey(name: "quantity") this.quantity, + @JsonKey(name: "reorder_level") this.reorderLevel, + @JsonKey(name: "unit_cost") this.unitCost, + @JsonKey(name: "total_value") this.totalValue, + @JsonKey(name: "total_in") this.totalIn, + @JsonKey(name: "total_out") this.totalOut, + @JsonKey(name: "is_low_stock") this.isLowStock, + @JsonKey(name: "is_zero_stock") this.isZeroStock, + @JsonKey(name: "updated_at") this.updatedAt, + }); + + factory _$InventoryProductDtoImpl.fromJson(Map json) => + _$$InventoryProductDtoImplFromJson(json); + + @override + @JsonKey(name: "id") + final String? id; + @override + @JsonKey(name: "product_id") + final String? productId; + @override + @JsonKey(name: "product_name") + final String? productName; + @override + @JsonKey(name: "category_name") + final String? categoryName; + @override + @JsonKey(name: "quantity") + final int? quantity; + @override + @JsonKey(name: "reorder_level") + final int? reorderLevel; + @override + @JsonKey(name: "unit_cost") + final int? unitCost; + @override + @JsonKey(name: "total_value") + final int? totalValue; + @override + @JsonKey(name: "total_in") + final int? totalIn; + @override + @JsonKey(name: "total_out") + final int? totalOut; + @override + @JsonKey(name: "is_low_stock") + final bool? isLowStock; + @override + @JsonKey(name: "is_zero_stock") + final bool? isZeroStock; + @override + @JsonKey(name: "updated_at") + final String? updatedAt; + + @override + String toString() { + return 'InventoryProductDto(id: $id, productId: $productId, productName: $productName, categoryName: $categoryName, quantity: $quantity, reorderLevel: $reorderLevel, unitCost: $unitCost, totalValue: $totalValue, totalIn: $totalIn, totalOut: $totalOut, isLowStock: $isLowStock, isZeroStock: $isZeroStock, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryProductDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.reorderLevel, reorderLevel) || + other.reorderLevel == reorderLevel) && + (identical(other.unitCost, unitCost) || + other.unitCost == unitCost) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.totalIn, totalIn) || other.totalIn == totalIn) && + (identical(other.totalOut, totalOut) || + other.totalOut == totalOut) && + (identical(other.isLowStock, isLowStock) || + other.isLowStock == isLowStock) && + (identical(other.isZeroStock, isZeroStock) || + other.isZeroStock == isZeroStock) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + productId, + productName, + categoryName, + quantity, + reorderLevel, + unitCost, + totalValue, + totalIn, + totalOut, + isLowStock, + isZeroStock, + updatedAt, + ); + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryProductDtoImplCopyWith<_$InventoryProductDtoImpl> get copyWith => + __$$InventoryProductDtoImplCopyWithImpl<_$InventoryProductDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$InventoryProductDtoImplToJson(this); + } +} + +abstract class _InventoryProductDto implements InventoryProductDto { + const factory _InventoryProductDto({ + @JsonKey(name: "id") final String? id, + @JsonKey(name: "product_id") final String? productId, + @JsonKey(name: "product_name") final String? productName, + @JsonKey(name: "category_name") final String? categoryName, + @JsonKey(name: "quantity") final int? quantity, + @JsonKey(name: "reorder_level") final int? reorderLevel, + @JsonKey(name: "unit_cost") final int? unitCost, + @JsonKey(name: "total_value") final int? totalValue, + @JsonKey(name: "total_in") final int? totalIn, + @JsonKey(name: "total_out") final int? totalOut, + @JsonKey(name: "is_low_stock") final bool? isLowStock, + @JsonKey(name: "is_zero_stock") final bool? isZeroStock, + @JsonKey(name: "updated_at") final String? updatedAt, + }) = _$InventoryProductDtoImpl; + + factory _InventoryProductDto.fromJson(Map json) = + _$InventoryProductDtoImpl.fromJson; + + @override + @JsonKey(name: "id") + String? get id; + @override + @JsonKey(name: "product_id") + String? get productId; + @override + @JsonKey(name: "product_name") + String? get productName; + @override + @JsonKey(name: "category_name") + String? get categoryName; + @override + @JsonKey(name: "quantity") + int? get quantity; + @override + @JsonKey(name: "reorder_level") + int? get reorderLevel; + @override + @JsonKey(name: "unit_cost") + int? get unitCost; + @override + @JsonKey(name: "total_value") + int? get totalValue; + @override + @JsonKey(name: "total_in") + int? get totalIn; + @override + @JsonKey(name: "total_out") + int? get totalOut; + @override + @JsonKey(name: "is_low_stock") + bool? get isLowStock; + @override + @JsonKey(name: "is_zero_stock") + bool? get isZeroStock; + @override + @JsonKey(name: "updated_at") + String? get updatedAt; + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryProductDtoImplCopyWith<_$InventoryProductDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +InventoryIngredientDto _$InventoryIngredientDtoFromJson( + Map json, +) { + return _InventoryIngredientDto.fromJson(json); +} + +/// @nodoc +mixin _$InventoryIngredientDto { + @JsonKey(name: "id") + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: "ingredient_id") + String? get ingredientId => throw _privateConstructorUsedError; + @JsonKey(name: "ingredient_name") + String? get ingredientName => throw _privateConstructorUsedError; + @JsonKey(name: "unit_name") + String? get unitName => throw _privateConstructorUsedError; + @JsonKey(name: "quantity") + int? get quantity => throw _privateConstructorUsedError; + @JsonKey(name: "reorder_level") + int? get reorderLevel => throw _privateConstructorUsedError; + @JsonKey(name: "unit_cost") + int? get unitCost => throw _privateConstructorUsedError; + @JsonKey(name: "total_value") + int? get totalValue => throw _privateConstructorUsedError; + @JsonKey(name: "total_in") + int? get totalIn => throw _privateConstructorUsedError; + @JsonKey(name: "total_out") + int? get totalOut => throw _privateConstructorUsedError; + @JsonKey(name: "is_low_stock") + bool? get isLowStock => throw _privateConstructorUsedError; + @JsonKey(name: "is_zero_stock") + bool? get isZeroStock => throw _privateConstructorUsedError; + @JsonKey(name: "updated_at") + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this InventoryIngredientDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryIngredientDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryIngredientDtoCopyWith<$Res> { + factory $InventoryIngredientDtoCopyWith( + InventoryIngredientDto value, + $Res Function(InventoryIngredientDto) then, + ) = _$InventoryIngredientDtoCopyWithImpl<$Res, InventoryIngredientDto>; + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "ingredient_id") String? ingredientId, + @JsonKey(name: "ingredient_name") String? ingredientName, + @JsonKey(name: "unit_name") String? unitName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class _$InventoryIngredientDtoCopyWithImpl< + $Res, + $Val extends InventoryIngredientDto +> + implements $InventoryIngredientDtoCopyWith<$Res> { + _$InventoryIngredientDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? ingredientId = freezed, + Object? ingredientName = freezed, + Object? unitName = freezed, + Object? quantity = freezed, + Object? reorderLevel = freezed, + Object? unitCost = freezed, + Object? totalValue = freezed, + Object? totalIn = freezed, + Object? totalOut = freezed, + Object? isLowStock = freezed, + Object? isZeroStock = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + ingredientId: freezed == ingredientId + ? _value.ingredientId + : ingredientId // ignore: cast_nullable_to_non_nullable + as String?, + ingredientName: freezed == ingredientName + ? _value.ingredientName + : ingredientName // ignore: cast_nullable_to_non_nullable + as String?, + unitName: freezed == unitName + ? _value.unitName + : unitName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + reorderLevel: freezed == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int?, + unitCost: freezed == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + totalIn: freezed == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int?, + totalOut: freezed == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int?, + isLowStock: freezed == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool?, + isZeroStock: freezed == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventoryIngredientDtoImplCopyWith<$Res> + implements $InventoryIngredientDtoCopyWith<$Res> { + factory _$$InventoryIngredientDtoImplCopyWith( + _$InventoryIngredientDtoImpl value, + $Res Function(_$InventoryIngredientDtoImpl) then, + ) = __$$InventoryIngredientDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "ingredient_id") String? ingredientId, + @JsonKey(name: "ingredient_name") String? ingredientName, + @JsonKey(name: "unit_name") String? unitName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class __$$InventoryIngredientDtoImplCopyWithImpl<$Res> + extends + _$InventoryIngredientDtoCopyWithImpl<$Res, _$InventoryIngredientDtoImpl> + implements _$$InventoryIngredientDtoImplCopyWith<$Res> { + __$$InventoryIngredientDtoImplCopyWithImpl( + _$InventoryIngredientDtoImpl _value, + $Res Function(_$InventoryIngredientDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? ingredientId = freezed, + Object? ingredientName = freezed, + Object? unitName = freezed, + Object? quantity = freezed, + Object? reorderLevel = freezed, + Object? unitCost = freezed, + Object? totalValue = freezed, + Object? totalIn = freezed, + Object? totalOut = freezed, + Object? isLowStock = freezed, + Object? isZeroStock = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$InventoryIngredientDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + ingredientId: freezed == ingredientId + ? _value.ingredientId + : ingredientId // ignore: cast_nullable_to_non_nullable + as String?, + ingredientName: freezed == ingredientName + ? _value.ingredientName + : ingredientName // ignore: cast_nullable_to_non_nullable + as String?, + unitName: freezed == unitName + ? _value.unitName + : unitName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + reorderLevel: freezed == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int?, + unitCost: freezed == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + totalIn: freezed == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int?, + totalOut: freezed == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int?, + isLowStock: freezed == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool?, + isZeroStock: freezed == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$InventoryIngredientDtoImpl implements _InventoryIngredientDto { + const _$InventoryIngredientDtoImpl({ + @JsonKey(name: "id") this.id, + @JsonKey(name: "ingredient_id") this.ingredientId, + @JsonKey(name: "ingredient_name") this.ingredientName, + @JsonKey(name: "unit_name") this.unitName, + @JsonKey(name: "quantity") this.quantity, + @JsonKey(name: "reorder_level") this.reorderLevel, + @JsonKey(name: "unit_cost") this.unitCost, + @JsonKey(name: "total_value") this.totalValue, + @JsonKey(name: "total_in") this.totalIn, + @JsonKey(name: "total_out") this.totalOut, + @JsonKey(name: "is_low_stock") this.isLowStock, + @JsonKey(name: "is_zero_stock") this.isZeroStock, + @JsonKey(name: "updated_at") this.updatedAt, + }); + + factory _$InventoryIngredientDtoImpl.fromJson(Map json) => + _$$InventoryIngredientDtoImplFromJson(json); + + @override + @JsonKey(name: "id") + final String? id; + @override + @JsonKey(name: "ingredient_id") + final String? ingredientId; + @override + @JsonKey(name: "ingredient_name") + final String? ingredientName; + @override + @JsonKey(name: "unit_name") + final String? unitName; + @override + @JsonKey(name: "quantity") + final int? quantity; + @override + @JsonKey(name: "reorder_level") + final int? reorderLevel; + @override + @JsonKey(name: "unit_cost") + final int? unitCost; + @override + @JsonKey(name: "total_value") + final int? totalValue; + @override + @JsonKey(name: "total_in") + final int? totalIn; + @override + @JsonKey(name: "total_out") + final int? totalOut; + @override + @JsonKey(name: "is_low_stock") + final bool? isLowStock; + @override + @JsonKey(name: "is_zero_stock") + final bool? isZeroStock; + @override + @JsonKey(name: "updated_at") + final String? updatedAt; + + @override + String toString() { + return 'InventoryIngredientDto(id: $id, ingredientId: $ingredientId, ingredientName: $ingredientName, unitName: $unitName, quantity: $quantity, reorderLevel: $reorderLevel, unitCost: $unitCost, totalValue: $totalValue, totalIn: $totalIn, totalOut: $totalOut, isLowStock: $isLowStock, isZeroStock: $isZeroStock, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryIngredientDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.ingredientId, ingredientId) || + other.ingredientId == ingredientId) && + (identical(other.ingredientName, ingredientName) || + other.ingredientName == ingredientName) && + (identical(other.unitName, unitName) || + other.unitName == unitName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.reorderLevel, reorderLevel) || + other.reorderLevel == reorderLevel) && + (identical(other.unitCost, unitCost) || + other.unitCost == unitCost) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.totalIn, totalIn) || other.totalIn == totalIn) && + (identical(other.totalOut, totalOut) || + other.totalOut == totalOut) && + (identical(other.isLowStock, isLowStock) || + other.isLowStock == isLowStock) && + (identical(other.isZeroStock, isZeroStock) || + other.isZeroStock == isZeroStock) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + ingredientId, + ingredientName, + unitName, + quantity, + reorderLevel, + unitCost, + totalValue, + totalIn, + totalOut, + isLowStock, + isZeroStock, + updatedAt, + ); + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryIngredientDtoImplCopyWith<_$InventoryIngredientDtoImpl> + get copyWith => + __$$InventoryIngredientDtoImplCopyWithImpl<_$InventoryIngredientDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$InventoryIngredientDtoImplToJson(this); + } +} + +abstract class _InventoryIngredientDto implements InventoryIngredientDto { + const factory _InventoryIngredientDto({ + @JsonKey(name: "id") final String? id, + @JsonKey(name: "ingredient_id") final String? ingredientId, + @JsonKey(name: "ingredient_name") final String? ingredientName, + @JsonKey(name: "unit_name") final String? unitName, + @JsonKey(name: "quantity") final int? quantity, + @JsonKey(name: "reorder_level") final int? reorderLevel, + @JsonKey(name: "unit_cost") final int? unitCost, + @JsonKey(name: "total_value") final int? totalValue, + @JsonKey(name: "total_in") final int? totalIn, + @JsonKey(name: "total_out") final int? totalOut, + @JsonKey(name: "is_low_stock") final bool? isLowStock, + @JsonKey(name: "is_zero_stock") final bool? isZeroStock, + @JsonKey(name: "updated_at") final String? updatedAt, + }) = _$InventoryIngredientDtoImpl; + + factory _InventoryIngredientDto.fromJson(Map json) = + _$InventoryIngredientDtoImpl.fromJson; + + @override + @JsonKey(name: "id") + String? get id; + @override + @JsonKey(name: "ingredient_id") + String? get ingredientId; + @override + @JsonKey(name: "ingredient_name") + String? get ingredientName; + @override + @JsonKey(name: "unit_name") + String? get unitName; + @override + @JsonKey(name: "quantity") + int? get quantity; + @override + @JsonKey(name: "reorder_level") + int? get reorderLevel; + @override + @JsonKey(name: "unit_cost") + int? get unitCost; + @override + @JsonKey(name: "total_value") + int? get totalValue; + @override + @JsonKey(name: "total_in") + int? get totalIn; + @override + @JsonKey(name: "total_out") + int? get totalOut; + @override + @JsonKey(name: "is_low_stock") + bool? get isLowStock; + @override + @JsonKey(name: "is_zero_stock") + bool? get isZeroStock; + @override + @JsonKey(name: "updated_at") + String? get updatedAt; + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryIngredientDtoImplCopyWith<_$InventoryIngredientDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/analytic/analytic_dtos.g.dart b/lib/infrastructure/analytic/analytic_dtos.g.dart index 044d525..e1f95fc 100644 --- a/lib/infrastructure/analytic/analytic_dtos.g.dart +++ b/lib/infrastructure/analytic/analytic_dtos.g.dart @@ -257,3 +257,131 @@ Map _$$CategoryAnalyticItemDtoImplToJson( 'product_count': instance.productCount, 'order_count': instance.orderCount, }; + +_$InventoryAnalyticDtoImpl _$$InventoryAnalyticDtoImplFromJson( + Map json, +) => _$InventoryAnalyticDtoImpl( + summary: json['summary'] == null + ? null + : InventorySummaryDto.fromJson(json['summary'] as Map), + products: (json['products'] as List?) + ?.map((e) => InventoryProductDto.fromJson(e as Map)) + .toList(), + ingredients: (json['ingredients'] as List?) + ?.map((e) => InventoryIngredientDto.fromJson(e as Map)) + .toList(), +); + +Map _$$InventoryAnalyticDtoImplToJson( + _$InventoryAnalyticDtoImpl instance, +) => { + 'summary': instance.summary, + 'products': instance.products, + 'ingredients': instance.ingredients, +}; + +_$InventorySummaryDtoImpl _$$InventorySummaryDtoImplFromJson( + Map json, +) => _$InventorySummaryDtoImpl( + totalProducts: (json['total_products'] as num?)?.toInt(), + totalIngredients: (json['total_ingredients'] as num?)?.toInt(), + totalValue: (json['total_value'] as num?)?.toInt(), + lowStockProducts: (json['low_stock_products'] as num?)?.toInt(), + lowStockIngredients: (json['low_stock_ingredients'] as num?)?.toInt(), + zeroStockProducts: (json['zero_stock_products'] as num?)?.toInt(), + zeroStockIngredients: (json['zero_stock_ingredients'] as num?)?.toInt(), + totalSoldProducts: (json['total_sold_products'] as num?)?.toInt(), + totalSoldIngredients: (json['total_sold_ingredients'] as num?)?.toInt(), + outletId: json['outlet_id'] as String?, + outletName: json['outlet_name'] as String?, + generatedAt: json['generated_at'] as String?, +); + +Map _$$InventorySummaryDtoImplToJson( + _$InventorySummaryDtoImpl instance, +) => { + 'total_products': instance.totalProducts, + 'total_ingredients': instance.totalIngredients, + 'total_value': instance.totalValue, + 'low_stock_products': instance.lowStockProducts, + 'low_stock_ingredients': instance.lowStockIngredients, + 'zero_stock_products': instance.zeroStockProducts, + 'zero_stock_ingredients': instance.zeroStockIngredients, + 'total_sold_products': instance.totalSoldProducts, + 'total_sold_ingredients': instance.totalSoldIngredients, + 'outlet_id': instance.outletId, + 'outlet_name': instance.outletName, + 'generated_at': instance.generatedAt, +}; + +_$InventoryProductDtoImpl _$$InventoryProductDtoImplFromJson( + Map json, +) => _$InventoryProductDtoImpl( + id: json['id'] as String?, + productId: json['product_id'] as String?, + productName: json['product_name'] as String?, + categoryName: json['category_name'] as String?, + quantity: (json['quantity'] as num?)?.toInt(), + reorderLevel: (json['reorder_level'] as num?)?.toInt(), + unitCost: (json['unit_cost'] as num?)?.toInt(), + totalValue: (json['total_value'] as num?)?.toInt(), + totalIn: (json['total_in'] as num?)?.toInt(), + totalOut: (json['total_out'] as num?)?.toInt(), + isLowStock: json['is_low_stock'] as bool?, + isZeroStock: json['is_zero_stock'] as bool?, + updatedAt: json['updated_at'] as String?, +); + +Map _$$InventoryProductDtoImplToJson( + _$InventoryProductDtoImpl instance, +) => { + 'id': instance.id, + 'product_id': instance.productId, + 'product_name': instance.productName, + 'category_name': instance.categoryName, + 'quantity': instance.quantity, + 'reorder_level': instance.reorderLevel, + 'unit_cost': instance.unitCost, + 'total_value': instance.totalValue, + 'total_in': instance.totalIn, + 'total_out': instance.totalOut, + 'is_low_stock': instance.isLowStock, + 'is_zero_stock': instance.isZeroStock, + 'updated_at': instance.updatedAt, +}; + +_$InventoryIngredientDtoImpl _$$InventoryIngredientDtoImplFromJson( + Map json, +) => _$InventoryIngredientDtoImpl( + id: json['id'] as String?, + ingredientId: json['ingredient_id'] as String?, + ingredientName: json['ingredient_name'] as String?, + unitName: json['unit_name'] as String?, + quantity: (json['quantity'] as num?)?.toInt(), + reorderLevel: (json['reorder_level'] as num?)?.toInt(), + unitCost: (json['unit_cost'] as num?)?.toInt(), + totalValue: (json['total_value'] as num?)?.toInt(), + totalIn: (json['total_in'] as num?)?.toInt(), + totalOut: (json['total_out'] as num?)?.toInt(), + isLowStock: json['is_low_stock'] as bool?, + isZeroStock: json['is_zero_stock'] as bool?, + updatedAt: json['updated_at'] as String?, +); + +Map _$$InventoryIngredientDtoImplToJson( + _$InventoryIngredientDtoImpl instance, +) => { + 'id': instance.id, + 'ingredient_id': instance.ingredientId, + 'ingredient_name': instance.ingredientName, + 'unit_name': instance.unitName, + 'quantity': instance.quantity, + 'reorder_level': instance.reorderLevel, + 'unit_cost': instance.unitCost, + 'total_value': instance.totalValue, + 'total_in': instance.totalIn, + 'total_out': instance.totalOut, + 'is_low_stock': instance.isLowStock, + 'is_zero_stock': instance.isZeroStock, + 'updated_at': instance.updatedAt, +}; diff --git a/lib/infrastructure/analytic/datasource/remote_data_provider.dart b/lib/infrastructure/analytic/datasource/remote_data_provider.dart index 9fd53eb..83ab43f 100644 --- a/lib/infrastructure/analytic/datasource/remote_data_provider.dart +++ b/lib/infrastructure/analytic/datasource/remote_data_provider.dart @@ -98,4 +98,32 @@ class AnalyticRemoteDataProvider { return DC.error(AnalyticFailure.serverError(e)); } } + + Future> fetchInventory({ + required String outletId, + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + final response = await _apiClient.get( + '${ApiPath.inventoryReportDetail}/$outletId', + params: { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = InventoryAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchInventoryError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } } diff --git a/lib/infrastructure/analytic/dto/inventory_analytic_dto.dart b/lib/infrastructure/analytic/dto/inventory_analytic_dto.dart new file mode 100644 index 0000000..a76c149 --- /dev/null +++ b/lib/infrastructure/analytic/dto/inventory_analytic_dto.dart @@ -0,0 +1,139 @@ +part of '../analytic_dtos.dart'; + +@freezed +class InventoryAnalyticDto with _$InventoryAnalyticDto { + const InventoryAnalyticDto._(); + + const factory InventoryAnalyticDto({ + @JsonKey(name: "summary") InventorySummaryDto? summary, + @JsonKey(name: "products") List? products, + @JsonKey(name: "ingredients") List? ingredients, + }) = _InventoryAnalyticDto; + + factory InventoryAnalyticDto.fromJson(Map json) => + _$InventoryAnalyticDtoFromJson(json); + + InventoryAnalytic toDomain() => InventoryAnalytic( + summary: summary?.toDomain() ?? InventorySummary.empty(), + products: products?.map((e) => e.toDomain()).toList() ?? [], + ingredients: ingredients?.map((e) => e.toDomain()).toList() ?? [], + ); +} + +@freezed +class InventorySummaryDto with _$InventorySummaryDto { + const factory InventorySummaryDto({ + @JsonKey(name: "total_products") int? totalProducts, + @JsonKey(name: "total_ingredients") int? totalIngredients, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "low_stock_products") int? lowStockProducts, + @JsonKey(name: "low_stock_ingredients") int? lowStockIngredients, + @JsonKey(name: "zero_stock_products") int? zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") int? zeroStockIngredients, + @JsonKey(name: "total_sold_products") int? totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") int? totalSoldIngredients, + @JsonKey(name: "outlet_id") String? outletId, + @JsonKey(name: "outlet_name") String? outletName, + @JsonKey(name: "generated_at") String? generatedAt, + }) = _InventorySummaryDto; + + factory InventorySummaryDto.fromJson(Map json) => + _$InventorySummaryDtoFromJson(json); +} + +extension InventorySummaryDtoX on InventorySummaryDto { + InventorySummary toDomain() => InventorySummary( + totalProducts: totalProducts ?? 0, + totalIngredients: totalIngredients ?? 0, + totalValue: totalValue ?? 0, + lowStockProducts: lowStockProducts ?? 0, + lowStockIngredients: lowStockIngredients ?? 0, + zeroStockProducts: zeroStockProducts ?? 0, + zeroStockIngredients: zeroStockIngredients ?? 0, + totalSoldProducts: totalSoldProducts ?? 0, + totalSoldIngredients: totalSoldIngredients ?? 0, + outletId: outletId ?? "", + outletName: outletName ?? "", + generatedAt: generatedAt ?? "", + ); +} + +@freezed +class InventoryProductDto with _$InventoryProductDto { + const factory InventoryProductDto({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "product_id") String? productId, + @JsonKey(name: "product_name") String? productName, + @JsonKey(name: "category_name") String? categoryName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }) = _InventoryProductDto; + + factory InventoryProductDto.fromJson(Map json) => + _$InventoryProductDtoFromJson(json); +} + +extension InventoryProductDtoX on InventoryProductDto { + InventoryProduct toDomain() => InventoryProduct( + id: id ?? "", + productId: productId ?? "", + productName: productName ?? "", + categoryName: categoryName ?? "", + quantity: quantity ?? 0, + reorderLevel: reorderLevel ?? 0, + unitCost: unitCost ?? 0, + totalValue: totalValue ?? 0, + totalIn: totalIn ?? 0, + totalOut: totalOut ?? 0, + isLowStock: isLowStock ?? false, + isZeroStock: isZeroStock ?? false, + updatedAt: updatedAt ?? "", + ); +} + +@freezed +class InventoryIngredientDto with _$InventoryIngredientDto { + const factory InventoryIngredientDto({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "ingredient_id") String? ingredientId, + @JsonKey(name: "ingredient_name") String? ingredientName, + @JsonKey(name: "unit_name") String? unitName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }) = _InventoryIngredientDto; + + factory InventoryIngredientDto.fromJson(Map json) => + _$InventoryIngredientDtoFromJson(json); +} + +extension InventoryIngredientDtoX on InventoryIngredientDto { + InventoryIngredient toDomain() => InventoryIngredient( + id: id ?? "", + ingredientId: ingredientId ?? "", + ingredientName: ingredientName ?? "", + unitName: unitName ?? "", + quantity: quantity ?? 0, + reorderLevel: reorderLevel ?? 0, + unitCost: unitCost ?? 0, + totalValue: totalValue ?? 0, + totalIn: totalIn ?? 0, + totalOut: totalOut ?? 0, + isLowStock: isLowStock ?? false, + isZeroStock: isZeroStock ?? false, + updatedAt: updatedAt ?? "", + ); +} diff --git a/lib/infrastructure/analytic/repositories/analytic_repository.dart b/lib/infrastructure/analytic/repositories/analytic_repository.dart index 3acc60a..3001595 100644 --- a/lib/infrastructure/analytic/repositories/analytic_repository.dart +++ b/lib/infrastructure/analytic/repositories/analytic_repository.dart @@ -5,14 +5,17 @@ import 'package:injectable/injectable.dart'; import '../../../domain/analytic/analytic.dart'; import '../../../domain/analytic/repositories/i_analytic_repository.dart'; +import '../../../domain/auth/auth.dart'; +import '../../auth/datasources/local_data_provider.dart'; import '../datasource/remote_data_provider.dart'; @Injectable(as: IAnalyticRepository) class AnalyticRepository implements IAnalyticRepository { final AnalyticRemoteDataProvider _dataProvider; + final AuthLocalDataProvider _authLocalDataProvider; final String _logName = 'AnalyticRepository'; - AnalyticRepository(this._dataProvider); + AnalyticRepository(this._dataProvider, this._authLocalDataProvider); @override Future> getSales({ @@ -85,4 +88,31 @@ class AnalyticRepository implements IAnalyticRepository { return left(const AnalyticFailure.unexpectedError()); } } + + @override + Future> getInventory({ + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + User currentUser = await _authLocalDataProvider.currentUser(); + + final result = await _dataProvider.fetchInventory( + outletId: currentUser.outletId, + dateFrom: dateFrom, + dateTo: dateTo, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.toDomain(); + + return right(auth); + } catch (e, s) { + log('getInventoryError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } } diff --git a/lib/injection.config.dart b/lib/injection.config.dart index e2ca7f3..e51896f 100644 --- a/lib/injection.config.dart +++ b/lib/injection.config.dart @@ -11,6 +11,8 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:apskel_owner_flutter/application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart' as _i1038; +import 'package:apskel_owner_flutter/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart' + as _i785; import 'package:apskel_owner_flutter/application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart' as _i11; import 'package:apskel_owner_flutter/application/analytic/sales_loader/sales_loader_bloc.dart' @@ -120,9 +122,6 @@ extension GetItInjectableX on _i174.GetIt { gh.factory<_i866.AnalyticRemoteDataProvider>( () => _i866.AnalyticRemoteDataProvider(gh<_i115.ApiClient>()), ); - gh.factory<_i477.IAnalyticRepository>( - () => _i393.AnalyticRepository(gh<_i866.AnalyticRemoteDataProvider>()), - ); gh.factory<_i49.IAuthRepository>( () => _i1035.AuthRepository( gh<_i991.AuthLocalDataProvider>(), @@ -132,6 +131,12 @@ extension GetItInjectableX on _i174.GetIt { gh.factory<_i419.IProductRepository>( () => _i121.ProductRepository(gh<_i823.ProductRemoteDataProvider>()), ); + gh.factory<_i477.IAnalyticRepository>( + () => _i393.AnalyticRepository( + gh<_i866.AnalyticRemoteDataProvider>(), + gh<_i991.AuthLocalDataProvider>(), + ), + ); gh.factory<_i1020.ICategoryRepository>( () => _i869.CategoryRepository(gh<_i333.CategoryRemoteDataProvider>()), ); @@ -150,6 +155,9 @@ extension GetItInjectableX on _i174.GetIt { gh.factory<_i1038.CategoryAnalyticLoaderBloc>( () => _i1038.CategoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()), ); + gh.factory<_i785.InventoryAnalyticLoaderBloc>( + () => _i785.InventoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); gh.factory<_i775.LoginFormBloc>( () => _i775.LoginFormBloc(gh<_i49.IAuthRepository>()), ); diff --git a/lib/presentation/pages/inventory/inventory_page.dart b/lib/presentation/pages/inventory/inventory_page.dart index 16cd5c7..f91b0f4 100644 --- a/lib/presentation/pages/inventory/inventory_page.dart +++ b/lib/presentation/pages/inventory/inventory_page.dart @@ -1,63 +1,33 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import '../../../application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart'; import '../../../common/theme/theme.dart'; +import '../../../domain/analytic/analytic.dart'; +import '../../../injection.dart'; import '../../components/appbar/appbar.dart'; import 'widgets/ingredient_tile.dart'; import 'widgets/product_tile.dart'; import 'widgets/stat_card.dart'; import 'widgets/tabbar_delegate.dart'; -// Sample inventory data for products -class ProductItem { - final String id; - final String name; - final String category; - final int quantity; - final double price; - final String status; - final String image; - - ProductItem({ - required this.id, - required this.name, - required this.category, - required this.quantity, - required this.price, - required this.status, - required this.image, - }); -} - -// Sample inventory data for ingredients -class IngredientItem { - final String id; - final String name; - final String unit; - final double quantity; - final double minQuantity; - final String status; - final String image; - - IngredientItem({ - required this.id, - required this.name, - required this.unit, - required this.quantity, - required this.minQuantity, - required this.status, - required this.image, - }); -} - // Custom SliverPersistentHeaderDelegate untuk TabBar @RoutePage() -class InventoryPage extends StatefulWidget { +class InventoryPage extends StatefulWidget implements AutoRouteWrapper { const InventoryPage({super.key}); @override State createState() => _InventoryPageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (_) => + getIt() + ..add(InventoryAnalyticLoaderEvent.fetched()), + child: this, + ); } class _InventoryPageState extends State @@ -68,111 +38,6 @@ class _InventoryPageState extends State late Animation _slideAnimation; late TabController _tabController; - final List productItems = [ - ProductItem( - id: '1', - name: 'Laptop Gaming ASUS ROG', - category: 'Elektronik', - quantity: 5, - price: 15000000, - status: 'available', - image: '💻', - ), - ProductItem( - id: '2', - name: 'Kemeja Formal Pria', - category: 'Fashion', - quantity: 25, - price: 250000, - status: 'available', - image: '👔', - ), - ProductItem( - id: '3', - name: 'Smartphone Samsung Galaxy', - category: 'Elektronik', - quantity: 12, - price: 8500000, - status: 'available', - image: '📱', - ), - ProductItem( - id: '4', - name: 'Tas Ransel Travel', - category: 'Fashion', - quantity: 8, - price: 350000, - status: 'low_stock', - image: '🎒', - ), - ProductItem( - id: '4', - name: 'Tas Ransel Travel', - category: 'Fashion', - quantity: 8, - price: 350000, - status: 'low_stock', - image: '🎒', - ), - ProductItem( - id: '4', - name: 'Tas Ransel Travel', - category: 'Fashion', - quantity: 8, - price: 350000, - status: 'low_stock', - image: '🎒', - ), - ]; - - final List ingredientItems = [ - IngredientItem( - id: '1', - name: 'Tepung Terigu', - unit: 'kg', - quantity: 50.5, - minQuantity: 10.0, - status: 'available', - image: '🌾', - ), - IngredientItem( - id: '2', - name: 'Gula Pasir', - unit: 'kg', - quantity: 2.5, - minQuantity: 5.0, - status: 'low_stock', - image: '🍬', - ), - IngredientItem( - id: '3', - name: 'Telur Ayam', - unit: 'butir', - quantity: 120, - minQuantity: 50, - status: 'available', - image: '🥚', - ), - IngredientItem( - id: '4', - name: 'Susu Segar', - unit: 'liter', - quantity: 0, - minQuantity: 10.0, - status: 'out_of_stock', - image: '🥛', - ), - IngredientItem( - id: '5', - name: 'Mentega', - unit: 'kg', - quantity: 15.2, - minQuantity: 5.0, - status: 'available', - image: '🧈', - ), - ]; - @override void initState() { super.initState(); @@ -244,95 +109,118 @@ class _InventoryPageState extends State Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, - body: FadeTransition( - opacity: _fadeAnimation, - child: SlideTransition( - position: _slideAnimation, - child: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) { - return [ - _buildSliverAppBar(), - SliverPersistentHeader( - pinned: true, - delegate: InventorySliverTabBarDelegate( - tabBar: TabBar( + 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, + ), + 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'), + ], + ), + ), + ), + ], + ), + ), + ), + ]; + }, + body: TabBarView( 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), - ), - ], - ), - 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'), - ], - ), - ), - ), + children: [ + _buildProductTab(state.inventoryAnalytic), + _buildIngredientTab(state.inventoryAnalytic), ], ), ), ), - ]; + ); }, - body: TabBarView( - controller: _tabController, - children: [_buildProductTab(), _buildIngredientTab()], - ), ), - ), - ), ); } @@ -347,41 +235,19 @@ class _InventoryPageState extends State ); } - Widget _buildProductTab() { + Widget _buildProductTab(InventoryAnalytic inventoryAnalytic) { return CustomScrollView( slivers: [ - SliverToBoxAdapter(child: _buildProductStats()), - SliverPadding( - padding: const EdgeInsets.all(16), - sliver: SliverGrid( - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 12, - mainAxisSpacing: 12, - childAspectRatio: 0.75, - ), - delegate: SliverChildBuilderDelegate( - (context, index) => - InventoryProductTile(item: productItems[index]), - childCount: productItems.length, - ), - ), + SliverToBoxAdapter( + child: _buildProductStats(inventoryAnalytic.summary), ), - ], - ); - } - - Widget _buildIngredientTab() { - return CustomScrollView( - slivers: [ - SliverToBoxAdapter(child: _buildIngredientStats()), SliverPadding( padding: const EdgeInsets.all(16), sliver: SliverList( delegate: SliverChildBuilderDelegate( (context, index) => - InventoryIngredientTile(item: ingredientItems[index]), - childCount: ingredientItems.length, + InventoryProductTile(item: inventoryAnalytic.products[index]), + childCount: inventoryAnalytic.products.length, ), ), ), @@ -389,15 +255,28 @@ class _InventoryPageState extends State ); } - Widget _buildProductStats() { - final totalProducts = productItems.length; - final availableProducts = productItems - .where((item) => item.status == 'available') - .length; - final lowStockProducts = productItems - .where((item) => item.status == 'low_stock') - .length; + Widget _buildIngredientTab(InventoryAnalytic inventoryAnalytic) { + return CustomScrollView( + slivers: [ + SliverToBoxAdapter( + child: _buildIngredientStats(inventoryAnalytic.summary), + ), + SliverPadding( + padding: const EdgeInsets.all(16), + sliver: SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => InventoryIngredientTile( + item: inventoryAnalytic.ingredients[index], + ), + childCount: inventoryAnalytic.ingredients.length, + ), + ), + ), + ], + ); + } + Widget _buildProductStats(InventorySummary inventory) { return Container( margin: const EdgeInsets.all(16), child: Column( @@ -407,20 +286,18 @@ class _InventoryPageState extends State Expanded( child: _buildStatCard( 'Total Produk', - totalProducts.toString(), + inventory.totalProducts.toString(), Icons.inventory_2_rounded, AppColor.primary, - '+12%', ), ), const SizedBox(width: 16), Expanded( child: _buildStatCard( - 'Tersedia', - availableProducts.toString(), + 'Produk Terjual', + inventory.totalSoldProducts.toString(), Icons.check_circle_rounded, AppColor.success, - '+5%', ), ), ], @@ -431,15 +308,19 @@ class _InventoryPageState extends State Expanded( child: _buildStatCard( 'Stok Rendah', - lowStockProducts.toString(), + inventory.lowStockProducts.toString(), Icons.warning_rounded, AppColor.warning, - '-8%', ), ), const SizedBox(width: 16), Expanded( - child: Container(), // Empty space for balance + child: _buildStatCard( + 'Stok Kosong', + inventory.zeroStockProducts.toString(), + Icons.error_rounded, + AppColor.error, + ), ), ], ), @@ -448,18 +329,7 @@ class _InventoryPageState extends State ); } - Widget _buildIngredientStats() { - final totalIngredients = ingredientItems.length; - final availableIngredients = ingredientItems - .where((item) => item.status == 'available') - .length; - final lowStockIngredients = ingredientItems - .where((item) => item.status == 'low_stock') - .length; - final outOfStockIngredients = ingredientItems - .where((item) => item.status == 'out_of_stock') - .length; - + Widget _buildIngredientStats(InventorySummary inventory) { return Container( margin: const EdgeInsets.all(16), child: Column( @@ -469,20 +339,18 @@ class _InventoryPageState extends State Expanded( child: _buildStatCard( 'Total Bahan', - totalIngredients.toString(), + inventory.totalIngredients.toString(), Icons.restaurant_menu_rounded, AppColor.primary, - '+8%', ), ), const SizedBox(width: 16), Expanded( child: _buildStatCard( - 'Tersedia', - availableIngredients.toString(), + 'Bahan Terjual', + inventory.totalSoldIngredients.toString(), Icons.check_circle_rounded, AppColor.success, - '+15%', ), ), ], @@ -493,20 +361,18 @@ class _InventoryPageState extends State Expanded( child: _buildStatCard( 'Stok Kurang', - lowStockIngredients.toString(), + inventory.lowStockIngredients.toString(), Icons.warning_rounded, AppColor.warning, - '-3%', ), ), const SizedBox(width: 16), Expanded( child: _buildStatCard( 'Habis', - outOfStockIngredients.toString(), + inventory.zeroStockIngredients.toString(), Icons.error_rounded, AppColor.error, - '+1', ), ), ], @@ -521,7 +387,6 @@ class _InventoryPageState extends State String value, IconData icon, Color color, - String change, ) { return TweenAnimationBuilder( tween: Tween(begin: 0, end: 1), @@ -534,7 +399,6 @@ class _InventoryPageState extends State value: value, icon: icon, color: color, - change: change, ), ); }, diff --git a/lib/presentation/pages/inventory/widgets/ingredient_tile.dart b/lib/presentation/pages/inventory/widgets/ingredient_tile.dart index 5a54464..8f40077 100644 --- a/lib/presentation/pages/inventory/widgets/ingredient_tile.dart +++ b/lib/presentation/pages/inventory/widgets/ingredient_tile.dart @@ -1,11 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; +import 'package:intl/intl.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; import '../../../components/spacer/spacer.dart'; -import '../inventory_page.dart'; class InventoryIngredientTile extends StatelessWidget { - final IngredientItem item; + final InventoryIngredient item; const InventoryIngredientTile({super.key, required this.item}); @override @@ -16,94 +19,458 @@ class InventoryIngredientTile extends StatelessWidget { decoration: BoxDecoration( color: AppColor.surface, borderRadius: BorderRadius.circular(16), + border: Border.all( + color: _getStatusColor().withOpacity(0.2), + width: 1.5, + ), boxShadow: [ BoxShadow( - color: AppColor.primaryWithOpacity(0.1), - blurRadius: 8, + color: _getStatusColor().withOpacity(0.08), + blurRadius: 12, + offset: const Offset(0, 4), + ), + BoxShadow( + color: AppColor.textLight.withOpacity(0.06), + blurRadius: 6, offset: const Offset(0, 2), ), ], ), - child: Row( + child: Column( children: [ - Container( - width: 60, - height: 60, - decoration: BoxDecoration( - gradient: LinearGradient(colors: AppColor.backgroundGradient), - borderRadius: BorderRadius.circular(12), - ), - child: Center( - child: Text(item.image, style: const TextStyle(fontSize: 24)), - ), - ), - const SpaceWidth(16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - item.name, - style: AppStyle.lg.copyWith( - fontWeight: FontWeight.bold, - color: AppColor.textPrimary, + // Main Row + Row( + children: [ + // Enhanced Icon Container + Container( + width: 65, + height: 65, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: _getGradientColors(), + begin: Alignment.topLeft, + end: Alignment.bottomRight, ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.2), + blurRadius: 8, + offset: const Offset(0, 3), + ), + ], ), - SpaceHeight(4), - Text( - 'Stok: ${item.quantity} ${item.unit}', - style: AppStyle.md.copyWith(color: AppColor.textSecondary), + child: Stack( + children: [ + Center( + child: Icon( + _getIngredientIcon(), + size: 28, + color: AppColor.white, + ), + ), + // Status indicator dot + Positioned( + top: 6, + right: 6, + child: Container( + width: 12, + height: 12, + decoration: BoxDecoration( + color: AppColor.white, + shape: BoxShape.circle, + border: Border.all( + color: _getStatusColor(), + width: 2, + ), + ), + child: Center( + child: Container( + width: 4, + height: 4, + decoration: BoxDecoration( + color: _getStatusColor(), + shape: BoxShape.circle, + ), + ), + ), + ), + ), + ], ), - SpaceHeight(4), - Text( - 'Min: ${item.minQuantity} ${item.unit}', - style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + ), + + const SpaceWidth(16), + + // Content Section + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Ingredient Name + Text( + item.ingredientName, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + height: 1.2, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + + SpaceHeight(6), + + // Stock Information Row + Row( + children: [ + Icon( + LineIcons.warehouse, + size: 14, + color: AppColor.textSecondary, + ), + const SpaceWidth(4), + Text( + 'Stok: ', + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(item.quantity)} ${item.unitName}', + style: AppStyle.sm.copyWith( + color: _getQuantityColor(), + fontWeight: FontWeight.w700, + ), + ), + ], + ), + + SpaceHeight(4), + + // Reorder Level Information + Row( + children: [ + Icon( + LineIcons.exclamationTriangle, + size: 14, + color: AppColor.warning, + ), + const SpaceWidth(4), + Text( + 'Min: ', + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(item.reorderLevel)} ${item.unitName}', + style: AppStyle.sm.copyWith( + color: AppColor.warning, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + + SpaceHeight(6), + + // Unit Cost + Row( + children: [ + Icon( + LineIcons.dollarSign, + size: 14, + color: AppColor.success, + ), + const SpaceWidth(4), + Text( + item.unitCost.currencyFormatRp, + style: AppStyle.sm.copyWith( + color: AppColor.success, + fontWeight: FontWeight.w700, + ), + ), + Text( + '/${item.unitName}', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ], ), - ], - ), + ), + + // Status Badge + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: _getStatusColor(), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.3), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + _getStatusText(), + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w700, + color: AppColor.white, + fontSize: 11, + ), + ), + ], + ), + ), + ], ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), - decoration: BoxDecoration( - color: getStatusColor(item.status), - borderRadius: BorderRadius.circular(20), - ), - child: Text( - getStatusText(item.status), - style: AppStyle.sm.copyWith( - fontWeight: FontWeight.bold, - color: AppColor.textWhite, + + // Additional Information Card (if low stock or has movements) + if (item.isLowStock || item.totalIn > 0 || item.totalOut > 0) ...[ + SpaceHeight(12), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.borderLight, width: 0.5), + ), + child: Column( + children: [ + // Warning message for low stock + if (item.isLowStock && !item.isZeroStock) ...[ + Row( + children: [ + Icon( + LineIcons.exclamationTriangle, + size: 16, + color: AppColor.warning, + ), + const SpaceWidth(6), + Expanded( + child: Text( + 'Stok mendekati batas minimum (${item.reorderLevel} ${item.unitName})', + style: AppStyle.xs.copyWith( + color: AppColor.warning, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + if (item.totalIn > 0 || item.totalOut > 0) SpaceHeight(8), + ], + + // Movement Information + if (item.totalIn > 0 || item.totalOut > 0) + Row( + children: [ + // Stock In + if (item.totalIn > 0) ...[ + Expanded( + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: AppColor.success.withOpacity(0.1), + borderRadius: BorderRadius.circular(6), + ), + child: Icon( + LineIcons.arrowUp, + size: 12, + color: AppColor.success, + ), + ), + const SpaceWidth(6), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Masuk', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(item.totalIn)} ${item.unitName}', + style: AppStyle.xs.copyWith( + color: AppColor.success, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ], + ), + ), + ], + + // Stock Out + if (item.totalOut > 0) ...[ + if (item.totalIn > 0) const SpaceWidth(16), + Expanded( + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: AppColor.error.withOpacity(0.1), + borderRadius: BorderRadius.circular(6), + ), + child: Icon( + LineIcons.arrowDown, + size: 12, + color: AppColor.error, + ), + ), + const SpaceWidth(6), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Keluar', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(item.totalOut)} ${item.unitName}', + style: AppStyle.xs.copyWith( + color: AppColor.error, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ], + ), + ), + ], + + // Total Value + if (item.totalValue > 0) ...[ + const SpaceWidth(16), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + 'Nilai Total', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + _formatCurrencyShort(item.totalValue), + style: AppStyle.xs.copyWith( + color: AppColor.info, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ], + ], + ), + ], ), ), - ), + ], ], ), ); } - Color getStatusColor(String status) { - switch (status) { - case 'available': - return AppColor.success; - case 'low_stock': - return AppColor.warning; - case 'out_of_stock': - return AppColor.error; - default: - return AppColor.textSecondary; - } + // Helper methods + Color _getStatusColor() { + if (item.isZeroStock) return AppColor.error; + if (item.isLowStock) return AppColor.warning; + return AppColor.success; } - String getStatusText(String status) { - switch (status) { - case 'available': - return 'Tersedia'; - case 'low_stock': - return 'Stok Rendah'; - case 'out_of_stock': - return 'Habis'; - default: - return 'Unknown'; + List _getGradientColors() { + if (item.isZeroStock) { + return [AppColor.error, AppColor.error.withOpacity(0.7)]; + } + if (item.isLowStock) { + return [AppColor.warning, AppColor.warning.withOpacity(0.7)]; + } + return [AppColor.success, AppColor.success.withOpacity(0.7)]; + } + + Color _getQuantityColor() { + if (item.isZeroStock) return AppColor.error; + if (item.isLowStock) return AppColor.warning; + return AppColor.textPrimary; + } + + String _getStatusText() { + if (item.isZeroStock) return 'HABIS'; + if (item.isLowStock) return 'MINIM'; + return 'TERSEDIA'; + } + + IconData _getIngredientIcon() { + final name = item.ingredientName.toLowerCase(); + + // Food ingredients + if (name.contains('tepung') || name.contains('flour')) { + return LineIcons.breadSlice; + } else if (name.contains('gula') || name.contains('sugar')) { + return LineIcons.cube; + } else if (name.contains('garam') || name.contains('salt')) { + return LineIcons.breadSlice; + } else if (name.contains('minyak') || name.contains('oil')) { + return LineIcons.tint; + } else if (name.contains('susu') || name.contains('milk')) { + return LineIcons.glasses; + } else if (name.contains('telur') || name.contains('egg')) { + return LineIcons.egg; + } else if (name.contains('daging') || name.contains('meat')) { + return LineIcons.hamburger; + } else if (name.contains('sayur') || name.contains('vegetable')) { + return LineIcons.carrot; + } else if (name.contains('bumbu') || name.contains('spice')) { + return LineIcons.leaf; + } else if (name.contains('buah') || name.contains('fruit')) { + return LineIcons.apple; + } else if (name.contains('beras') || name.contains('rice')) { + return LineIcons.seedling; + } else if (name.contains('kopi') || name.contains('coffee')) { + return LineIcons.coffee; + } + + // Default ingredient icon + return LineIcons.utensils; + } + + String _formatCurrencyShort(int amount) { + if (amount.abs() >= 1000000000) { + return 'Rp ${(amount / 1000000000).toStringAsFixed(1)}B'; + } else if (amount.abs() >= 1000000) { + return 'Rp ${(amount / 1000000).toStringAsFixed(1)}M'; + } else if (amount.abs() >= 1000) { + return 'Rp ${(amount / 1000).toStringAsFixed(0)}K'; + } else { + return 'Rp ${NumberFormat('#,###', 'id_ID').format(amount)}'; } } } diff --git a/lib/presentation/pages/inventory/widgets/product_tile.dart b/lib/presentation/pages/inventory/widgets/product_tile.dart index bcfdd6e..fe3a1e7 100644 --- a/lib/presentation/pages/inventory/widgets/product_tile.dart +++ b/lib/presentation/pages/inventory/widgets/product_tile.dart @@ -1,154 +1,514 @@ import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; +import 'package:intl/intl.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; import '../../../components/spacer/spacer.dart'; -import '../inventory_page.dart'; class InventoryProductTile extends StatelessWidget { - final ProductItem item; + final InventoryProduct item; const InventoryProductTile({super.key, required this.item}); @override Widget build(BuildContext context) { return Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColor.surface, borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColor.primary.withOpacity(0.08), width: 1), + border: Border.all( + color: _getStatusColor().withOpacity(0.2), + width: 1.5, + ), boxShadow: [ BoxShadow( - color: AppColor.primary.withOpacity(0.06), - blurRadius: 12, - offset: const Offset(0, 4), + color: _getStatusColor().withOpacity(0.06), + blurRadius: 16, + offset: const Offset(0, 6), + ), + BoxShadow( + color: AppColor.textLight.withOpacity(0.08), + blurRadius: 4, + offset: const Offset(0, 2), ), ], ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Image Container - Container( - height: 85, - width: double.infinity, - decoration: BoxDecoration( - gradient: LinearGradient( - colors: AppColor.backgroundGradient, - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - ), - ), - child: Center( - child: Container( - padding: const EdgeInsets.all(8), + // Main Content Row + Row( + children: [ + // Enhanced Product Icon + Container( + width: 70, + height: 70, decoration: BoxDecoration( - color: AppColor.textWhite.withOpacity(0.9), - borderRadius: BorderRadius.circular(12), + gradient: LinearGradient( + colors: _getGradientColors(), + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(18), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.25), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + child: Stack( + children: [ + Center( + child: Icon( + _getCategoryIcon(), + size: 32, + color: AppColor.white, + ), + ), + // Status indicator + Positioned( + top: 6, + right: 6, + child: Container( + width: 14, + height: 14, + decoration: BoxDecoration( + color: AppColor.white, + shape: BoxShape.circle, + border: Border.all( + color: _getStatusColor(), + width: 2.5, + ), + ), + child: Center( + child: Container( + width: 5, + height: 5, + decoration: BoxDecoration( + color: _getStatusColor(), + shape: BoxShape.circle, + ), + ), + ), + ), + ), + ], ), - child: Text(item.image, style: const TextStyle(fontSize: 32)), ), - ), + + const SpaceWidth(16), + + // Product Information + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Product Name and Category Row + Row( + children: [ + Expanded( + child: Text( + item.productName, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + height: 1.2, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + const SpaceWidth(8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(10), + border: Border.all( + color: AppColor.primary.withOpacity(0.15), + width: 0.5, + ), + ), + child: Text( + item.categoryName, + style: AppStyle.xs.copyWith( + fontSize: 9, + fontWeight: FontWeight.w600, + color: AppColor.primary, + letterSpacing: 0.2, + ), + ), + ), + ], + ), + + SpaceHeight(8), + + // Price and Status Row + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Price + Text( + item.unitCost.currencyFormatRp, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.w800, + color: AppColor.success, + fontSize: 16, + ), + ), + // Status Badge + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 4, + ), + decoration: BoxDecoration( + color: _getStatusColor(), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.3), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Text( + _getStatusText(), + style: AppStyle.xs.copyWith( + fontSize: 10, + fontWeight: FontWeight.w700, + color: AppColor.white, + ), + ), + ), + ], + ), + + SpaceHeight(10), + + // Stock Information Grid + Row( + children: [ + // Quantity Info + Expanded( + child: _buildInfoItem( + LineIcons.boxes, + 'Stok', + '${NumberFormat('#,###', 'id_ID').format(item.quantity)} pcs', + _getQuantityColor(), + ), + ), + const SpaceWidth(16), + // Total Value Info + Expanded( + child: _buildInfoItem( + LineIcons.dollarSign, + 'Nilai', + _formatCurrencyShort(item.totalValue), + AppColor.info, + ), + ), + ], + ), + ], + ), + ), + ], ), - // Content Container - Expanded( - child: Padding( + // Additional Information (conditionally shown) + if (_shouldShowAdditionalInfo()) ...[ + SpaceHeight(12), + Container( padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.borderLight, width: 0.5), + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Product Name - Text( - item.name, - style: AppStyle.sm.copyWith( - fontWeight: FontWeight.w600, - color: AppColor.textPrimary, - height: 1.2, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - - SpaceHeight(4), - - // Category - Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 2, - ), - decoration: BoxDecoration( - color: AppColor.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - item.category, - style: AppStyle.xs.copyWith( - fontSize: 9, - fontWeight: FontWeight.w500, - color: AppColor.primary, - ), - ), - ), - - const Spacer(), - - // Price - Text( - 'Rp ${item.price}', - style: AppStyle.sm.copyWith( - fontSize: 13, - fontWeight: FontWeight.w700, - color: AppColor.primary, - ), - ), - - SpaceHeight(6), - - // Quantity & Status - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '${item.quantity} pcs', - style: AppStyle.xs.copyWith( - fontSize: 11, - fontWeight: FontWeight.w500, - color: AppColor.textSecondary, + // Low Stock Warning + if (item.isLowStock && !item.isZeroStock) ...[ + Row( + children: [ + Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration( + color: AppColor.warning.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + LineIcons.exclamationTriangle, + size: 16, + color: AppColor.warning, + ), ), - ), - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: getStatusColor(item.status), - shape: BoxShape.circle, + const SpaceWidth(10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Stok Menipis', + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.warning, + ), + ), + Text( + 'Segera reorder minimal ${NumberFormat('#,###', 'id_ID').format(item.reorderLevel)} pcs', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ), ), - ), - ], - ), + ], + ), + ], + + // Zero Stock Warning + if (item.isZeroStock) ...[ + Row( + children: [ + Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration( + color: AppColor.error.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + LineIcons.timesCircle, + size: 16, + color: AppColor.error, + ), + ), + const SpaceWidth(10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Stok Habis', + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.error, + ), + ), + Text( + 'Produk tidak tersedia untuk dijual', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ], + ), + ], + + // Movement Information + if (_hasMovementData()) ...[ + if ((item.isLowStock || item.isZeroStock)) SpaceHeight(12), + Row( + children: [ + if (item.totalIn > 0) + Expanded( + child: _buildMovementInfo( + LineIcons.arrowUp, + 'Masuk', + '${NumberFormat('#,###', 'id_ID').format(item.totalIn)} pcs', + AppColor.success, + ), + ), + if (item.totalIn > 0 && item.totalOut > 0) + const SpaceWidth(16), + if (item.totalOut > 0) + Expanded( + child: _buildMovementInfo( + LineIcons.arrowDown, + 'Keluar', + '${NumberFormat('#,###', 'id_ID').format(item.totalOut)} pcs', + AppColor.error, + ), + ), + ], + ), + ], ], ), ), + ], + ], + ), + ); + } + + Widget _buildInfoItem( + IconData icon, + String label, + String value, + Color valueColor, + ) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: AppColor.borderLight, width: 0.5), + ), + child: Row( + children: [ + Icon(icon, size: 14, color: AppColor.textSecondary), + const SpaceWidth(6), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: AppStyle.xs.copyWith( + fontSize: 10, + fontWeight: FontWeight.w500, + color: AppColor.textSecondary, + ), + ), + SpaceHeight(1), + Text( + value, + style: AppStyle.xs.copyWith( + fontSize: 11, + fontWeight: FontWeight.w700, + color: valueColor, + ), + ), + ], + ), ), ], ), ); } - Color getStatusColor(String status) { - switch (status) { - case 'available': - return AppColor.success; - case 'low_stock': - return AppColor.warning; - case 'out_of_stock': - return AppColor.error; - default: - return AppColor.textSecondary; + Widget _buildMovementInfo( + IconData icon, + String label, + String value, + Color color, + ) { + return Row( + children: [ + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: color.withOpacity(0.1), + borderRadius: BorderRadius.circular(6), + ), + child: Icon(icon, size: 12, color: color), + ), + const SpaceWidth(8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + value, + style: AppStyle.xs.copyWith( + color: color, + fontWeight: FontWeight.w700, + fontSize: 11, + ), + ), + ], + ), + ], + ); + } + + // Helper methods + bool _shouldShowAdditionalInfo() { + return item.isLowStock || item.isZeroStock || _hasMovementData(); + } + + bool _hasMovementData() { + return item.totalIn > 0 || item.totalOut > 0; + } + + Color _getStatusColor() { + if (item.isZeroStock) return AppColor.error; + if (item.isLowStock) return AppColor.warning; + return AppColor.success; + } + + List _getGradientColors() { + if (item.isZeroStock) { + return [AppColor.error, AppColor.error.withOpacity(0.7)]; + } + if (item.isLowStock) { + return [AppColor.warning, AppColor.warning.withOpacity(0.7)]; + } + return [AppColor.primary, AppColor.primary.withOpacity(0.7)]; + } + + Color _getQuantityColor() { + if (item.isZeroStock) return AppColor.error; + if (item.isLowStock) return AppColor.warning; + return AppColor.textPrimary; + } + + String _getStatusText() { + if (item.isZeroStock) return 'HABIS'; + if (item.isLowStock) return 'MINIM'; + return 'TERSEDIA'; + } + + IconData _getCategoryIcon() { + final category = item.categoryName.toLowerCase(); + if (category.contains('elektronik') || category.contains('gadget')) { + return LineIcons.mobilePhone; + } else if (category.contains('fashion') || category.contains('pakaian')) { + return LineIcons.tShirt; + } else if (category.contains('makanan') || category.contains('food')) { + return LineIcons.utensils; + } else if (category.contains('kesehatan') || category.contains('health')) { + return LineIcons.medkit; + } else if (category.contains('rumah') || category.contains('home')) { + return LineIcons.home; + } else if (category.contains('olahraga') || category.contains('sport')) { + return LineIcons.dumbbell; + } + return LineIcons.box; + } + + String _formatCurrencyShort(int amount) { + if (amount.abs() >= 1000000000) { + return 'Rp ${(amount / 1000000000).toStringAsFixed(1)}B'; + } else if (amount.abs() >= 1000000) { + return 'Rp ${(amount / 1000000).toStringAsFixed(1)}M'; + } else if (amount.abs() >= 1000) { + return 'Rp ${(amount / 1000).toStringAsFixed(0)}K'; + } else { + return 'Rp ${NumberFormat('#,###', 'id_ID').format(amount)}'; } } } diff --git a/lib/presentation/pages/inventory/widgets/stat_card.dart b/lib/presentation/pages/inventory/widgets/stat_card.dart index 08d5125..c418b06 100644 --- a/lib/presentation/pages/inventory/widgets/stat_card.dart +++ b/lib/presentation/pages/inventory/widgets/stat_card.dart @@ -8,14 +8,12 @@ class InventoryStatCard extends StatelessWidget { final String value; final IconData icon; final Color color; - final String change; const InventoryStatCard({ super.key, required this.title, required this.value, required this.icon, required this.color, - required this.change, }); @override @@ -52,20 +50,6 @@ class InventoryStatCard extends StatelessWidget { child: Icon(icon, color: color, size: 24), ), const Spacer(), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: _getChangeColor(change).withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - change, - style: AppStyle.sm.copyWith( - color: _getChangeColor(change), - fontWeight: FontWeight.w700, - ), - ), - ), ], ), SpaceHeight(16), @@ -88,14 +72,4 @@ class InventoryStatCard extends StatelessWidget { ), ); } - - Color _getChangeColor(String change) { - if (change.startsWith('+')) { - return AppColor.success; - } else if (change.startsWith('-')) { - return AppColor.error; - } else { - return AppColor.warning; - } - } }