diff --git a/lib/data/repositories/home_repository.dart b/lib/data/repositories/home_repository.dart index 3ba476e..3d8c010 100644 --- a/lib/data/repositories/home_repository.dart +++ b/lib/data/repositories/home_repository.dart @@ -8,7 +8,7 @@ import '../services/model/feedback_stats_response/feedback_stat_response.dart'; class HomeRepository { HomeRepository({required HomeService homeService}) - : _homeService = homeService; + : _homeService = homeService; final HomeService _homeService; Future> getHomeRecommendedTenders({ @@ -18,8 +18,11 @@ class HomeRepository { return _homeService.getRecommendedTenders(limit: limit, offset: offset); } - Future> getYourTenders() { - return _homeService.getYourTenders(); + Future> getYourTenders({ + required int limit, + required int offset, + }) { + return _homeService.getYourTenders(limit: limit, offset: offset); } Future> getTendersApprovalsState() { diff --git a/lib/data/services/api/home_api.dart b/lib/data/services/api/home_api.dart index c2cab7d..c0d4cc2 100644 --- a/lib/data/services/api/home_api.dart +++ b/lib/data/services/api/home_api.dart @@ -7,7 +7,15 @@ class HomeApi { return '$recommendedTenders?limit=$limit&offset=$offset'; } - static const String tenderApprovals = '/api/v1/tender-approvals'; + static const String tenderApprovalsBase = '/api/v1/tender-approvals'; + + static String getYourTenders({ + required int limit, + required int offset, + }) { + return '$tenderApprovalsBase?limit=$limit&offset=$offset'; + } + static const String tenderApprovalStats = '/api/v1/tender-approvals/stats'; static const String statsCompany = '/api/v1/feedback/stats/company'; } diff --git a/lib/data/services/home_service.dart b/lib/data/services/home_service.dart index 76f9c71..404d993 100644 --- a/lib/data/services/home_service.dart +++ b/lib/data/services/home_service.dart @@ -9,7 +9,7 @@ import '../../core/network/network_manager.dart'; class HomeService { HomeService({required NetworkManager networkManager}) - : _networkManager = networkManager; + : _networkManager = networkManager; final NetworkManager _networkManager; Future> getRecommendedTenders({ @@ -24,24 +24,24 @@ class HomeService { return result; } - Future> getYourTenders() async { + Future> getYourTenders({ + required int limit, + required int offset, + }) async { final result = await _networkManager.makeRequest( - HomeApi.tenderApprovals, + HomeApi.getYourTenders(limit: limit, offset: offset), (json) => TenderApprovalsResponse.fromJson(json), method: 'GET', ); - return result; } - Future> - getTendersApprovalsState() async { + Future> getTendersApprovalsState() async { final result = await _networkManager.makeRequest( HomeApi.tenderApprovalStats, (json) => TenderApprovalsStateResponse.fromJson(json), method: 'GET', ); - return result; } diff --git a/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.dart b/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.dart new file mode 100644 index 0000000..9469cdc --- /dev/null +++ b/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.dart @@ -0,0 +1,30 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import '../tender_approvals_data/tender_approvals_data.dart'; + +part 'tender_approvals_data_wrapper.freezed.dart'; +part 'tender_approvals_data_wrapper.g.dart'; + +@freezed +abstract class TenderApprovalsDataWrapper with _$TenderApprovalsDataWrapper { + const factory TenderApprovalsDataWrapper({ + required List? tenders, + required Metadata? metadata, + }) = _TenderApprovalsDataWrapper; + + factory TenderApprovalsDataWrapper.fromJson(Map json) => + _$TenderApprovalsDataWrapperFromJson(json); +} + +@freezed +abstract class Metadata with _$Metadata { + const factory Metadata({ + required int? total, + required int? limit, + required int? offset, + required int? page, + required int? pages, + }) = _Metadata; + + factory Metadata.fromJson(Map json) => + _$MetadataFromJson(json); +} diff --git a/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.freezed.dart b/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.freezed.dart new file mode 100644 index 0000000..f341f47 --- /dev/null +++ b/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.freezed.dart @@ -0,0 +1,587 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// 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 'tender_approvals_data_wrapper.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$TenderApprovalsDataWrapper { + + List? get tenders; Metadata? get metadata; +/// Create a copy of TenderApprovalsDataWrapper +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TenderApprovalsDataWrapperCopyWith get copyWith => _$TenderApprovalsDataWrapperCopyWithImpl(this as TenderApprovalsDataWrapper, _$identity); + + /// Serializes this TenderApprovalsDataWrapper to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderApprovalsDataWrapper&&const DeepCollectionEquality().equals(other.tenders, tenders)&&(identical(other.metadata, metadata) || other.metadata == metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(tenders),metadata); + +@override +String toString() { + return 'TenderApprovalsDataWrapper(tenders: $tenders, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class $TenderApprovalsDataWrapperCopyWith<$Res> { + factory $TenderApprovalsDataWrapperCopyWith(TenderApprovalsDataWrapper value, $Res Function(TenderApprovalsDataWrapper) _then) = _$TenderApprovalsDataWrapperCopyWithImpl; +@useResult +$Res call({ + List? tenders, Metadata? metadata +}); + + +$MetadataCopyWith<$Res>? get metadata; + +} +/// @nodoc +class _$TenderApprovalsDataWrapperCopyWithImpl<$Res> + implements $TenderApprovalsDataWrapperCopyWith<$Res> { + _$TenderApprovalsDataWrapperCopyWithImpl(this._self, this._then); + + final TenderApprovalsDataWrapper _self; + final $Res Function(TenderApprovalsDataWrapper) _then; + +/// Create a copy of TenderApprovalsDataWrapper +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? tenders = freezed,Object? metadata = freezed,}) { + return _then(_self.copyWith( +tenders: freezed == tenders ? _self.tenders : tenders // ignore: cast_nullable_to_non_nullable +as List?,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable +as Metadata?, + )); +} +/// Create a copy of TenderApprovalsDataWrapper +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$MetadataCopyWith<$Res>? get metadata { + if (_self.metadata == null) { + return null; + } + + return $MetadataCopyWith<$Res>(_self.metadata!, (value) { + return _then(_self.copyWith(metadata: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [TenderApprovalsDataWrapper]. +extension TenderApprovalsDataWrapperPatterns on TenderApprovalsDataWrapper { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _TenderApprovalsDataWrapper value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _TenderApprovalsDataWrapper() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _TenderApprovalsDataWrapper value) $default,){ +final _that = this; +switch (_that) { +case _TenderApprovalsDataWrapper(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _TenderApprovalsDataWrapper value)? $default,){ +final _that = this; +switch (_that) { +case _TenderApprovalsDataWrapper() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List? tenders, Metadata? metadata)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _TenderApprovalsDataWrapper() when $default != null: +return $default(_that.tenders,_that.metadata);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List? tenders, Metadata? metadata) $default,) {final _that = this; +switch (_that) { +case _TenderApprovalsDataWrapper(): +return $default(_that.tenders,_that.metadata);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List? tenders, Metadata? metadata)? $default,) {final _that = this; +switch (_that) { +case _TenderApprovalsDataWrapper() when $default != null: +return $default(_that.tenders,_that.metadata);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _TenderApprovalsDataWrapper implements TenderApprovalsDataWrapper { + const _TenderApprovalsDataWrapper({required final List? tenders, required this.metadata}): _tenders = tenders; + factory _TenderApprovalsDataWrapper.fromJson(Map json) => _$TenderApprovalsDataWrapperFromJson(json); + + final List? _tenders; +@override List? get tenders { + final value = _tenders; + if (value == null) return null; + if (_tenders is EqualUnmodifiableListView) return _tenders; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +@override final Metadata? metadata; + +/// Create a copy of TenderApprovalsDataWrapper +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$TenderApprovalsDataWrapperCopyWith<_TenderApprovalsDataWrapper> get copyWith => __$TenderApprovalsDataWrapperCopyWithImpl<_TenderApprovalsDataWrapper>(this, _$identity); + +@override +Map toJson() { + return _$TenderApprovalsDataWrapperToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderApprovalsDataWrapper&&const DeepCollectionEquality().equals(other._tenders, _tenders)&&(identical(other.metadata, metadata) || other.metadata == metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_tenders),metadata); + +@override +String toString() { + return 'TenderApprovalsDataWrapper(tenders: $tenders, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class _$TenderApprovalsDataWrapperCopyWith<$Res> implements $TenderApprovalsDataWrapperCopyWith<$Res> { + factory _$TenderApprovalsDataWrapperCopyWith(_TenderApprovalsDataWrapper value, $Res Function(_TenderApprovalsDataWrapper) _then) = __$TenderApprovalsDataWrapperCopyWithImpl; +@override @useResult +$Res call({ + List? tenders, Metadata? metadata +}); + + +@override $MetadataCopyWith<$Res>? get metadata; + +} +/// @nodoc +class __$TenderApprovalsDataWrapperCopyWithImpl<$Res> + implements _$TenderApprovalsDataWrapperCopyWith<$Res> { + __$TenderApprovalsDataWrapperCopyWithImpl(this._self, this._then); + + final _TenderApprovalsDataWrapper _self; + final $Res Function(_TenderApprovalsDataWrapper) _then; + +/// Create a copy of TenderApprovalsDataWrapper +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? tenders = freezed,Object? metadata = freezed,}) { + return _then(_TenderApprovalsDataWrapper( +tenders: freezed == tenders ? _self._tenders : tenders // ignore: cast_nullable_to_non_nullable +as List?,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable +as Metadata?, + )); +} + +/// Create a copy of TenderApprovalsDataWrapper +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$MetadataCopyWith<$Res>? get metadata { + if (_self.metadata == null) { + return null; + } + + return $MetadataCopyWith<$Res>(_self.metadata!, (value) { + return _then(_self.copyWith(metadata: value)); + }); +} +} + + +/// @nodoc +mixin _$Metadata { + + int? get total; int? get limit; int? get offset; int? get page; int? get pages; +/// Create a copy of Metadata +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$MetadataCopyWith get copyWith => _$MetadataCopyWithImpl(this as Metadata, _$identity); + + /// Serializes this Metadata to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is Metadata&&(identical(other.total, total) || other.total == total)&&(identical(other.limit, limit) || other.limit == limit)&&(identical(other.offset, offset) || other.offset == offset)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,limit,offset,page,pages); + +@override +String toString() { + return 'Metadata(total: $total, limit: $limit, offset: $offset, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class $MetadataCopyWith<$Res> { + factory $MetadataCopyWith(Metadata value, $Res Function(Metadata) _then) = _$MetadataCopyWithImpl; +@useResult +$Res call({ + int? total, int? limit, int? offset, int? page, int? pages +}); + + + + +} +/// @nodoc +class _$MetadataCopyWithImpl<$Res> + implements $MetadataCopyWith<$Res> { + _$MetadataCopyWithImpl(this._self, this._then); + + final Metadata _self; + final $Res Function(Metadata) _then; + +/// Create a copy of Metadata +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? total = freezed,Object? limit = freezed,Object? offset = freezed,Object? page = freezed,Object? pages = freezed,}) { + return _then(_self.copyWith( +total: freezed == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int?,limit: freezed == limit ? _self.limit : limit // ignore: cast_nullable_to_non_nullable +as int?,offset: freezed == offset ? _self.offset : offset // ignore: cast_nullable_to_non_nullable +as int?,page: freezed == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int?,pages: freezed == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [Metadata]. +extension MetadataPatterns on Metadata { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _Metadata value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _Metadata() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _Metadata value) $default,){ +final _that = this; +switch (_that) { +case _Metadata(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _Metadata value)? $default,){ +final _that = this; +switch (_that) { +case _Metadata() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int? total, int? limit, int? offset, int? page, int? pages)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _Metadata() when $default != null: +return $default(_that.total,_that.limit,_that.offset,_that.page,_that.pages);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int? total, int? limit, int? offset, int? page, int? pages) $default,) {final _that = this; +switch (_that) { +case _Metadata(): +return $default(_that.total,_that.limit,_that.offset,_that.page,_that.pages);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int? total, int? limit, int? offset, int? page, int? pages)? $default,) {final _that = this; +switch (_that) { +case _Metadata() when $default != null: +return $default(_that.total,_that.limit,_that.offset,_that.page,_that.pages);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _Metadata implements Metadata { + const _Metadata({required this.total, required this.limit, required this.offset, required this.page, required this.pages}); + factory _Metadata.fromJson(Map json) => _$MetadataFromJson(json); + +@override final int? total; +@override final int? limit; +@override final int? offset; +@override final int? page; +@override final int? pages; + +/// Create a copy of Metadata +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$MetadataCopyWith<_Metadata> get copyWith => __$MetadataCopyWithImpl<_Metadata>(this, _$identity); + +@override +Map toJson() { + return _$MetadataToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Metadata&&(identical(other.total, total) || other.total == total)&&(identical(other.limit, limit) || other.limit == limit)&&(identical(other.offset, offset) || other.offset == offset)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,limit,offset,page,pages); + +@override +String toString() { + return 'Metadata(total: $total, limit: $limit, offset: $offset, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class _$MetadataCopyWith<$Res> implements $MetadataCopyWith<$Res> { + factory _$MetadataCopyWith(_Metadata value, $Res Function(_Metadata) _then) = __$MetadataCopyWithImpl; +@override @useResult +$Res call({ + int? total, int? limit, int? offset, int? page, int? pages +}); + + + + +} +/// @nodoc +class __$MetadataCopyWithImpl<$Res> + implements _$MetadataCopyWith<$Res> { + __$MetadataCopyWithImpl(this._self, this._then); + + final _Metadata _self; + final $Res Function(_Metadata) _then; + +/// Create a copy of Metadata +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? total = freezed,Object? limit = freezed,Object? offset = freezed,Object? page = freezed,Object? pages = freezed,}) { + return _then(_Metadata( +total: freezed == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int?,limit: freezed == limit ? _self.limit : limit // ignore: cast_nullable_to_non_nullable +as int?,offset: freezed == offset ? _self.offset : offset // ignore: cast_nullable_to_non_nullable +as int?,page: freezed == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int?,pages: freezed == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + + +} + +// dart format on diff --git a/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.g.dart b/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.g.dart new file mode 100644 index 0000000..8ccc748 --- /dev/null +++ b/lib/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.g.dart @@ -0,0 +1,43 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'tender_approvals_data_wrapper.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_TenderApprovalsDataWrapper _$TenderApprovalsDataWrapperFromJson( + Map json, +) => _TenderApprovalsDataWrapper( + tenders: + (json['tenders'] as List?) + ?.map((e) => TenderApprovalsData.fromJson(e as Map)) + .toList(), + metadata: + json['metadata'] == null + ? null + : Metadata.fromJson(json['metadata'] as Map), +); + +Map _$TenderApprovalsDataWrapperToJson( + _TenderApprovalsDataWrapper instance, +) => { + 'tenders': instance.tenders, + 'metadata': instance.metadata, +}; + +_Metadata _$MetadataFromJson(Map json) => _Metadata( + total: (json['total'] as num?)?.toInt(), + limit: (json['limit'] as num?)?.toInt(), + offset: (json['offset'] as num?)?.toInt(), + page: (json['page'] as num?)?.toInt(), + pages: (json['pages'] as num?)?.toInt(), +); + +Map _$MetadataToJson(_Metadata instance) => { + 'total': instance.total, + 'limit': instance.limit, + 'offset': instance.offset, + 'page': instance.page, + 'pages': instance.pages, +}; diff --git a/lib/data/services/model/tender_approvals_response/tender_approvals_response.dart b/lib/data/services/model/tender_approvals_response/tender_approvals_response.dart index 954ee3d..348388d 100644 --- a/lib/data/services/model/tender_approvals_response/tender_approvals_response.dart +++ b/lib/data/services/model/tender_approvals_response/tender_approvals_response.dart @@ -1,7 +1,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:tm_app/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.dart'; import '../error/error_model.dart'; -import '../tender_approvals_data/tender_approvals_data.dart'; part 'tender_approvals_response.freezed.dart'; part 'tender_approvals_response.g.dart'; @@ -11,7 +11,7 @@ abstract class TenderApprovalsResponse with _$TenderApprovalsResponse { const factory TenderApprovalsResponse({ required bool? success, required ErrorModel? error, - required List? data, + required TenderApprovalsDataWrapper? data, }) = _TenderApprovalsResponse; factory TenderApprovalsResponse.fromJson(Map json) => diff --git a/lib/data/services/model/tender_approvals_response/tender_approvals_response.freezed.dart b/lib/data/services/model/tender_approvals_response/tender_approvals_response.freezed.dart index e940f27..c10bb4e 100644 --- a/lib/data/services/model/tender_approvals_response/tender_approvals_response.freezed.dart +++ b/lib/data/services/model/tender_approvals_response/tender_approvals_response.freezed.dart @@ -15,7 +15,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$TenderApprovalsResponse { - bool? get success; ErrorModel? get error; List? get data; + bool? get success; ErrorModel? get error; TenderApprovalsDataWrapper? get data; /// Create a copy of TenderApprovalsResponse /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -28,12 +28,12 @@ $TenderApprovalsResponseCopyWith get copyWith => _$Tend @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderApprovalsResponse&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other.data, data)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderApprovalsResponse&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&(identical(other.data, data) || other.data == data)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,success,error,const DeepCollectionEquality().hash(data)); +int get hashCode => Object.hash(runtimeType,success,error,data); @override String toString() { @@ -48,11 +48,11 @@ abstract mixin class $TenderApprovalsResponseCopyWith<$Res> { factory $TenderApprovalsResponseCopyWith(TenderApprovalsResponse value, $Res Function(TenderApprovalsResponse) _then) = _$TenderApprovalsResponseCopyWithImpl; @useResult $Res call({ - bool? success, ErrorModel? error, List? data + bool? success, ErrorModel? error, TenderApprovalsDataWrapper? data }); -$ErrorModelCopyWith<$Res>? get error; +$ErrorModelCopyWith<$Res>? get error;$TenderApprovalsDataWrapperCopyWith<$Res>? get data; } /// @nodoc @@ -70,7 +70,7 @@ class _$TenderApprovalsResponseCopyWithImpl<$Res> success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable as ErrorModel?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable -as List?, +as TenderApprovalsDataWrapper?, )); } /// Create a copy of TenderApprovalsResponse @@ -85,6 +85,18 @@ $ErrorModelCopyWith<$Res>? get error { return $ErrorModelCopyWith<$Res>(_self.error!, (value) { return _then(_self.copyWith(error: value)); }); +}/// Create a copy of TenderApprovalsResponse +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$TenderApprovalsDataWrapperCopyWith<$Res>? get data { + if (_self.data == null) { + return null; + } + + return $TenderApprovalsDataWrapperCopyWith<$Res>(_self.data!, (value) { + return _then(_self.copyWith(data: value)); + }); } } @@ -167,7 +179,7 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( bool? success, ErrorModel? error, List? data)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( bool? success, ErrorModel? error, TenderApprovalsDataWrapper? data)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _TenderApprovalsResponse() when $default != null: return $default(_that.success,_that.error,_that.data);case _: @@ -188,7 +200,7 @@ return $default(_that.success,_that.error,_that.data);case _: /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( bool? success, ErrorModel? error, List? data) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( bool? success, ErrorModel? error, TenderApprovalsDataWrapper? data) $default,) {final _that = this; switch (_that) { case _TenderApprovalsResponse(): return $default(_that.success,_that.error,_that.data);case _: @@ -208,7 +220,7 @@ return $default(_that.success,_that.error,_that.data);case _: /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool? success, ErrorModel? error, List? data)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool? success, ErrorModel? error, TenderApprovalsDataWrapper? data)? $default,) {final _that = this; switch (_that) { case _TenderApprovalsResponse() when $default != null: return $default(_that.success,_that.error,_that.data);case _: @@ -223,20 +235,12 @@ return $default(_that.success,_that.error,_that.data);case _: @JsonSerializable() class _TenderApprovalsResponse implements TenderApprovalsResponse { - const _TenderApprovalsResponse({required this.success, required this.error, required final List? data}): _data = data; + const _TenderApprovalsResponse({required this.success, required this.error, required this.data}); factory _TenderApprovalsResponse.fromJson(Map json) => _$TenderApprovalsResponseFromJson(json); @override final bool? success; @override final ErrorModel? error; - final List? _data; -@override List? get data { - final value = _data; - if (value == null) return null; - if (_data is EqualUnmodifiableListView) return _data; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(value); -} - +@override final TenderApprovalsDataWrapper? data; /// Create a copy of TenderApprovalsResponse /// with the given fields replaced by the non-null parameter values. @@ -251,12 +255,12 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderApprovalsResponse&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other._data, _data)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderApprovalsResponse&&(identical(other.success, success) || other.success == success)&&(identical(other.error, error) || other.error == error)&&(identical(other.data, data) || other.data == data)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,success,error,const DeepCollectionEquality().hash(_data)); +int get hashCode => Object.hash(runtimeType,success,error,data); @override String toString() { @@ -271,11 +275,11 @@ abstract mixin class _$TenderApprovalsResponseCopyWith<$Res> implements $TenderA factory _$TenderApprovalsResponseCopyWith(_TenderApprovalsResponse value, $Res Function(_TenderApprovalsResponse) _then) = __$TenderApprovalsResponseCopyWithImpl; @override @useResult $Res call({ - bool? success, ErrorModel? error, List? data + bool? success, ErrorModel? error, TenderApprovalsDataWrapper? data }); -@override $ErrorModelCopyWith<$Res>? get error; +@override $ErrorModelCopyWith<$Res>? get error;@override $TenderApprovalsDataWrapperCopyWith<$Res>? get data; } /// @nodoc @@ -292,8 +296,8 @@ class __$TenderApprovalsResponseCopyWithImpl<$Res> return _then(_TenderApprovalsResponse( success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable as bool?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable -as ErrorModel?,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable -as List?, +as ErrorModel?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable +as TenderApprovalsDataWrapper?, )); } @@ -309,6 +313,18 @@ $ErrorModelCopyWith<$Res>? get error { return $ErrorModelCopyWith<$Res>(_self.error!, (value) { return _then(_self.copyWith(error: value)); }); +}/// Create a copy of TenderApprovalsResponse +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$TenderApprovalsDataWrapperCopyWith<$Res>? get data { + if (_self.data == null) { + return null; + } + + return $TenderApprovalsDataWrapperCopyWith<$Res>(_self.data!, (value) { + return _then(_self.copyWith(data: value)); + }); } } diff --git a/lib/data/services/model/tender_approvals_response/tender_approvals_response.g.dart b/lib/data/services/model/tender_approvals_response/tender_approvals_response.g.dart index d3d96ae..1d43b8e 100644 --- a/lib/data/services/model/tender_approvals_response/tender_approvals_response.g.dart +++ b/lib/data/services/model/tender_approvals_response/tender_approvals_response.g.dart @@ -15,9 +15,11 @@ _TenderApprovalsResponse _$TenderApprovalsResponseFromJson( ? null : ErrorModel.fromJson(json['error'] as Map), data: - (json['data'] as List?) - ?.map((e) => TenderApprovalsData.fromJson(e as Map)) - .toList(), + json['data'] == null + ? null + : TenderApprovalsDataWrapper.fromJson( + json['data'] as Map, + ), ); Map _$TenderApprovalsResponseToJson( diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart index 327433a..107333f 100644 --- a/lib/gen/assets.gen.dart +++ b/lib/gen/assets.gen.dart @@ -35,6 +35,9 @@ class $AssetsIconsGen { /// File path: assets/icons/arrow-right.svg String get arrowRight => 'assets/icons/arrow-right.svg'; + /// File path: assets/icons/arrow_down_small.svg + String get arrowDownSmall => 'assets/icons/arrow_down_small.svg'; + /// File path: assets/icons/arrows.svg String get arrows => 'assets/icons/arrows.svg'; @@ -129,6 +132,7 @@ class $AssetsIconsGen { arrowLeftSmall, arrowRightSmall, arrowRight, + arrowDownSmall, arrows, calendar, closeCircle, @@ -163,6 +167,9 @@ class $AssetsIconsGen { class $AssetsPngsGen { const $AssetsPngsGen(); + /// File path: assets/pngs/app_logo.png + AssetGenImage get appLogo => const AssetGenImage('assets/pngs/app_logo.png'); + /// File path: assets/pngs/forgot_password.png AssetGenImage get forgotPassword => const AssetGenImage('assets/pngs/forgot_password.png'); @@ -175,7 +182,12 @@ class $AssetsPngsGen { const AssetGenImage('assets/pngs/web_login_image.png'); /// List of all assets - List get values => [forgotPassword, logo, webLoginImage]; + List get values => [ + appLogo, + forgotPassword, + logo, + webLoginImage, + ]; } class $AssetsSvgsGen { diff --git a/lib/view_models/home_view_model.dart b/lib/view_models/home_view_model.dart index 0eba9d9..211c52c 100644 --- a/lib/view_models/home_view_model.dart +++ b/lib/view_models/home_view_model.dart @@ -14,7 +14,7 @@ class HomeViewModel with ChangeNotifier { final HomeRepository _homeRepository; HomeViewModel({required HomeRepository homeRepository}) - : _homeRepository = homeRepository { + : _homeRepository = homeRepository { init(); } @@ -36,7 +36,6 @@ class HomeViewModel with ChangeNotifier { bool _isLoadingMore = false; bool _hasMore = true; - /// آیا الان در حالت Recommended هستیم یا YourTenders bool _isRecommendedMode = false; List get tenders => _tenders; @@ -46,11 +45,11 @@ class HomeViewModel with ChangeNotifier { void init() async { await getApprovedStates(); - await getYourTenders(); + await getYourTenders(reset: true); await getFeedbackStats(); } - Future getHomeRecommandTenders({bool reset = false}) async { + Future getHomeRecommendTenders({bool reset = false}) async { if (_isLoadingMore || (!_hasMore && !reset)) { return; } @@ -63,7 +62,7 @@ class HomeViewModel with ChangeNotifier { _isLoadingMore = true; _errorMessage = null; - _isRecommendedMode = true; // ✅ اینجا یعنی در حالت Recommended هستیم + _isRecommendedMode = true; notifyListeners(); final result = await _homeRepository.getHomeRecommendedTenders( @@ -94,38 +93,58 @@ class HomeViewModel with ChangeNotifier { notifyListeners(); } - Future getYourTenders() async { - _isLoading = true; - _isRecommendedMode = false; // ✅ وقتی YourTenders میاد → بدون pagination - notifyListeners(); - - final result = await _homeRepository.getYourTenders(); - - switch (result) { - case Ok(): - data = result.value; - _errorMessage = null; - - if (data?.data?.isEmpty ?? true) { - // اگه YourTenders خالی بود → برو سمت Recommended - await getHomeRecommandTenders(reset: true); - } else { - _tenders.clear(); - _tenders.addAll( - data!.data!.map((e) => e.tender).whereType(), - ); - } - - case Error(): - _errorMessage = result.error.toString(); - await getHomeRecommandTenders(reset: true); - break; - } - - _isLoading = false; - notifyListeners(); +Future getYourTenders({bool reset = false}) async { + if (_isLoadingMore || (!_hasMore && !reset)) { + return; } + if (reset) { + _currentPage = 0; + _hasMore = true; + _tenders.clear(); + } + + _isLoadingMore = true; + _errorMessage = null; + _isRecommendedMode = false; + notifyListeners(); + + final result = await _homeRepository.getYourTenders( + limit: _pageSize, + offset: _currentPage * _pageSize, + ); + + switch (result) { + case Ok(): + data = result.value; + + final tendersList = data?.data?.tenders ?? []; + final metadata = data?.data?.metadata; + + if (tendersList.isNotEmpty) { + _tenders.addAll( + tendersList.map((e) => e.tender).whereType(), + ); + _currentPage++; + + if (metadata != null && (_currentPage >= metadata.pages!)) { + _hasMore = false; + } + } else { + _hasMore = false; + } + break; + + case Error(): + _errorMessage = result.error.toString(); + break; + } + + _isLoadingMore = false; + notifyListeners(); +} + + Future getApprovedStates() async { _isLoading = true; _errorMessage = null; @@ -166,7 +185,6 @@ class HomeViewModel with ChangeNotifier { notifyListeners(); } - // Calculation methods for progress bars double get partnershipCount { return tenderApprovalsStateResponse?.data?.partnershipCount?.toDouble() ?? 0.0; diff --git a/lib/views/home/pages/d_home_page.dart b/lib/views/home/pages/d_home_page.dart index b9b684f..880c229 100644 --- a/lib/views/home/pages/d_home_page.dart +++ b/lib/views/home/pages/d_home_page.dart @@ -169,7 +169,8 @@ class DesktopHomePage extends StatelessWidget { } Widget _yourTenderText(HomeViewModel homeViewModel) { - final isYourTenders = homeViewModel.data?.data?.isNotEmpty ?? false; + final isYourTenders = + homeViewModel.data?.data?.tenders!.isNotEmpty ?? false; return ConstrainedBox( constraints: BoxConstraints(maxWidth: 740), child: Align( @@ -190,16 +191,23 @@ class DesktopHomePage extends StatelessWidget { Widget _bottomListView(HomeViewModel homeViewModel) { final controller = ScrollController(); - controller.addListener(() { - if (homeViewModel.isRecommendedMode) { - if (controller.position.pixels >= - controller.position.maxScrollExtent - 200) { - if (!homeViewModel.isLoadingMore && homeViewModel.hasMore) { - homeViewModel.getHomeRecommandTenders(); - } + if (!homeViewModel.isRecommendedMode) { + // YourTenders + if (controller.position.pixels >= + controller.position.maxScrollExtent - 200) { + if (!homeViewModel.isLoadingMore && homeViewModel.hasMore) { + homeViewModel.getYourTenders(); } } - }); + } else { + // Recommended + if (controller.position.pixels >= + controller.position.maxScrollExtent - 200) { + if (!homeViewModel.isLoadingMore && homeViewModel.hasMore) { + homeViewModel.getHomeRecommendTenders(); + } + } + } return SizedBox( width: 740, diff --git a/lib/views/home/pages/m_home_page.dart b/lib/views/home/pages/m_home_page.dart index 20aad8e..6755ab5 100644 --- a/lib/views/home/pages/m_home_page.dart +++ b/lib/views/home/pages/m_home_page.dart @@ -163,7 +163,8 @@ class MobileHomePage extends StatelessWidget { } Widget _yourTenderText(HomeViewModel homeViewModel) { - final isYourTenders = homeViewModel.data?.data?.isNotEmpty ?? false; + final isYourTenders = + homeViewModel.data?.data?.tenders!.isNotEmpty ?? false; return Padding( padding: EdgeInsets.symmetric(horizontal: 24.0.w()), child: Text( @@ -183,11 +184,20 @@ class MobileHomePage extends StatelessWidget { final controller = ScrollController(); controller.addListener(() { - if (homeViewModel.isRecommendedMode) { + if (!homeViewModel.isRecommendedMode) { + // YourTenders if (controller.position.pixels >= controller.position.maxScrollExtent - 200) { if (!homeViewModel.isLoadingMore && homeViewModel.hasMore) { - homeViewModel.getHomeRecommandTenders(); + homeViewModel.getYourTenders(); + } + } + } else { + // Recommended + if (controller.position.pixels >= + controller.position.maxScrollExtent - 200) { + if (!homeViewModel.isLoadingMore && homeViewModel.hasMore) { + homeViewModel.getHomeRecommendTenders(); } } } diff --git a/lib/views/home/pages/t_home_page.dart b/lib/views/home/pages/t_home_page.dart index f9e7cd1..eacb216 100644 --- a/lib/views/home/pages/t_home_page.dart +++ b/lib/views/home/pages/t_home_page.dart @@ -195,7 +195,8 @@ class TabletHomePage extends StatelessWidget { } Widget _yourTenderText(HomeViewModel homeViewModel) { - final isYourTenders = homeViewModel.data?.data?.isNotEmpty ?? false; + final isYourTenders = + homeViewModel.data?.data?.tenders!.isNotEmpty ?? false; return Text( isYourTenders ? HomeStrings.yourTenders : HomeStrings.recommendedTenders, style: TextStyle( @@ -209,16 +210,23 @@ class TabletHomePage extends StatelessWidget { Widget _bottomListView(HomeViewModel homeViewModel) { final controller = ScrollController(); - controller.addListener(() { - if (homeViewModel.isRecommendedMode) { - if (controller.position.pixels >= - controller.position.maxScrollExtent - 200) { - if (!homeViewModel.isLoadingMore && homeViewModel.hasMore) { - homeViewModel.getHomeRecommandTenders(); - } + if (!homeViewModel.isRecommendedMode) { + // YourTenders + if (controller.position.pixels >= + controller.position.maxScrollExtent - 200) { + if (!homeViewModel.isLoadingMore && homeViewModel.hasMore) { + homeViewModel.getYourTenders(); } } - }); + } else { + // Recommended + if (controller.position.pixels >= + controller.position.maxScrollExtent - 200) { + if (!homeViewModel.isLoadingMore && homeViewModel.hasMore) { + homeViewModel.getHomeRecommendTenders(); + } + } + } return SizedBox( width: double.infinity, diff --git a/lib/views/your_tenders/widgets/tenders_submitted.dart b/lib/views/your_tenders/widgets/tenders_submitted.dart index f357642..fd1bea8 100644 --- a/lib/views/your_tenders/widgets/tenders_submitted.dart +++ b/lib/views/your_tenders/widgets/tenders_submitted.dart @@ -21,9 +21,9 @@ class TendersSubmitted extends StatelessWidget { ? const Center(child: Text('No submitted projects yet.')) : ListView.builder( padding: const EdgeInsets.only(top: 20), - itemCount: approvedTenders.data!.length, + itemCount: approvedTenders.data!.tenders!.length, itemBuilder: (context, index) { - final tender = approvedTenders.data![index]; + final tender = approvedTenders.data!.tenders![index]; return TenderCard( date: tender.createdAt!.toString(), title: tender.tender!.title!,