feat: product
This commit is contained in:
parent
82c0eaf5fe
commit
7d24b3296d
@ -0,0 +1,92 @@
|
||||
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/product/product.dart';
|
||||
|
||||
part 'product_loader_event.dart';
|
||||
part 'product_loader_state.dart';
|
||||
part 'product_loader_bloc.freezed.dart';
|
||||
|
||||
@injectable
|
||||
class ProductLoaderBloc extends Bloc<ProductLoaderEvent, ProductLoaderState> {
|
||||
final IProductRepository _productRepository;
|
||||
|
||||
ProductLoaderBloc(this._productRepository)
|
||||
: super(ProductLoaderState.initial()) {
|
||||
on<ProductLoaderEvent>(_onProductLoaderEvent);
|
||||
}
|
||||
|
||||
Future<void> _onProductLoaderEvent(
|
||||
ProductLoaderEvent event,
|
||||
Emitter<ProductLoaderState> emit,
|
||||
) {
|
||||
return event.map(
|
||||
categoryIdChanged: (e) async {
|
||||
emit(state.copyWith(categoryId: e.categoryId));
|
||||
},
|
||||
searchChanged: (e) async {
|
||||
emit(state.copyWith(search: e.search));
|
||||
},
|
||||
fetched: (e) async {
|
||||
var newState = state;
|
||||
|
||||
if (e.isRefresh) {
|
||||
newState = state.copyWith(isFetching: true);
|
||||
|
||||
emit(newState);
|
||||
}
|
||||
|
||||
newState = await _mapFetchedToState(state, isRefresh: e.isRefresh);
|
||||
|
||||
emit(newState);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<ProductLoaderState> _mapFetchedToState(
|
||||
ProductLoaderState state, {
|
||||
bool isRefresh = false,
|
||||
}) async {
|
||||
state = state.copyWith(isFetching: false);
|
||||
|
||||
if (state.hasReachedMax && state.products.isNotEmpty && !isRefresh) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (isRefresh) {
|
||||
state = state.copyWith(
|
||||
page: 1,
|
||||
failureOptionProduct: none(),
|
||||
hasReachedMax: false,
|
||||
products: [],
|
||||
);
|
||||
}
|
||||
|
||||
final failureOrProduct = await _productRepository.get(
|
||||
categoryId: state.categoryId,
|
||||
page: state.page,
|
||||
search: state.search,
|
||||
);
|
||||
|
||||
state = failureOrProduct.fold(
|
||||
(f) {
|
||||
if (state.products.isNotEmpty) {
|
||||
return state.copyWith(hasReachedMax: true);
|
||||
}
|
||||
return state.copyWith(failureOptionProduct: optionOf(f));
|
||||
},
|
||||
(products) {
|
||||
return state.copyWith(
|
||||
products: List.from(state.products)..addAll(products),
|
||||
failureOptionProduct: none(),
|
||||
page: state.page + 1,
|
||||
hasReachedMax: products.length < 10,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,821 @@
|
||||
// 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 'product_loader_bloc.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(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 _$ProductLoaderEvent {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(String categoryId) categoryIdChanged,
|
||||
required TResult Function(String search) searchChanged,
|
||||
required TResult Function(bool isRefresh) fetched,
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(String categoryId)? categoryIdChanged,
|
||||
TResult? Function(String search)? searchChanged,
|
||||
TResult? Function(bool isRefresh)? fetched,
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(String categoryId)? categoryIdChanged,
|
||||
TResult Function(String search)? searchChanged,
|
||||
TResult Function(bool isRefresh)? fetched,
|
||||
required TResult orElse(),
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_CategoryIdChanged value) categoryIdChanged,
|
||||
required TResult Function(_SearchChanged value) searchChanged,
|
||||
required TResult Function(_Fetched value) fetched,
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(_CategoryIdChanged value)? categoryIdChanged,
|
||||
TResult? Function(_SearchChanged value)? searchChanged,
|
||||
TResult? Function(_Fetched value)? fetched,
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_CategoryIdChanged value)? categoryIdChanged,
|
||||
TResult Function(_SearchChanged value)? searchChanged,
|
||||
TResult Function(_Fetched value)? fetched,
|
||||
required TResult orElse(),
|
||||
}) => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ProductLoaderEventCopyWith<$Res> {
|
||||
factory $ProductLoaderEventCopyWith(
|
||||
ProductLoaderEvent value,
|
||||
$Res Function(ProductLoaderEvent) then,
|
||||
) = _$ProductLoaderEventCopyWithImpl<$Res, ProductLoaderEvent>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ProductLoaderEventCopyWithImpl<$Res, $Val extends ProductLoaderEvent>
|
||||
implements $ProductLoaderEventCopyWith<$Res> {
|
||||
_$ProductLoaderEventCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$CategoryIdChangedImplCopyWith<$Res> {
|
||||
factory _$$CategoryIdChangedImplCopyWith(
|
||||
_$CategoryIdChangedImpl value,
|
||||
$Res Function(_$CategoryIdChangedImpl) then,
|
||||
) = __$$CategoryIdChangedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String categoryId});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$CategoryIdChangedImplCopyWithImpl<$Res>
|
||||
extends _$ProductLoaderEventCopyWithImpl<$Res, _$CategoryIdChangedImpl>
|
||||
implements _$$CategoryIdChangedImplCopyWith<$Res> {
|
||||
__$$CategoryIdChangedImplCopyWithImpl(
|
||||
_$CategoryIdChangedImpl _value,
|
||||
$Res Function(_$CategoryIdChangedImpl) _then,
|
||||
) : super(_value, _then);
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({Object? categoryId = null}) {
|
||||
return _then(
|
||||
_$CategoryIdChangedImpl(
|
||||
null == categoryId
|
||||
? _value.categoryId
|
||||
: categoryId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$CategoryIdChangedImpl implements _CategoryIdChanged {
|
||||
const _$CategoryIdChangedImpl(this.categoryId);
|
||||
|
||||
@override
|
||||
final String categoryId;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductLoaderEvent.categoryIdChanged(categoryId: $categoryId)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$CategoryIdChangedImpl &&
|
||||
(identical(other.categoryId, categoryId) ||
|
||||
other.categoryId == categoryId));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, categoryId);
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$CategoryIdChangedImplCopyWith<_$CategoryIdChangedImpl> get copyWith =>
|
||||
__$$CategoryIdChangedImplCopyWithImpl<_$CategoryIdChangedImpl>(
|
||||
this,
|
||||
_$identity,
|
||||
);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(String categoryId) categoryIdChanged,
|
||||
required TResult Function(String search) searchChanged,
|
||||
required TResult Function(bool isRefresh) fetched,
|
||||
}) {
|
||||
return categoryIdChanged(categoryId);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(String categoryId)? categoryIdChanged,
|
||||
TResult? Function(String search)? searchChanged,
|
||||
TResult? Function(bool isRefresh)? fetched,
|
||||
}) {
|
||||
return categoryIdChanged?.call(categoryId);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(String categoryId)? categoryIdChanged,
|
||||
TResult Function(String search)? searchChanged,
|
||||
TResult Function(bool isRefresh)? fetched,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (categoryIdChanged != null) {
|
||||
return categoryIdChanged(categoryId);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_CategoryIdChanged value) categoryIdChanged,
|
||||
required TResult Function(_SearchChanged value) searchChanged,
|
||||
required TResult Function(_Fetched value) fetched,
|
||||
}) {
|
||||
return categoryIdChanged(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(_CategoryIdChanged value)? categoryIdChanged,
|
||||
TResult? Function(_SearchChanged value)? searchChanged,
|
||||
TResult? Function(_Fetched value)? fetched,
|
||||
}) {
|
||||
return categoryIdChanged?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_CategoryIdChanged value)? categoryIdChanged,
|
||||
TResult Function(_SearchChanged value)? searchChanged,
|
||||
TResult Function(_Fetched value)? fetched,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (categoryIdChanged != null) {
|
||||
return categoryIdChanged(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _CategoryIdChanged implements ProductLoaderEvent {
|
||||
const factory _CategoryIdChanged(final String categoryId) =
|
||||
_$CategoryIdChangedImpl;
|
||||
|
||||
String get categoryId;
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$CategoryIdChangedImplCopyWith<_$CategoryIdChangedImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$SearchChangedImplCopyWith<$Res> {
|
||||
factory _$$SearchChangedImplCopyWith(
|
||||
_$SearchChangedImpl value,
|
||||
$Res Function(_$SearchChangedImpl) then,
|
||||
) = __$$SearchChangedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String search});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$SearchChangedImplCopyWithImpl<$Res>
|
||||
extends _$ProductLoaderEventCopyWithImpl<$Res, _$SearchChangedImpl>
|
||||
implements _$$SearchChangedImplCopyWith<$Res> {
|
||||
__$$SearchChangedImplCopyWithImpl(
|
||||
_$SearchChangedImpl _value,
|
||||
$Res Function(_$SearchChangedImpl) _then,
|
||||
) : super(_value, _then);
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({Object? search = null}) {
|
||||
return _then(
|
||||
_$SearchChangedImpl(
|
||||
null == search
|
||||
? _value.search
|
||||
: search // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$SearchChangedImpl implements _SearchChanged {
|
||||
const _$SearchChangedImpl(this.search);
|
||||
|
||||
@override
|
||||
final String search;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductLoaderEvent.searchChanged(search: $search)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$SearchChangedImpl &&
|
||||
(identical(other.search, search) || other.search == search));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, search);
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith =>
|
||||
__$$SearchChangedImplCopyWithImpl<_$SearchChangedImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(String categoryId) categoryIdChanged,
|
||||
required TResult Function(String search) searchChanged,
|
||||
required TResult Function(bool isRefresh) fetched,
|
||||
}) {
|
||||
return searchChanged(search);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(String categoryId)? categoryIdChanged,
|
||||
TResult? Function(String search)? searchChanged,
|
||||
TResult? Function(bool isRefresh)? fetched,
|
||||
}) {
|
||||
return searchChanged?.call(search);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(String categoryId)? categoryIdChanged,
|
||||
TResult Function(String search)? searchChanged,
|
||||
TResult Function(bool isRefresh)? fetched,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (searchChanged != null) {
|
||||
return searchChanged(search);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_CategoryIdChanged value) categoryIdChanged,
|
||||
required TResult Function(_SearchChanged value) searchChanged,
|
||||
required TResult Function(_Fetched value) fetched,
|
||||
}) {
|
||||
return searchChanged(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(_CategoryIdChanged value)? categoryIdChanged,
|
||||
TResult? Function(_SearchChanged value)? searchChanged,
|
||||
TResult? Function(_Fetched value)? fetched,
|
||||
}) {
|
||||
return searchChanged?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_CategoryIdChanged value)? categoryIdChanged,
|
||||
TResult Function(_SearchChanged value)? searchChanged,
|
||||
TResult Function(_Fetched value)? fetched,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (searchChanged != null) {
|
||||
return searchChanged(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _SearchChanged implements ProductLoaderEvent {
|
||||
const factory _SearchChanged(final String search) = _$SearchChangedImpl;
|
||||
|
||||
String get search;
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$FetchedImplCopyWith<$Res> {
|
||||
factory _$$FetchedImplCopyWith(
|
||||
_$FetchedImpl value,
|
||||
$Res Function(_$FetchedImpl) then,
|
||||
) = __$$FetchedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({bool isRefresh});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$FetchedImplCopyWithImpl<$Res>
|
||||
extends _$ProductLoaderEventCopyWithImpl<$Res, _$FetchedImpl>
|
||||
implements _$$FetchedImplCopyWith<$Res> {
|
||||
__$$FetchedImplCopyWithImpl(
|
||||
_$FetchedImpl _value,
|
||||
$Res Function(_$FetchedImpl) _then,
|
||||
) : super(_value, _then);
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({Object? isRefresh = null}) {
|
||||
return _then(
|
||||
_$FetchedImpl(
|
||||
isRefresh: null == isRefresh
|
||||
? _value.isRefresh
|
||||
: isRefresh // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$FetchedImpl implements _Fetched {
|
||||
const _$FetchedImpl({this.isRefresh = false});
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool isRefresh;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductLoaderEvent.fetched(isRefresh: $isRefresh)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$FetchedImpl &&
|
||||
(identical(other.isRefresh, isRefresh) ||
|
||||
other.isRefresh == isRefresh));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, isRefresh);
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$FetchedImplCopyWith<_$FetchedImpl> get copyWith =>
|
||||
__$$FetchedImplCopyWithImpl<_$FetchedImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(String categoryId) categoryIdChanged,
|
||||
required TResult Function(String search) searchChanged,
|
||||
required TResult Function(bool isRefresh) fetched,
|
||||
}) {
|
||||
return fetched(isRefresh);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(String categoryId)? categoryIdChanged,
|
||||
TResult? Function(String search)? searchChanged,
|
||||
TResult? Function(bool isRefresh)? fetched,
|
||||
}) {
|
||||
return fetched?.call(isRefresh);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(String categoryId)? categoryIdChanged,
|
||||
TResult Function(String search)? searchChanged,
|
||||
TResult Function(bool isRefresh)? fetched,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (fetched != null) {
|
||||
return fetched(isRefresh);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_CategoryIdChanged value) categoryIdChanged,
|
||||
required TResult Function(_SearchChanged value) searchChanged,
|
||||
required TResult Function(_Fetched value) fetched,
|
||||
}) {
|
||||
return fetched(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(_CategoryIdChanged value)? categoryIdChanged,
|
||||
TResult? Function(_SearchChanged value)? searchChanged,
|
||||
TResult? Function(_Fetched value)? fetched,
|
||||
}) {
|
||||
return fetched?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_CategoryIdChanged value)? categoryIdChanged,
|
||||
TResult Function(_SearchChanged value)? searchChanged,
|
||||
TResult Function(_Fetched value)? fetched,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (fetched != null) {
|
||||
return fetched(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Fetched implements ProductLoaderEvent {
|
||||
const factory _Fetched({final bool isRefresh}) = _$FetchedImpl;
|
||||
|
||||
bool get isRefresh;
|
||||
|
||||
/// Create a copy of ProductLoaderEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$FetchedImplCopyWith<_$FetchedImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ProductLoaderState {
|
||||
List<Product> get products => throw _privateConstructorUsedError;
|
||||
Option<ProductFailure> get failureOptionProduct =>
|
||||
throw _privateConstructorUsedError;
|
||||
String? get categoryId => throw _privateConstructorUsedError;
|
||||
String? get search => throw _privateConstructorUsedError;
|
||||
bool get isFetching => throw _privateConstructorUsedError;
|
||||
bool get hasReachedMax => throw _privateConstructorUsedError;
|
||||
int get page => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ProductLoaderState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$ProductLoaderStateCopyWith<ProductLoaderState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ProductLoaderStateCopyWith<$Res> {
|
||||
factory $ProductLoaderStateCopyWith(
|
||||
ProductLoaderState value,
|
||||
$Res Function(ProductLoaderState) then,
|
||||
) = _$ProductLoaderStateCopyWithImpl<$Res, ProductLoaderState>;
|
||||
@useResult
|
||||
$Res call({
|
||||
List<Product> products,
|
||||
Option<ProductFailure> failureOptionProduct,
|
||||
String? categoryId,
|
||||
String? search,
|
||||
bool isFetching,
|
||||
bool hasReachedMax,
|
||||
int page,
|
||||
});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ProductLoaderStateCopyWithImpl<$Res, $Val extends ProductLoaderState>
|
||||
implements $ProductLoaderStateCopyWith<$Res> {
|
||||
_$ProductLoaderStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ProductLoaderState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? products = null,
|
||||
Object? failureOptionProduct = null,
|
||||
Object? categoryId = freezed,
|
||||
Object? search = freezed,
|
||||
Object? isFetching = null,
|
||||
Object? hasReachedMax = null,
|
||||
Object? page = null,
|
||||
}) {
|
||||
return _then(
|
||||
_value.copyWith(
|
||||
products: null == products
|
||||
? _value.products
|
||||
: products // ignore: cast_nullable_to_non_nullable
|
||||
as List<Product>,
|
||||
failureOptionProduct: null == failureOptionProduct
|
||||
? _value.failureOptionProduct
|
||||
: failureOptionProduct // ignore: cast_nullable_to_non_nullable
|
||||
as Option<ProductFailure>,
|
||||
categoryId: freezed == categoryId
|
||||
? _value.categoryId
|
||||
: categoryId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
search: freezed == search
|
||||
? _value.search
|
||||
: search // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
isFetching: null == isFetching
|
||||
? _value.isFetching
|
||||
: isFetching // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
hasReachedMax: null == hasReachedMax
|
||||
? _value.hasReachedMax
|
||||
: hasReachedMax // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
page: null == page
|
||||
? _value.page
|
||||
: page // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
)
|
||||
as $Val,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ProductLoaderStateImplCopyWith<$Res>
|
||||
implements $ProductLoaderStateCopyWith<$Res> {
|
||||
factory _$$ProductLoaderStateImplCopyWith(
|
||||
_$ProductLoaderStateImpl value,
|
||||
$Res Function(_$ProductLoaderStateImpl) then,
|
||||
) = __$$ProductLoaderStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({
|
||||
List<Product> products,
|
||||
Option<ProductFailure> failureOptionProduct,
|
||||
String? categoryId,
|
||||
String? search,
|
||||
bool isFetching,
|
||||
bool hasReachedMax,
|
||||
int page,
|
||||
});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ProductLoaderStateImplCopyWithImpl<$Res>
|
||||
extends _$ProductLoaderStateCopyWithImpl<$Res, _$ProductLoaderStateImpl>
|
||||
implements _$$ProductLoaderStateImplCopyWith<$Res> {
|
||||
__$$ProductLoaderStateImplCopyWithImpl(
|
||||
_$ProductLoaderStateImpl _value,
|
||||
$Res Function(_$ProductLoaderStateImpl) _then,
|
||||
) : super(_value, _then);
|
||||
|
||||
/// Create a copy of ProductLoaderState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? products = null,
|
||||
Object? failureOptionProduct = null,
|
||||
Object? categoryId = freezed,
|
||||
Object? search = freezed,
|
||||
Object? isFetching = null,
|
||||
Object? hasReachedMax = null,
|
||||
Object? page = null,
|
||||
}) {
|
||||
return _then(
|
||||
_$ProductLoaderStateImpl(
|
||||
products: null == products
|
||||
? _value._products
|
||||
: products // ignore: cast_nullable_to_non_nullable
|
||||
as List<Product>,
|
||||
failureOptionProduct: null == failureOptionProduct
|
||||
? _value.failureOptionProduct
|
||||
: failureOptionProduct // ignore: cast_nullable_to_non_nullable
|
||||
as Option<ProductFailure>,
|
||||
categoryId: freezed == categoryId
|
||||
? _value.categoryId
|
||||
: categoryId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
search: freezed == search
|
||||
? _value.search
|
||||
: search // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
isFetching: null == isFetching
|
||||
? _value.isFetching
|
||||
: isFetching // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
hasReachedMax: null == hasReachedMax
|
||||
? _value.hasReachedMax
|
||||
: hasReachedMax // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
page: null == page
|
||||
? _value.page
|
||||
: page // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ProductLoaderStateImpl implements _ProductLoaderState {
|
||||
const _$ProductLoaderStateImpl({
|
||||
required final List<Product> products,
|
||||
required this.failureOptionProduct,
|
||||
this.categoryId,
|
||||
this.search,
|
||||
this.isFetching = false,
|
||||
this.hasReachedMax = false,
|
||||
this.page = 1,
|
||||
}) : _products = products;
|
||||
|
||||
final List<Product> _products;
|
||||
@override
|
||||
List<Product> get products {
|
||||
if (_products is EqualUnmodifiableListView) return _products;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_products);
|
||||
}
|
||||
|
||||
@override
|
||||
final Option<ProductFailure> failureOptionProduct;
|
||||
@override
|
||||
final String? categoryId;
|
||||
@override
|
||||
final String? search;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool isFetching;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool hasReachedMax;
|
||||
@override
|
||||
@JsonKey()
|
||||
final int page;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductLoaderState(products: $products, failureOptionProduct: $failureOptionProduct, categoryId: $categoryId, search: $search, isFetching: $isFetching, hasReachedMax: $hasReachedMax, page: $page)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ProductLoaderStateImpl &&
|
||||
const DeepCollectionEquality().equals(other._products, _products) &&
|
||||
(identical(other.failureOptionProduct, failureOptionProduct) ||
|
||||
other.failureOptionProduct == failureOptionProduct) &&
|
||||
(identical(other.categoryId, categoryId) ||
|
||||
other.categoryId == categoryId) &&
|
||||
(identical(other.search, search) || other.search == search) &&
|
||||
(identical(other.isFetching, isFetching) ||
|
||||
other.isFetching == isFetching) &&
|
||||
(identical(other.hasReachedMax, hasReachedMax) ||
|
||||
other.hasReachedMax == hasReachedMax) &&
|
||||
(identical(other.page, page) || other.page == page));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_products),
|
||||
failureOptionProduct,
|
||||
categoryId,
|
||||
search,
|
||||
isFetching,
|
||||
hasReachedMax,
|
||||
page,
|
||||
);
|
||||
|
||||
/// Create a copy of ProductLoaderState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ProductLoaderStateImplCopyWith<_$ProductLoaderStateImpl> get copyWith =>
|
||||
__$$ProductLoaderStateImplCopyWithImpl<_$ProductLoaderStateImpl>(
|
||||
this,
|
||||
_$identity,
|
||||
);
|
||||
}
|
||||
|
||||
abstract class _ProductLoaderState implements ProductLoaderState {
|
||||
const factory _ProductLoaderState({
|
||||
required final List<Product> products,
|
||||
required final Option<ProductFailure> failureOptionProduct,
|
||||
final String? categoryId,
|
||||
final String? search,
|
||||
final bool isFetching,
|
||||
final bool hasReachedMax,
|
||||
final int page,
|
||||
}) = _$ProductLoaderStateImpl;
|
||||
|
||||
@override
|
||||
List<Product> get products;
|
||||
@override
|
||||
Option<ProductFailure> get failureOptionProduct;
|
||||
@override
|
||||
String? get categoryId;
|
||||
@override
|
||||
String? get search;
|
||||
@override
|
||||
bool get isFetching;
|
||||
@override
|
||||
bool get hasReachedMax;
|
||||
@override
|
||||
int get page;
|
||||
|
||||
/// Create a copy of ProductLoaderState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ProductLoaderStateImplCopyWith<_$ProductLoaderStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
part of 'product_loader_bloc.dart';
|
||||
|
||||
@freezed
|
||||
class ProductLoaderEvent with _$ProductLoaderEvent {
|
||||
const factory ProductLoaderEvent.categoryIdChanged(String categoryId) =
|
||||
_CategoryIdChanged;
|
||||
const factory ProductLoaderEvent.searchChanged(String search) =
|
||||
_SearchChanged;
|
||||
const factory ProductLoaderEvent.fetched({@Default(false) bool isRefresh}) =
|
||||
_Fetched;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
part of 'product_loader_bloc.dart';
|
||||
|
||||
@freezed
|
||||
class ProductLoaderState with _$ProductLoaderState {
|
||||
const factory ProductLoaderState({
|
||||
required List<Product> products,
|
||||
required Option<ProductFailure> failureOptionProduct,
|
||||
String? categoryId,
|
||||
String? search,
|
||||
@Default(false) bool isFetching,
|
||||
@Default(false) bool hasReachedMax,
|
||||
@Default(1) int page,
|
||||
}) = _ProductLoaderState;
|
||||
|
||||
factory ProductLoaderState.initial() =>
|
||||
ProductLoaderState(products: [], failureOptionProduct: none());
|
||||
}
|
||||
@ -8,4 +8,7 @@ class ApiPath {
|
||||
|
||||
// Category
|
||||
static const String category = '/api/v1/categories';
|
||||
|
||||
// Product
|
||||
static const String product = '/api/v1/products';
|
||||
}
|
||||
|
||||
43
lib/domain/product/entities/product_entity.dart
Normal file
43
lib/domain/product/entities/product_entity.dart
Normal file
@ -0,0 +1,43 @@
|
||||
part of '../product.dart';
|
||||
|
||||
@freezed
|
||||
class Product with _$Product {
|
||||
const factory Product({
|
||||
required String id,
|
||||
required String organizationId,
|
||||
required String categoryId,
|
||||
required String sku,
|
||||
required String name,
|
||||
required String description,
|
||||
required int price,
|
||||
required int cost,
|
||||
required String businessType,
|
||||
required String imageUrl,
|
||||
required String printerType,
|
||||
required Map<String, dynamic> metadata,
|
||||
required bool isActive,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required List<ProductVariant> variants,
|
||||
}) = _Product;
|
||||
|
||||
/// ✅ factory kosong untuk default state
|
||||
factory Product.empty() => Product(
|
||||
id: '',
|
||||
organizationId: '',
|
||||
categoryId: '',
|
||||
sku: '',
|
||||
name: '',
|
||||
description: '',
|
||||
price: 0,
|
||||
cost: 0,
|
||||
businessType: '',
|
||||
imageUrl: '',
|
||||
printerType: '',
|
||||
metadata: {},
|
||||
isActive: false,
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
variants: [],
|
||||
);
|
||||
}
|
||||
26
lib/domain/product/entities/product_variant_entity.dart
Normal file
26
lib/domain/product/entities/product_variant_entity.dart
Normal file
@ -0,0 +1,26 @@
|
||||
part of '../product.dart';
|
||||
|
||||
@freezed
|
||||
class ProductVariant with _$ProductVariant {
|
||||
const factory ProductVariant({
|
||||
required String id,
|
||||
required String productId,
|
||||
required String name,
|
||||
required int priceModifier,
|
||||
required int cost,
|
||||
required Map<String, dynamic> metadata,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
}) = _ProductVariant;
|
||||
|
||||
factory ProductVariant.empty() => ProductVariant(
|
||||
id: '',
|
||||
productId: '',
|
||||
name: '',
|
||||
priceModifier: 0,
|
||||
cost: 0,
|
||||
metadata: {},
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
}
|
||||
10
lib/domain/product/failures/product_failure.dart
Normal file
10
lib/domain/product/failures/product_failure.dart
Normal file
@ -0,0 +1,10 @@
|
||||
part of '../product.dart';
|
||||
|
||||
@freezed
|
||||
sealed class ProductFailure with _$ProductFailure {
|
||||
const factory ProductFailure.serverError(ApiFailure failure) = _ServerError;
|
||||
const factory ProductFailure.unexpectedError() = _UnexpectedError;
|
||||
const factory ProductFailure.empty() = _Empty;
|
||||
const factory ProductFailure.dynamicErrorMessage(String erroMessage) =
|
||||
_DynamicErrorMessage;
|
||||
}
|
||||
11
lib/domain/product/product.dart
Normal file
11
lib/domain/product/product.dart
Normal file
@ -0,0 +1,11 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import '../../common/api/api_failure.dart';
|
||||
|
||||
part 'product.freezed.dart';
|
||||
|
||||
part 'entities/product_entity.dart';
|
||||
part 'entities/product_variant_entity.dart';
|
||||
part 'failures/product_failure.dart';
|
||||
part 'repositories/i_product_repository.dart';
|
||||
1435
lib/domain/product/product.freezed.dart
Normal file
1435
lib/domain/product/product.freezed.dart
Normal file
File diff suppressed because it is too large
Load Diff
10
lib/domain/product/repositories/i_product_repository.dart
Normal file
10
lib/domain/product/repositories/i_product_repository.dart
Normal file
@ -0,0 +1,10 @@
|
||||
part of '../product.dart';
|
||||
|
||||
abstract class IProductRepository {
|
||||
Future<Either<ProductFailure, List<Product>>> get({
|
||||
int page = 1,
|
||||
int limit = 10,
|
||||
String? categoryId,
|
||||
String? search,
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:data_channel/data_channel.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
|
||||
import '../../../common/api/api_client.dart';
|
||||
import '../../../common/api/api_failure.dart';
|
||||
import '../../../common/url/api_path.dart';
|
||||
import '../../../domain/product/product.dart';
|
||||
import '../product_dtos.dart';
|
||||
|
||||
@injectable
|
||||
class ProductRemoteDataProvider {
|
||||
final ApiClient _apiClient;
|
||||
final String _logName = 'ProductRemoteDataProvider';
|
||||
|
||||
ProductRemoteDataProvider(this._apiClient);
|
||||
|
||||
Future<DC<ProductFailure, List<ProductDto>>> fetch({
|
||||
int page = 1,
|
||||
int limit = 10,
|
||||
String? categoryId,
|
||||
String? search,
|
||||
}) async {
|
||||
try {
|
||||
Map<String, dynamic> params = {'page': page, 'limit': limit};
|
||||
|
||||
if (categoryId != null) {
|
||||
params['category_id'] = categoryId;
|
||||
}
|
||||
|
||||
if (search != null) {
|
||||
params['search'] = search;
|
||||
}
|
||||
|
||||
final response = await _apiClient.get(ApiPath.product, params: params);
|
||||
|
||||
if (response.data['data'] == null) {
|
||||
return DC.error(ProductFailure.empty());
|
||||
}
|
||||
|
||||
final dto = (response.data['data']['products'] as List)
|
||||
.map((item) => ProductDto.fromJson(item))
|
||||
.toList();
|
||||
|
||||
return DC.data(dto);
|
||||
} on ApiFailure catch (e, s) {
|
||||
log('fetchProductError', name: _logName, error: e, stackTrace: s);
|
||||
return DC.error(ProductFailure.serverError(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
70
lib/infrastructure/product/dto/product_dto.dart
Normal file
70
lib/infrastructure/product/dto/product_dto.dart
Normal file
@ -0,0 +1,70 @@
|
||||
part of '../product_dtos.dart';
|
||||
|
||||
@freezed
|
||||
class ProductDto with _$ProductDto {
|
||||
const ProductDto._();
|
||||
|
||||
const factory ProductDto({
|
||||
@JsonKey(name: 'id') String? id,
|
||||
@JsonKey(name: 'organization_id') String? organizationId,
|
||||
@JsonKey(name: 'category_id') String? categoryId,
|
||||
@JsonKey(name: 'sku') String? sku,
|
||||
@JsonKey(name: 'name') String? name,
|
||||
@JsonKey(name: 'description') String? description,
|
||||
@JsonKey(name: 'price') int? price,
|
||||
@JsonKey(name: 'cost') int? cost,
|
||||
@JsonKey(name: 'business_type') String? businessType,
|
||||
@JsonKey(name: 'image_url') String? imageUrl,
|
||||
@JsonKey(name: 'printer_type') String? printerType,
|
||||
@JsonKey(name: 'metadata') Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'is_active') bool? isActive,
|
||||
@JsonKey(name: 'created_at') DateTime? createdAt,
|
||||
@JsonKey(name: 'updated_at') DateTime? updatedAt,
|
||||
@JsonKey(name: 'variants') List<ProductVariantDto>? variants,
|
||||
}) = _ProductDto;
|
||||
|
||||
factory ProductDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$ProductDtoFromJson(json);
|
||||
|
||||
/// DTO -> Domain (isi default kalau null)
|
||||
Product toDomain() => Product(
|
||||
id: id ?? '',
|
||||
organizationId: organizationId ?? '',
|
||||
categoryId: categoryId ?? '',
|
||||
sku: sku ?? '',
|
||||
name: name ?? '',
|
||||
description: description ?? '',
|
||||
price: price ?? 0,
|
||||
cost: cost ?? 0,
|
||||
businessType: businessType ?? '',
|
||||
imageUrl: imageUrl ?? '',
|
||||
printerType: printerType ?? '',
|
||||
metadata: metadata ?? {},
|
||||
isActive: isActive ?? false,
|
||||
createdAt: createdAt ?? DateTime.now(),
|
||||
updatedAt: updatedAt ?? DateTime.now(),
|
||||
variants: variants?.map((v) => v.toDomain()).toList() ?? [],
|
||||
);
|
||||
|
||||
/// Domain -> DTO
|
||||
factory ProductDto.fromDomain(Product product) => ProductDto(
|
||||
id: product.id,
|
||||
organizationId: product.organizationId,
|
||||
categoryId: product.categoryId,
|
||||
sku: product.sku,
|
||||
name: product.name,
|
||||
description: product.description,
|
||||
price: product.price,
|
||||
cost: product.cost,
|
||||
businessType: product.businessType,
|
||||
imageUrl: product.imageUrl,
|
||||
printerType: product.printerType,
|
||||
metadata: product.metadata,
|
||||
isActive: product.isActive,
|
||||
createdAt: product.createdAt,
|
||||
updatedAt: product.updatedAt,
|
||||
variants: product.variants
|
||||
.map((v) => ProductVariantDto.fromDomain(v))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
45
lib/infrastructure/product/dto/product_variant_dto.dart
Normal file
45
lib/infrastructure/product/dto/product_variant_dto.dart
Normal file
@ -0,0 +1,45 @@
|
||||
part of '../product_dtos.dart';
|
||||
|
||||
@freezed
|
||||
class ProductVariantDto with _$ProductVariantDto {
|
||||
const ProductVariantDto._();
|
||||
|
||||
const factory ProductVariantDto({
|
||||
@JsonKey(name: 'id') String? id,
|
||||
@JsonKey(name: 'product_id') String? productId,
|
||||
@JsonKey(name: 'name') String? name,
|
||||
@JsonKey(name: 'price_modifier') int? priceModifier,
|
||||
@JsonKey(name: 'cost') int? cost,
|
||||
@JsonKey(name: 'metadata') Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'created_at') DateTime? createdAt,
|
||||
@JsonKey(name: 'updated_at') DateTime? updatedAt,
|
||||
}) = _ProductVariantDto;
|
||||
|
||||
factory ProductVariantDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$ProductVariantDtoFromJson(json);
|
||||
|
||||
/// DTO -> Domain
|
||||
ProductVariant toDomain() => ProductVariant(
|
||||
id: id ?? '',
|
||||
productId: productId ?? '',
|
||||
name: name ?? '',
|
||||
priceModifier: priceModifier ?? 0,
|
||||
cost: cost ?? 0,
|
||||
metadata: metadata ?? {},
|
||||
createdAt: createdAt ?? DateTime.now(),
|
||||
updatedAt: updatedAt ?? DateTime.now(),
|
||||
);
|
||||
|
||||
/// Domain -> DTO
|
||||
factory ProductVariantDto.fromDomain(ProductVariant variant) =>
|
||||
ProductVariantDto(
|
||||
id: variant.id,
|
||||
productId: variant.productId,
|
||||
name: variant.name,
|
||||
priceModifier: variant.priceModifier,
|
||||
cost: variant.cost,
|
||||
metadata: variant.metadata,
|
||||
createdAt: variant.createdAt,
|
||||
updatedAt: variant.updatedAt,
|
||||
);
|
||||
}
|
||||
9
lib/infrastructure/product/product_dtos.dart
Normal file
9
lib/infrastructure/product/product_dtos.dart
Normal file
@ -0,0 +1,9 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import '../../domain/product/product.dart';
|
||||
|
||||
part 'product_dtos.freezed.dart';
|
||||
part 'product_dtos.g.dart';
|
||||
|
||||
part 'dto/product_dto.dart';
|
||||
part 'dto/product_variant_dto.dart';
|
||||
926
lib/infrastructure/product/product_dtos.freezed.dart
Normal file
926
lib/infrastructure/product/product_dtos.freezed.dart
Normal file
@ -0,0 +1,926 @@
|
||||
// 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 'product_dtos.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(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',
|
||||
);
|
||||
|
||||
ProductDto _$ProductDtoFromJson(Map<String, dynamic> json) {
|
||||
return _ProductDto.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ProductDto {
|
||||
@JsonKey(name: 'id')
|
||||
String? get id => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'organization_id')
|
||||
String? get organizationId => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'category_id')
|
||||
String? get categoryId => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'sku')
|
||||
String? get sku => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'name')
|
||||
String? get name => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'description')
|
||||
String? get description => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'price')
|
||||
int? get price => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'cost')
|
||||
int? get cost => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'business_type')
|
||||
String? get businessType => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'image_url')
|
||||
String? get imageUrl => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'printer_type')
|
||||
String? get printerType => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'metadata')
|
||||
Map<String, dynamic>? get metadata => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'is_active')
|
||||
bool? get isActive => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'created_at')
|
||||
DateTime? get createdAt => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'updated_at')
|
||||
DateTime? get updatedAt => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'variants')
|
||||
List<ProductVariantDto>? get variants => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this ProductDto to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ProductDto
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$ProductDtoCopyWith<ProductDto> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ProductDtoCopyWith<$Res> {
|
||||
factory $ProductDtoCopyWith(
|
||||
ProductDto value,
|
||||
$Res Function(ProductDto) then,
|
||||
) = _$ProductDtoCopyWithImpl<$Res, ProductDto>;
|
||||
@useResult
|
||||
$Res call({
|
||||
@JsonKey(name: 'id') String? id,
|
||||
@JsonKey(name: 'organization_id') String? organizationId,
|
||||
@JsonKey(name: 'category_id') String? categoryId,
|
||||
@JsonKey(name: 'sku') String? sku,
|
||||
@JsonKey(name: 'name') String? name,
|
||||
@JsonKey(name: 'description') String? description,
|
||||
@JsonKey(name: 'price') int? price,
|
||||
@JsonKey(name: 'cost') int? cost,
|
||||
@JsonKey(name: 'business_type') String? businessType,
|
||||
@JsonKey(name: 'image_url') String? imageUrl,
|
||||
@JsonKey(name: 'printer_type') String? printerType,
|
||||
@JsonKey(name: 'metadata') Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'is_active') bool? isActive,
|
||||
@JsonKey(name: 'created_at') DateTime? createdAt,
|
||||
@JsonKey(name: 'updated_at') DateTime? updatedAt,
|
||||
@JsonKey(name: 'variants') List<ProductVariantDto>? variants,
|
||||
});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ProductDtoCopyWithImpl<$Res, $Val extends ProductDto>
|
||||
implements $ProductDtoCopyWith<$Res> {
|
||||
_$ProductDtoCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ProductDto
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = freezed,
|
||||
Object? organizationId = freezed,
|
||||
Object? categoryId = freezed,
|
||||
Object? sku = freezed,
|
||||
Object? name = freezed,
|
||||
Object? description = freezed,
|
||||
Object? price = freezed,
|
||||
Object? cost = freezed,
|
||||
Object? businessType = freezed,
|
||||
Object? imageUrl = freezed,
|
||||
Object? printerType = freezed,
|
||||
Object? metadata = freezed,
|
||||
Object? isActive = freezed,
|
||||
Object? createdAt = freezed,
|
||||
Object? updatedAt = freezed,
|
||||
Object? variants = freezed,
|
||||
}) {
|
||||
return _then(
|
||||
_value.copyWith(
|
||||
id: freezed == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
organizationId: freezed == organizationId
|
||||
? _value.organizationId
|
||||
: organizationId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
categoryId: freezed == categoryId
|
||||
? _value.categoryId
|
||||
: categoryId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
sku: freezed == sku
|
||||
? _value.sku
|
||||
: sku // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
name: freezed == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
description: freezed == description
|
||||
? _value.description
|
||||
: description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
price: freezed == price
|
||||
? _value.price
|
||||
: price // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
cost: freezed == cost
|
||||
? _value.cost
|
||||
: cost // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
businessType: freezed == businessType
|
||||
? _value.businessType
|
||||
: businessType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
imageUrl: freezed == imageUrl
|
||||
? _value.imageUrl
|
||||
: imageUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
printerType: freezed == printerType
|
||||
? _value.printerType
|
||||
: printerType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
metadata: freezed == metadata
|
||||
? _value.metadata
|
||||
: metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,
|
||||
isActive: freezed == isActive
|
||||
? _value.isActive
|
||||
: isActive // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
createdAt: freezed == createdAt
|
||||
? _value.createdAt
|
||||
: createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
updatedAt: freezed == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
variants: freezed == variants
|
||||
? _value.variants
|
||||
: variants // ignore: cast_nullable_to_non_nullable
|
||||
as List<ProductVariantDto>?,
|
||||
)
|
||||
as $Val,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ProductDtoImplCopyWith<$Res>
|
||||
implements $ProductDtoCopyWith<$Res> {
|
||||
factory _$$ProductDtoImplCopyWith(
|
||||
_$ProductDtoImpl value,
|
||||
$Res Function(_$ProductDtoImpl) then,
|
||||
) = __$$ProductDtoImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({
|
||||
@JsonKey(name: 'id') String? id,
|
||||
@JsonKey(name: 'organization_id') String? organizationId,
|
||||
@JsonKey(name: 'category_id') String? categoryId,
|
||||
@JsonKey(name: 'sku') String? sku,
|
||||
@JsonKey(name: 'name') String? name,
|
||||
@JsonKey(name: 'description') String? description,
|
||||
@JsonKey(name: 'price') int? price,
|
||||
@JsonKey(name: 'cost') int? cost,
|
||||
@JsonKey(name: 'business_type') String? businessType,
|
||||
@JsonKey(name: 'image_url') String? imageUrl,
|
||||
@JsonKey(name: 'printer_type') String? printerType,
|
||||
@JsonKey(name: 'metadata') Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'is_active') bool? isActive,
|
||||
@JsonKey(name: 'created_at') DateTime? createdAt,
|
||||
@JsonKey(name: 'updated_at') DateTime? updatedAt,
|
||||
@JsonKey(name: 'variants') List<ProductVariantDto>? variants,
|
||||
});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ProductDtoImplCopyWithImpl<$Res>
|
||||
extends _$ProductDtoCopyWithImpl<$Res, _$ProductDtoImpl>
|
||||
implements _$$ProductDtoImplCopyWith<$Res> {
|
||||
__$$ProductDtoImplCopyWithImpl(
|
||||
_$ProductDtoImpl _value,
|
||||
$Res Function(_$ProductDtoImpl) _then,
|
||||
) : super(_value, _then);
|
||||
|
||||
/// Create a copy of ProductDto
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = freezed,
|
||||
Object? organizationId = freezed,
|
||||
Object? categoryId = freezed,
|
||||
Object? sku = freezed,
|
||||
Object? name = freezed,
|
||||
Object? description = freezed,
|
||||
Object? price = freezed,
|
||||
Object? cost = freezed,
|
||||
Object? businessType = freezed,
|
||||
Object? imageUrl = freezed,
|
||||
Object? printerType = freezed,
|
||||
Object? metadata = freezed,
|
||||
Object? isActive = freezed,
|
||||
Object? createdAt = freezed,
|
||||
Object? updatedAt = freezed,
|
||||
Object? variants = freezed,
|
||||
}) {
|
||||
return _then(
|
||||
_$ProductDtoImpl(
|
||||
id: freezed == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
organizationId: freezed == organizationId
|
||||
? _value.organizationId
|
||||
: organizationId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
categoryId: freezed == categoryId
|
||||
? _value.categoryId
|
||||
: categoryId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
sku: freezed == sku
|
||||
? _value.sku
|
||||
: sku // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
name: freezed == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
description: freezed == description
|
||||
? _value.description
|
||||
: description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
price: freezed == price
|
||||
? _value.price
|
||||
: price // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
cost: freezed == cost
|
||||
? _value.cost
|
||||
: cost // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
businessType: freezed == businessType
|
||||
? _value.businessType
|
||||
: businessType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
imageUrl: freezed == imageUrl
|
||||
? _value.imageUrl
|
||||
: imageUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
printerType: freezed == printerType
|
||||
? _value.printerType
|
||||
: printerType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
metadata: freezed == metadata
|
||||
? _value._metadata
|
||||
: metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,
|
||||
isActive: freezed == isActive
|
||||
? _value.isActive
|
||||
: isActive // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
createdAt: freezed == createdAt
|
||||
? _value.createdAt
|
||||
: createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
updatedAt: freezed == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
variants: freezed == variants
|
||||
? _value._variants
|
||||
: variants // ignore: cast_nullable_to_non_nullable
|
||||
as List<ProductVariantDto>?,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$ProductDtoImpl extends _ProductDto {
|
||||
const _$ProductDtoImpl({
|
||||
@JsonKey(name: 'id') this.id,
|
||||
@JsonKey(name: 'organization_id') this.organizationId,
|
||||
@JsonKey(name: 'category_id') this.categoryId,
|
||||
@JsonKey(name: 'sku') this.sku,
|
||||
@JsonKey(name: 'name') this.name,
|
||||
@JsonKey(name: 'description') this.description,
|
||||
@JsonKey(name: 'price') this.price,
|
||||
@JsonKey(name: 'cost') this.cost,
|
||||
@JsonKey(name: 'business_type') this.businessType,
|
||||
@JsonKey(name: 'image_url') this.imageUrl,
|
||||
@JsonKey(name: 'printer_type') this.printerType,
|
||||
@JsonKey(name: 'metadata') final Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'is_active') this.isActive,
|
||||
@JsonKey(name: 'created_at') this.createdAt,
|
||||
@JsonKey(name: 'updated_at') this.updatedAt,
|
||||
@JsonKey(name: 'variants') final List<ProductVariantDto>? variants,
|
||||
}) : _metadata = metadata,
|
||||
_variants = variants,
|
||||
super._();
|
||||
|
||||
factory _$ProductDtoImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ProductDtoImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'id')
|
||||
final String? id;
|
||||
@override
|
||||
@JsonKey(name: 'organization_id')
|
||||
final String? organizationId;
|
||||
@override
|
||||
@JsonKey(name: 'category_id')
|
||||
final String? categoryId;
|
||||
@override
|
||||
@JsonKey(name: 'sku')
|
||||
final String? sku;
|
||||
@override
|
||||
@JsonKey(name: 'name')
|
||||
final String? name;
|
||||
@override
|
||||
@JsonKey(name: 'description')
|
||||
final String? description;
|
||||
@override
|
||||
@JsonKey(name: 'price')
|
||||
final int? price;
|
||||
@override
|
||||
@JsonKey(name: 'cost')
|
||||
final int? cost;
|
||||
@override
|
||||
@JsonKey(name: 'business_type')
|
||||
final String? businessType;
|
||||
@override
|
||||
@JsonKey(name: 'image_url')
|
||||
final String? imageUrl;
|
||||
@override
|
||||
@JsonKey(name: 'printer_type')
|
||||
final String? printerType;
|
||||
final Map<String, dynamic>? _metadata;
|
||||
@override
|
||||
@JsonKey(name: 'metadata')
|
||||
Map<String, dynamic>? get metadata {
|
||||
final value = _metadata;
|
||||
if (value == null) return null;
|
||||
if (_metadata is EqualUnmodifiableMapView) return _metadata;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(value);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'is_active')
|
||||
final bool? isActive;
|
||||
@override
|
||||
@JsonKey(name: 'created_at')
|
||||
final DateTime? createdAt;
|
||||
@override
|
||||
@JsonKey(name: 'updated_at')
|
||||
final DateTime? updatedAt;
|
||||
final List<ProductVariantDto>? _variants;
|
||||
@override
|
||||
@JsonKey(name: 'variants')
|
||||
List<ProductVariantDto>? get variants {
|
||||
final value = _variants;
|
||||
if (value == null) return null;
|
||||
if (_variants is EqualUnmodifiableListView) return _variants;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductDto(id: $id, organizationId: $organizationId, categoryId: $categoryId, sku: $sku, name: $name, description: $description, price: $price, cost: $cost, businessType: $businessType, imageUrl: $imageUrl, printerType: $printerType, metadata: $metadata, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt, variants: $variants)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ProductDtoImpl &&
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.organizationId, organizationId) ||
|
||||
other.organizationId == organizationId) &&
|
||||
(identical(other.categoryId, categoryId) ||
|
||||
other.categoryId == categoryId) &&
|
||||
(identical(other.sku, sku) || other.sku == sku) &&
|
||||
(identical(other.name, name) || other.name == name) &&
|
||||
(identical(other.description, description) ||
|
||||
other.description == description) &&
|
||||
(identical(other.price, price) || other.price == price) &&
|
||||
(identical(other.cost, cost) || other.cost == cost) &&
|
||||
(identical(other.businessType, businessType) ||
|
||||
other.businessType == businessType) &&
|
||||
(identical(other.imageUrl, imageUrl) ||
|
||||
other.imageUrl == imageUrl) &&
|
||||
(identical(other.printerType, printerType) ||
|
||||
other.printerType == printerType) &&
|
||||
const DeepCollectionEquality().equals(other._metadata, _metadata) &&
|
||||
(identical(other.isActive, isActive) ||
|
||||
other.isActive == isActive) &&
|
||||
(identical(other.createdAt, createdAt) ||
|
||||
other.createdAt == createdAt) &&
|
||||
(identical(other.updatedAt, updatedAt) ||
|
||||
other.updatedAt == updatedAt) &&
|
||||
const DeepCollectionEquality().equals(other._variants, _variants));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
id,
|
||||
organizationId,
|
||||
categoryId,
|
||||
sku,
|
||||
name,
|
||||
description,
|
||||
price,
|
||||
cost,
|
||||
businessType,
|
||||
imageUrl,
|
||||
printerType,
|
||||
const DeepCollectionEquality().hash(_metadata),
|
||||
isActive,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
const DeepCollectionEquality().hash(_variants),
|
||||
);
|
||||
|
||||
/// Create a copy of ProductDto
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ProductDtoImplCopyWith<_$ProductDtoImpl> get copyWith =>
|
||||
__$$ProductDtoImplCopyWithImpl<_$ProductDtoImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$ProductDtoImplToJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _ProductDto extends ProductDto {
|
||||
const factory _ProductDto({
|
||||
@JsonKey(name: 'id') final String? id,
|
||||
@JsonKey(name: 'organization_id') final String? organizationId,
|
||||
@JsonKey(name: 'category_id') final String? categoryId,
|
||||
@JsonKey(name: 'sku') final String? sku,
|
||||
@JsonKey(name: 'name') final String? name,
|
||||
@JsonKey(name: 'description') final String? description,
|
||||
@JsonKey(name: 'price') final int? price,
|
||||
@JsonKey(name: 'cost') final int? cost,
|
||||
@JsonKey(name: 'business_type') final String? businessType,
|
||||
@JsonKey(name: 'image_url') final String? imageUrl,
|
||||
@JsonKey(name: 'printer_type') final String? printerType,
|
||||
@JsonKey(name: 'metadata') final Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'is_active') final bool? isActive,
|
||||
@JsonKey(name: 'created_at') final DateTime? createdAt,
|
||||
@JsonKey(name: 'updated_at') final DateTime? updatedAt,
|
||||
@JsonKey(name: 'variants') final List<ProductVariantDto>? variants,
|
||||
}) = _$ProductDtoImpl;
|
||||
const _ProductDto._() : super._();
|
||||
|
||||
factory _ProductDto.fromJson(Map<String, dynamic> json) =
|
||||
_$ProductDtoImpl.fromJson;
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'id')
|
||||
String? get id;
|
||||
@override
|
||||
@JsonKey(name: 'organization_id')
|
||||
String? get organizationId;
|
||||
@override
|
||||
@JsonKey(name: 'category_id')
|
||||
String? get categoryId;
|
||||
@override
|
||||
@JsonKey(name: 'sku')
|
||||
String? get sku;
|
||||
@override
|
||||
@JsonKey(name: 'name')
|
||||
String? get name;
|
||||
@override
|
||||
@JsonKey(name: 'description')
|
||||
String? get description;
|
||||
@override
|
||||
@JsonKey(name: 'price')
|
||||
int? get price;
|
||||
@override
|
||||
@JsonKey(name: 'cost')
|
||||
int? get cost;
|
||||
@override
|
||||
@JsonKey(name: 'business_type')
|
||||
String? get businessType;
|
||||
@override
|
||||
@JsonKey(name: 'image_url')
|
||||
String? get imageUrl;
|
||||
@override
|
||||
@JsonKey(name: 'printer_type')
|
||||
String? get printerType;
|
||||
@override
|
||||
@JsonKey(name: 'metadata')
|
||||
Map<String, dynamic>? get metadata;
|
||||
@override
|
||||
@JsonKey(name: 'is_active')
|
||||
bool? get isActive;
|
||||
@override
|
||||
@JsonKey(name: 'created_at')
|
||||
DateTime? get createdAt;
|
||||
@override
|
||||
@JsonKey(name: 'updated_at')
|
||||
DateTime? get updatedAt;
|
||||
@override
|
||||
@JsonKey(name: 'variants')
|
||||
List<ProductVariantDto>? get variants;
|
||||
|
||||
/// Create a copy of ProductDto
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ProductDtoImplCopyWith<_$ProductDtoImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
ProductVariantDto _$ProductVariantDtoFromJson(Map<String, dynamic> json) {
|
||||
return _ProductVariantDto.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ProductVariantDto {
|
||||
@JsonKey(name: 'id')
|
||||
String? get id => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'product_id')
|
||||
String? get productId => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'name')
|
||||
String? get name => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'price_modifier')
|
||||
int? get priceModifier => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'cost')
|
||||
int? get cost => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'metadata')
|
||||
Map<String, dynamic>? get metadata => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'created_at')
|
||||
DateTime? get createdAt => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'updated_at')
|
||||
DateTime? get updatedAt => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this ProductVariantDto to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ProductVariantDto
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$ProductVariantDtoCopyWith<ProductVariantDto> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ProductVariantDtoCopyWith<$Res> {
|
||||
factory $ProductVariantDtoCopyWith(
|
||||
ProductVariantDto value,
|
||||
$Res Function(ProductVariantDto) then,
|
||||
) = _$ProductVariantDtoCopyWithImpl<$Res, ProductVariantDto>;
|
||||
@useResult
|
||||
$Res call({
|
||||
@JsonKey(name: 'id') String? id,
|
||||
@JsonKey(name: 'product_id') String? productId,
|
||||
@JsonKey(name: 'name') String? name,
|
||||
@JsonKey(name: 'price_modifier') int? priceModifier,
|
||||
@JsonKey(name: 'cost') int? cost,
|
||||
@JsonKey(name: 'metadata') Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'created_at') DateTime? createdAt,
|
||||
@JsonKey(name: 'updated_at') DateTime? updatedAt,
|
||||
});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ProductVariantDtoCopyWithImpl<$Res, $Val extends ProductVariantDto>
|
||||
implements $ProductVariantDtoCopyWith<$Res> {
|
||||
_$ProductVariantDtoCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ProductVariantDto
|
||||
/// 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? name = freezed,
|
||||
Object? priceModifier = freezed,
|
||||
Object? cost = freezed,
|
||||
Object? metadata = freezed,
|
||||
Object? createdAt = 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?,
|
||||
name: freezed == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
priceModifier: freezed == priceModifier
|
||||
? _value.priceModifier
|
||||
: priceModifier // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
cost: freezed == cost
|
||||
? _value.cost
|
||||
: cost // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
metadata: freezed == metadata
|
||||
? _value.metadata
|
||||
: metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,
|
||||
createdAt: freezed == createdAt
|
||||
? _value.createdAt
|
||||
: createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
updatedAt: freezed == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
)
|
||||
as $Val,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ProductVariantDtoImplCopyWith<$Res>
|
||||
implements $ProductVariantDtoCopyWith<$Res> {
|
||||
factory _$$ProductVariantDtoImplCopyWith(
|
||||
_$ProductVariantDtoImpl value,
|
||||
$Res Function(_$ProductVariantDtoImpl) then,
|
||||
) = __$$ProductVariantDtoImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({
|
||||
@JsonKey(name: 'id') String? id,
|
||||
@JsonKey(name: 'product_id') String? productId,
|
||||
@JsonKey(name: 'name') String? name,
|
||||
@JsonKey(name: 'price_modifier') int? priceModifier,
|
||||
@JsonKey(name: 'cost') int? cost,
|
||||
@JsonKey(name: 'metadata') Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'created_at') DateTime? createdAt,
|
||||
@JsonKey(name: 'updated_at') DateTime? updatedAt,
|
||||
});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ProductVariantDtoImplCopyWithImpl<$Res>
|
||||
extends _$ProductVariantDtoCopyWithImpl<$Res, _$ProductVariantDtoImpl>
|
||||
implements _$$ProductVariantDtoImplCopyWith<$Res> {
|
||||
__$$ProductVariantDtoImplCopyWithImpl(
|
||||
_$ProductVariantDtoImpl _value,
|
||||
$Res Function(_$ProductVariantDtoImpl) _then,
|
||||
) : super(_value, _then);
|
||||
|
||||
/// Create a copy of ProductVariantDto
|
||||
/// 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? name = freezed,
|
||||
Object? priceModifier = freezed,
|
||||
Object? cost = freezed,
|
||||
Object? metadata = freezed,
|
||||
Object? createdAt = freezed,
|
||||
Object? updatedAt = freezed,
|
||||
}) {
|
||||
return _then(
|
||||
_$ProductVariantDtoImpl(
|
||||
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?,
|
||||
name: freezed == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
priceModifier: freezed == priceModifier
|
||||
? _value.priceModifier
|
||||
: priceModifier // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
cost: freezed == cost
|
||||
? _value.cost
|
||||
: cost // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
metadata: freezed == metadata
|
||||
? _value._metadata
|
||||
: metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,
|
||||
createdAt: freezed == createdAt
|
||||
? _value.createdAt
|
||||
: createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
updatedAt: freezed == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$ProductVariantDtoImpl extends _ProductVariantDto {
|
||||
const _$ProductVariantDtoImpl({
|
||||
@JsonKey(name: 'id') this.id,
|
||||
@JsonKey(name: 'product_id') this.productId,
|
||||
@JsonKey(name: 'name') this.name,
|
||||
@JsonKey(name: 'price_modifier') this.priceModifier,
|
||||
@JsonKey(name: 'cost') this.cost,
|
||||
@JsonKey(name: 'metadata') final Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'created_at') this.createdAt,
|
||||
@JsonKey(name: 'updated_at') this.updatedAt,
|
||||
}) : _metadata = metadata,
|
||||
super._();
|
||||
|
||||
factory _$ProductVariantDtoImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ProductVariantDtoImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'id')
|
||||
final String? id;
|
||||
@override
|
||||
@JsonKey(name: 'product_id')
|
||||
final String? productId;
|
||||
@override
|
||||
@JsonKey(name: 'name')
|
||||
final String? name;
|
||||
@override
|
||||
@JsonKey(name: 'price_modifier')
|
||||
final int? priceModifier;
|
||||
@override
|
||||
@JsonKey(name: 'cost')
|
||||
final int? cost;
|
||||
final Map<String, dynamic>? _metadata;
|
||||
@override
|
||||
@JsonKey(name: 'metadata')
|
||||
Map<String, dynamic>? get metadata {
|
||||
final value = _metadata;
|
||||
if (value == null) return null;
|
||||
if (_metadata is EqualUnmodifiableMapView) return _metadata;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(value);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'created_at')
|
||||
final DateTime? createdAt;
|
||||
@override
|
||||
@JsonKey(name: 'updated_at')
|
||||
final DateTime? updatedAt;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductVariantDto(id: $id, productId: $productId, name: $name, priceModifier: $priceModifier, cost: $cost, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ProductVariantDtoImpl &&
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.productId, productId) ||
|
||||
other.productId == productId) &&
|
||||
(identical(other.name, name) || other.name == name) &&
|
||||
(identical(other.priceModifier, priceModifier) ||
|
||||
other.priceModifier == priceModifier) &&
|
||||
(identical(other.cost, cost) || other.cost == cost) &&
|
||||
const DeepCollectionEquality().equals(other._metadata, _metadata) &&
|
||||
(identical(other.createdAt, createdAt) ||
|
||||
other.createdAt == createdAt) &&
|
||||
(identical(other.updatedAt, updatedAt) ||
|
||||
other.updatedAt == updatedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
id,
|
||||
productId,
|
||||
name,
|
||||
priceModifier,
|
||||
cost,
|
||||
const DeepCollectionEquality().hash(_metadata),
|
||||
createdAt,
|
||||
updatedAt,
|
||||
);
|
||||
|
||||
/// Create a copy of ProductVariantDto
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ProductVariantDtoImplCopyWith<_$ProductVariantDtoImpl> get copyWith =>
|
||||
__$$ProductVariantDtoImplCopyWithImpl<_$ProductVariantDtoImpl>(
|
||||
this,
|
||||
_$identity,
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$ProductVariantDtoImplToJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _ProductVariantDto extends ProductVariantDto {
|
||||
const factory _ProductVariantDto({
|
||||
@JsonKey(name: 'id') final String? id,
|
||||
@JsonKey(name: 'product_id') final String? productId,
|
||||
@JsonKey(name: 'name') final String? name,
|
||||
@JsonKey(name: 'price_modifier') final int? priceModifier,
|
||||
@JsonKey(name: 'cost') final int? cost,
|
||||
@JsonKey(name: 'metadata') final Map<String, dynamic>? metadata,
|
||||
@JsonKey(name: 'created_at') final DateTime? createdAt,
|
||||
@JsonKey(name: 'updated_at') final DateTime? updatedAt,
|
||||
}) = _$ProductVariantDtoImpl;
|
||||
const _ProductVariantDto._() : super._();
|
||||
|
||||
factory _ProductVariantDto.fromJson(Map<String, dynamic> json) =
|
||||
_$ProductVariantDtoImpl.fromJson;
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'id')
|
||||
String? get id;
|
||||
@override
|
||||
@JsonKey(name: 'product_id')
|
||||
String? get productId;
|
||||
@override
|
||||
@JsonKey(name: 'name')
|
||||
String? get name;
|
||||
@override
|
||||
@JsonKey(name: 'price_modifier')
|
||||
int? get priceModifier;
|
||||
@override
|
||||
@JsonKey(name: 'cost')
|
||||
int? get cost;
|
||||
@override
|
||||
@JsonKey(name: 'metadata')
|
||||
Map<String, dynamic>? get metadata;
|
||||
@override
|
||||
@JsonKey(name: 'created_at')
|
||||
DateTime? get createdAt;
|
||||
@override
|
||||
@JsonKey(name: 'updated_at')
|
||||
DateTime? get updatedAt;
|
||||
|
||||
/// Create a copy of ProductVariantDto
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ProductVariantDtoImplCopyWith<_$ProductVariantDtoImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
83
lib/infrastructure/product/product_dtos.g.dart
Normal file
83
lib/infrastructure/product/product_dtos.g.dart
Normal file
@ -0,0 +1,83 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'product_dtos.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$ProductDtoImpl _$$ProductDtoImplFromJson(Map<String, dynamic> json) =>
|
||||
_$ProductDtoImpl(
|
||||
id: json['id'] as String?,
|
||||
organizationId: json['organization_id'] as String?,
|
||||
categoryId: json['category_id'] as String?,
|
||||
sku: json['sku'] as String?,
|
||||
name: json['name'] as String?,
|
||||
description: json['description'] as String?,
|
||||
price: (json['price'] as num?)?.toInt(),
|
||||
cost: (json['cost'] as num?)?.toInt(),
|
||||
businessType: json['business_type'] as String?,
|
||||
imageUrl: json['image_url'] as String?,
|
||||
printerType: json['printer_type'] as String?,
|
||||
metadata: json['metadata'] as Map<String, dynamic>?,
|
||||
isActive: json['is_active'] as bool?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
variants: (json['variants'] as List<dynamic>?)
|
||||
?.map((e) => ProductVariantDto.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ProductDtoImplToJson(_$ProductDtoImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'organization_id': instance.organizationId,
|
||||
'category_id': instance.categoryId,
|
||||
'sku': instance.sku,
|
||||
'name': instance.name,
|
||||
'description': instance.description,
|
||||
'price': instance.price,
|
||||
'cost': instance.cost,
|
||||
'business_type': instance.businessType,
|
||||
'image_url': instance.imageUrl,
|
||||
'printer_type': instance.printerType,
|
||||
'metadata': instance.metadata,
|
||||
'is_active': instance.isActive,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
'variants': instance.variants,
|
||||
};
|
||||
|
||||
_$ProductVariantDtoImpl _$$ProductVariantDtoImplFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _$ProductVariantDtoImpl(
|
||||
id: json['id'] as String?,
|
||||
productId: json['product_id'] as String?,
|
||||
name: json['name'] as String?,
|
||||
priceModifier: (json['price_modifier'] as num?)?.toInt(),
|
||||
cost: (json['cost'] as num?)?.toInt(),
|
||||
metadata: json['metadata'] as Map<String, dynamic>?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ProductVariantDtoImplToJson(
|
||||
_$ProductVariantDtoImpl instance,
|
||||
) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'product_id': instance.productId,
|
||||
'name': instance.name,
|
||||
'price_modifier': instance.priceModifier,
|
||||
'cost': instance.cost,
|
||||
'metadata': instance.metadata,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
};
|
||||
@ -0,0 +1,43 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
|
||||
import '../../../domain/product/product.dart';
|
||||
import '../datasources/remote_data_provider.dart';
|
||||
|
||||
@Injectable(as: IProductRepository)
|
||||
class ProductRepository implements IProductRepository {
|
||||
final ProductRemoteDataProvider _dataProvider;
|
||||
final String _logName = 'ProductRepository';
|
||||
|
||||
ProductRepository(this._dataProvider);
|
||||
|
||||
@override
|
||||
Future<Either<ProductFailure, List<Product>>> get({
|
||||
int page = 1,
|
||||
int limit = 10,
|
||||
String? categoryId,
|
||||
String? search,
|
||||
}) async {
|
||||
try {
|
||||
final result = await _dataProvider.fetch(
|
||||
page: page,
|
||||
limit: limit,
|
||||
categoryId: categoryId,
|
||||
search: search,
|
||||
);
|
||||
|
||||
if (result.hasError) {
|
||||
return left(result.error!);
|
||||
}
|
||||
|
||||
final auth = result.data!.map((e) => e.toDomain()).toList();
|
||||
|
||||
return right(auth);
|
||||
} catch (e, s) {
|
||||
log('getProductError', name: _logName, error: e, stackTrace: s);
|
||||
return left(const ProductFailure.unexpectedError());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,8 @@ import 'package:apskel_owner_flutter/application/category/category_loader/catego
|
||||
as _i183;
|
||||
import 'package:apskel_owner_flutter/application/language/language_bloc.dart'
|
||||
as _i455;
|
||||
import 'package:apskel_owner_flutter/application/product/product_loader/product_loader_bloc.dart'
|
||||
as _i458;
|
||||
import 'package:apskel_owner_flutter/application/sales/sales_loader/sales_loader_bloc.dart'
|
||||
as _i882;
|
||||
import 'package:apskel_owner_flutter/common/api/api_client.dart' as _i115;
|
||||
@ -33,6 +35,7 @@ import 'package:apskel_owner_flutter/domain/analytic/repositories/i_analytic_rep
|
||||
as _i477;
|
||||
import 'package:apskel_owner_flutter/domain/auth/auth.dart' as _i49;
|
||||
import 'package:apskel_owner_flutter/domain/category/category.dart' as _i1020;
|
||||
import 'package:apskel_owner_flutter/domain/product/product.dart' as _i419;
|
||||
import 'package:apskel_owner_flutter/env.dart' as _i6;
|
||||
import 'package:apskel_owner_flutter/infrastructure/analytic/datasource/remote_data_provider.dart'
|
||||
as _i866;
|
||||
@ -48,6 +51,10 @@ import 'package:apskel_owner_flutter/infrastructure/category/datasource/remote_d
|
||||
as _i333;
|
||||
import 'package:apskel_owner_flutter/infrastructure/category/repositories/category_repository.dart'
|
||||
as _i869;
|
||||
import 'package:apskel_owner_flutter/infrastructure/product/datasources/remote_data_provider.dart'
|
||||
as _i823;
|
||||
import 'package:apskel_owner_flutter/infrastructure/product/repositories/product_repository.dart'
|
||||
as _i121;
|
||||
import 'package:apskel_owner_flutter/presentation/router/app_router.dart'
|
||||
as _i258;
|
||||
import 'package:connectivity_plus/connectivity_plus.dart' as _i895;
|
||||
@ -110,6 +117,9 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
gh.factory<_i333.CategoryRemoteDataProvider>(
|
||||
() => _i333.CategoryRemoteDataProvider(gh<_i115.ApiClient>()),
|
||||
);
|
||||
gh.factory<_i823.ProductRemoteDataProvider>(
|
||||
() => _i823.ProductRemoteDataProvider(gh<_i115.ApiClient>()),
|
||||
);
|
||||
gh.factory<_i477.IAnalyticRepository>(
|
||||
() => _i393.AnalyticRepository(gh<_i866.AnalyticRemoteDataProvider>()),
|
||||
);
|
||||
@ -119,9 +129,15 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
gh<_i17.AuthRemoteDataProvider>(),
|
||||
),
|
||||
);
|
||||
gh.factory<_i419.IProductRepository>(
|
||||
() => _i121.ProductRepository(gh<_i823.ProductRemoteDataProvider>()),
|
||||
);
|
||||
gh.factory<_i1020.ICategoryRepository>(
|
||||
() => _i869.CategoryRepository(gh<_i333.CategoryRemoteDataProvider>()),
|
||||
);
|
||||
gh.factory<_i458.ProductLoaderBloc>(
|
||||
() => _i458.ProductLoaderBloc(gh<_i419.IProductRepository>()),
|
||||
);
|
||||
gh.factory<_i183.CategoryLoaderBloc>(
|
||||
() => _i183.CategoryLoaderBloc(gh<_i1020.ICategoryRepository>()),
|
||||
);
|
||||
|
||||
@ -4,11 +4,14 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
|
||||
import '../../../application/category/category_loader/category_loader_bloc.dart';
|
||||
import '../../../application/product/product_loader/product_loader_bloc.dart';
|
||||
import '../../../common/theme/theme.dart';
|
||||
import '../../../domain/category/category.dart';
|
||||
import '../../../domain/product/product.dart';
|
||||
import '../../../injection.dart';
|
||||
import '../../components/appbar/appbar.dart';
|
||||
import '../../components/button/button.dart';
|
||||
import '../../components/widgets/empty_widget.dart';
|
||||
import 'widgets/category_delegate.dart';
|
||||
import 'widgets/product_tile.dart';
|
||||
|
||||
@ -20,9 +23,18 @@ class ProductPage extends StatefulWidget implements AutoRouteWrapper {
|
||||
State<ProductPage> createState() => _ProductPageState();
|
||||
|
||||
@override
|
||||
Widget wrappedRoute(BuildContext context) => BlocProvider(
|
||||
create: (context) =>
|
||||
getIt<CategoryLoaderBloc>()..add(CategoryLoaderEvent.fetched()),
|
||||
Widget wrappedRoute(BuildContext context) => MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
create: (context) =>
|
||||
getIt<CategoryLoaderBloc>()..add(CategoryLoaderEvent.fetched()),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (context) =>
|
||||
getIt<ProductLoaderBloc>()
|
||||
..add(ProductLoaderEvent.fetched(isRefresh: true)),
|
||||
),
|
||||
],
|
||||
child: this,
|
||||
);
|
||||
}
|
||||
@ -34,109 +46,6 @@ class _ProductPageState extends State<ProductPage>
|
||||
Category selectedCategory = Category.addAllData();
|
||||
ViewType currentViewType = ViewType.grid;
|
||||
|
||||
// Sample product data
|
||||
List<Product> products = [
|
||||
Product(
|
||||
id: '1',
|
||||
name: 'Nasi Goreng Special',
|
||||
price: 25000,
|
||||
category: 'Makanan',
|
||||
stock: 50,
|
||||
imageUrl: 'assets/images/nasi_goreng.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
Product(
|
||||
id: '8',
|
||||
name: 'Nasi Goreng',
|
||||
price: 15000,
|
||||
category: 'Makanan',
|
||||
stock: 50,
|
||||
imageUrl: 'assets/images/nasi_goreng.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
Product(
|
||||
id: '9',
|
||||
name: 'Nasi Goreng Telor',
|
||||
price: 18000,
|
||||
category: 'Makanan',
|
||||
stock: 50,
|
||||
imageUrl: 'assets/images/nasi_goreng.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
Product(
|
||||
id: '10',
|
||||
name: 'Mie Goreng ',
|
||||
price: 18000,
|
||||
category: 'Makanan',
|
||||
stock: 50,
|
||||
imageUrl: 'assets/images/nasi_goreng.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
Product(
|
||||
id: '2',
|
||||
name: 'Es Teh Manis',
|
||||
price: 8000,
|
||||
category: 'Minuman',
|
||||
stock: 100,
|
||||
imageUrl: 'assets/images/es_teh.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
Product(
|
||||
id: '6',
|
||||
name: 'Es Jeruk',
|
||||
price: 10000,
|
||||
category: 'Minuman',
|
||||
stock: 100,
|
||||
imageUrl: 'assets/images/es_teh.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
Product(
|
||||
id: '7',
|
||||
name: 'Es Kelapa',
|
||||
price: 12000,
|
||||
category: 'Minuman',
|
||||
stock: 100,
|
||||
imageUrl: 'assets/images/es_teh.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
Product(
|
||||
id: '3',
|
||||
name: 'Keripik Singkong',
|
||||
price: 15000,
|
||||
category: 'Snack',
|
||||
stock: 25,
|
||||
imageUrl: 'assets/images/keripik.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
Product(
|
||||
id: '4',
|
||||
name: 'Es Krim Vanilla',
|
||||
price: 12000,
|
||||
category: 'Dessert',
|
||||
stock: 30,
|
||||
imageUrl: 'assets/images/ice_cream.jpg',
|
||||
isActive: false,
|
||||
),
|
||||
Product(
|
||||
id: '5',
|
||||
name: 'Ayam Bakar',
|
||||
price: 35000,
|
||||
category: 'Makanan',
|
||||
stock: 20,
|
||||
imageUrl: 'assets/images/ayam_bakar.jpg',
|
||||
isActive: true,
|
||||
),
|
||||
];
|
||||
|
||||
List<Product> get filteredProducts {
|
||||
return products.where((product) {
|
||||
bool matchesCategory =
|
||||
selectedCategory.name == 'Semua' ||
|
||||
product.category == selectedCategory.id;
|
||||
return matchesCategory;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
@ -144,16 +53,20 @@ class _ProductPageState extends State<ProductPage>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColor.background,
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
_buildSliverAppBar(),
|
||||
_buildCategoryFilter(),
|
||||
_buildProductContent(),
|
||||
_buildEmptyState(),
|
||||
],
|
||||
),
|
||||
return BlocBuilder<ProductLoaderBloc, ProductLoaderState>(
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColor.background,
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
_buildSliverAppBar(),
|
||||
_buildCategoryFilter(),
|
||||
_buildProductContent(state.products),
|
||||
_buildEmptyState(state.products),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -195,17 +108,17 @@ class _ProductPageState extends State<ProductPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildProductContent() {
|
||||
if (filteredProducts.isEmpty) {
|
||||
Widget _buildProductContent(List<Product> products) {
|
||||
if (products.isEmpty) {
|
||||
return const SliverToBoxAdapter(child: SizedBox.shrink());
|
||||
}
|
||||
|
||||
return currentViewType == ViewType.grid
|
||||
? _buildProductGrid()
|
||||
: _buildProductList();
|
||||
? _buildProductGrid(products)
|
||||
: _buildProductList(products);
|
||||
}
|
||||
|
||||
Widget _buildProductGrid() {
|
||||
Widget _buildProductGrid(List<Product> products) {
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
sliver: SliverGrid(
|
||||
@ -216,21 +129,21 @@ class _ProductPageState extends State<ProductPage>
|
||||
mainAxisSpacing: 16.0,
|
||||
),
|
||||
delegate: SliverChildBuilderDelegate((context, index) {
|
||||
final product = filteredProducts[index];
|
||||
final product = products[index];
|
||||
return ProductTile(product: product, onTap: () {});
|
||||
}, childCount: filteredProducts.length),
|
||||
}, childCount: products.length),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildProductList() {
|
||||
Widget _buildProductList(List<Product> products) {
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate((context, index) {
|
||||
final product = filteredProducts[index];
|
||||
final product = products[index];
|
||||
return _buildProductListItem(product);
|
||||
}, childCount: filteredProducts.length),
|
||||
}, childCount: products.length),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -300,7 +213,7 @@ class _ProductPageState extends State<ProductPage>
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
product.category,
|
||||
'',
|
||||
style: TextStyle(fontSize: 12, color: AppColor.textLight),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
@ -327,7 +240,7 @@ class _ProductPageState extends State<ProductPage>
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
'Stock: ${product.stock}',
|
||||
'Stock: ',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: product.isActive
|
||||
@ -370,62 +283,16 @@ class _ProductPageState extends State<ProductPage>
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildEmptyState() {
|
||||
if (filteredProducts.isNotEmpty) {
|
||||
Widget _buildEmptyState(List<Product> products) {
|
||||
if (products.isNotEmpty) {
|
||||
return const SliverToBoxAdapter(child: SizedBox.shrink());
|
||||
}
|
||||
|
||||
return SliverToBoxAdapter(
|
||||
child: Container(
|
||||
height: 300,
|
||||
margin: const EdgeInsets.all(32.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.inventory_2_outlined,
|
||||
size: 64,
|
||||
color: AppColor.textLight,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Tidak ada produk ditemukan',
|
||||
style: TextStyle(
|
||||
color: AppColor.textSecondary,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Coba ubah filter atau tambah produk baru',
|
||||
style: TextStyle(color: AppColor.textLight, fontSize: 14),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: EmptyWidget(
|
||||
title: 'Tidak ada produk ditemukan',
|
||||
message: 'Coba ubah filter atau tambah produk baru',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Product Model
|
||||
class Product {
|
||||
final String id;
|
||||
final String name;
|
||||
final int price;
|
||||
final String category;
|
||||
final int stock;
|
||||
final String imageUrl;
|
||||
bool isActive;
|
||||
|
||||
Product({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.price,
|
||||
required this.category,
|
||||
required this.stock,
|
||||
required this.imageUrl,
|
||||
required this.isActive,
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../common/theme/theme.dart';
|
||||
import '../../../../domain/product/product.dart';
|
||||
import '../../../components/spacer/spacer.dart';
|
||||
import '../product_page.dart';
|
||||
|
||||
class ProductTile extends StatelessWidget {
|
||||
final Product product;
|
||||
@ -156,7 +156,7 @@ class ProductTile extends StatelessWidget {
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
'Stok: ${product.stock}',
|
||||
'Stok: ',
|
||||
style: AppStyle.xs.copyWith(
|
||||
color: AppColor.textSecondary,
|
||||
fontSize: 9,
|
||||
@ -171,7 +171,7 @@ class ProductTile extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(3.0),
|
||||
),
|
||||
child: Text(
|
||||
product.category,
|
||||
'',
|
||||
style: AppStyle.xs.copyWith(
|
||||
color: product.isActive
|
||||
? AppColor.primary
|
||||
|
||||
@ -88,6 +88,7 @@ class ErrorRoute extends _i18.PageRouteInfo<ErrorRouteArgs> {
|
||||
_i19.VoidCallback? onRetry,
|
||||
_i19.VoidCallback? onBack,
|
||||
String? errorCode,
|
||||
_i19.IconData? errorIcon,
|
||||
List<_i18.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
ErrorRoute.name,
|
||||
@ -98,6 +99,7 @@ class ErrorRoute extends _i18.PageRouteInfo<ErrorRouteArgs> {
|
||||
onRetry: onRetry,
|
||||
onBack: onBack,
|
||||
errorCode: errorCode,
|
||||
errorIcon: errorIcon,
|
||||
),
|
||||
initialChildren: children,
|
||||
);
|
||||
@ -117,6 +119,7 @@ class ErrorRoute extends _i18.PageRouteInfo<ErrorRouteArgs> {
|
||||
onRetry: args.onRetry,
|
||||
onBack: args.onBack,
|
||||
errorCode: args.errorCode,
|
||||
errorIcon: args.errorIcon,
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -130,6 +133,7 @@ class ErrorRouteArgs {
|
||||
this.onRetry,
|
||||
this.onBack,
|
||||
this.errorCode,
|
||||
this.errorIcon,
|
||||
});
|
||||
|
||||
final _i19.Key? key;
|
||||
@ -144,9 +148,11 @@ class ErrorRouteArgs {
|
||||
|
||||
final String? errorCode;
|
||||
|
||||
final _i19.IconData? errorIcon;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ErrorRouteArgs{key: $key, title: $title, message: $message, onRetry: $onRetry, onBack: $onBack, errorCode: $errorCode}';
|
||||
return 'ErrorRouteArgs{key: $key, title: $title, message: $message, onRetry: $onRetry, onBack: $onBack, errorCode: $errorCode, errorIcon: $errorIcon}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user