added pagination in your tenders and some fixes
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
+2
-15
@@ -1,4 +1,5 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import '../meta/meta.dart';
|
||||
import '../tender_approvals_data/tender_approvals_data.dart';
|
||||
|
||||
part 'tender_approvals_data_wrapper.freezed.dart';
|
||||
@@ -8,23 +9,9 @@ part 'tender_approvals_data_wrapper.g.dart';
|
||||
abstract class TenderApprovalsDataWrapper with _$TenderApprovalsDataWrapper {
|
||||
const factory TenderApprovalsDataWrapper({
|
||||
required List<TenderApprovalsData>? tenders,
|
||||
required Metadata? metadata,
|
||||
required Meta? metadata,
|
||||
}) = _TenderApprovalsDataWrapper;
|
||||
|
||||
factory TenderApprovalsDataWrapper.fromJson(Map<String, Object?> 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<String, Object?> json) =>
|
||||
_$MetadataFromJson(json);
|
||||
}
|
||||
|
||||
+15
-290
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$TenderApprovalsDataWrapper {
|
||||
|
||||
List<TenderApprovalsData>? get tenders; Metadata? get metadata;
|
||||
List<TenderApprovalsData>? get tenders; Meta? get metadata;
|
||||
/// Create a copy of TenderApprovalsDataWrapper
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -48,11 +48,11 @@ abstract mixin class $TenderApprovalsDataWrapperCopyWith<$Res> {
|
||||
factory $TenderApprovalsDataWrapperCopyWith(TenderApprovalsDataWrapper value, $Res Function(TenderApprovalsDataWrapper) _then) = _$TenderApprovalsDataWrapperCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
List<TenderApprovalsData>? tenders, Metadata? metadata
|
||||
List<TenderApprovalsData>? tenders, Meta? metadata
|
||||
});
|
||||
|
||||
|
||||
$MetadataCopyWith<$Res>? get metadata;
|
||||
$MetaCopyWith<$Res>? get metadata;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -69,19 +69,19 @@ class _$TenderApprovalsDataWrapperCopyWithImpl<$Res>
|
||||
return _then(_self.copyWith(
|
||||
tenders: freezed == tenders ? _self.tenders : tenders // ignore: cast_nullable_to_non_nullable
|
||||
as List<TenderApprovalsData>?,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Metadata?,
|
||||
as Meta?,
|
||||
));
|
||||
}
|
||||
/// 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 {
|
||||
$MetaCopyWith<$Res>? get metadata {
|
||||
if (_self.metadata == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $MetadataCopyWith<$Res>(_self.metadata!, (value) {
|
||||
return $MetaCopyWith<$Res>(_self.metadata!, (value) {
|
||||
return _then(_self.copyWith(metadata: value));
|
||||
});
|
||||
}
|
||||
@@ -166,7 +166,7 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<TenderApprovalsData>? tenders, Metadata? metadata)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<TenderApprovalsData>? tenders, Meta? metadata)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TenderApprovalsDataWrapper() when $default != null:
|
||||
return $default(_that.tenders,_that.metadata);case _:
|
||||
@@ -187,7 +187,7 @@ return $default(_that.tenders,_that.metadata);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<TenderApprovalsData>? tenders, Metadata? metadata) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<TenderApprovalsData>? tenders, Meta? metadata) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TenderApprovalsDataWrapper():
|
||||
return $default(_that.tenders,_that.metadata);case _:
|
||||
@@ -207,7 +207,7 @@ return $default(_that.tenders,_that.metadata);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<TenderApprovalsData>? tenders, Metadata? metadata)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<TenderApprovalsData>? tenders, Meta? metadata)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TenderApprovalsDataWrapper() when $default != null:
|
||||
return $default(_that.tenders,_that.metadata);case _:
|
||||
@@ -234,7 +234,7 @@ class _TenderApprovalsDataWrapper implements TenderApprovalsDataWrapper {
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
@override final Metadata? metadata;
|
||||
@override final Meta? metadata;
|
||||
|
||||
/// Create a copy of TenderApprovalsDataWrapper
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -269,11 +269,11 @@ abstract mixin class _$TenderApprovalsDataWrapperCopyWith<$Res> implements $Tend
|
||||
factory _$TenderApprovalsDataWrapperCopyWith(_TenderApprovalsDataWrapper value, $Res Function(_TenderApprovalsDataWrapper) _then) = __$TenderApprovalsDataWrapperCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
List<TenderApprovalsData>? tenders, Metadata? metadata
|
||||
List<TenderApprovalsData>? tenders, Meta? metadata
|
||||
});
|
||||
|
||||
|
||||
@override $MetadataCopyWith<$Res>? get metadata;
|
||||
@override $MetaCopyWith<$Res>? get metadata;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -290,7 +290,7 @@ class __$TenderApprovalsDataWrapperCopyWithImpl<$Res>
|
||||
return _then(_TenderApprovalsDataWrapper(
|
||||
tenders: freezed == tenders ? _self._tenders : tenders // ignore: cast_nullable_to_non_nullable
|
||||
as List<TenderApprovalsData>?,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Metadata?,
|
||||
as Meta?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -298,290 +298,15 @@ as Metadata?,
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$MetadataCopyWith<$Res>? get metadata {
|
||||
$MetaCopyWith<$Res>? get metadata {
|
||||
if (_self.metadata == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $MetadataCopyWith<$Res>(_self.metadata!, (value) {
|
||||
return $MetaCopyWith<$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<Metadata> get copyWith => _$MetadataCopyWithImpl<Metadata>(this as Metadata, _$identity);
|
||||
|
||||
/// Serializes this Metadata to a JSON map.
|
||||
Map<String, dynamic> 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 extends Object?>(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 extends Object?>(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 extends Object?>(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 extends Object?>(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 extends Object?>(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 extends Object?>(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<String, dynamic> 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<String, dynamic> 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
|
||||
|
||||
+1
-17
@@ -16,7 +16,7 @@ _TenderApprovalsDataWrapper _$TenderApprovalsDataWrapperFromJson(
|
||||
metadata:
|
||||
json['metadata'] == null
|
||||
? null
|
||||
: Metadata.fromJson(json['metadata'] as Map<String, dynamic>),
|
||||
: Meta.fromJson(json['metadata'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$TenderApprovalsDataWrapperToJson(
|
||||
@@ -25,19 +25,3 @@ Map<String, dynamic> _$TenderApprovalsDataWrapperToJson(
|
||||
'tenders': instance.tenders,
|
||||
'metadata': instance.metadata,
|
||||
};
|
||||
|
||||
_Metadata _$MetadataFromJson(Map<String, dynamic> 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<String, dynamic> _$MetadataToJson(_Metadata instance) => <String, dynamic>{
|
||||
'total': instance.total,
|
||||
'limit': instance.limit,
|
||||
'offset': instance.offset,
|
||||
'page': instance.page,
|
||||
'pages': instance.pages,
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ class HomeViewModel with ChangeNotifier {
|
||||
final HomeRepository _homeRepository;
|
||||
|
||||
HomeViewModel({required HomeRepository homeRepository})
|
||||
: _homeRepository = homeRepository {
|
||||
: _homeRepository = homeRepository {
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class HomeViewModel with ChangeNotifier {
|
||||
TenderApprovalsStateResponse? tenderApprovalsStateResponse;
|
||||
FeedbackStats? feedbackStats;
|
||||
final List<TenderData> _tenders = [];
|
||||
final int _pageSize = 20;
|
||||
final int _pageSize = 10;
|
||||
int _currentPage = 0;
|
||||
bool _isLoadingMore = false;
|
||||
bool _hasMore = true;
|
||||
@@ -44,9 +44,15 @@ class HomeViewModel with ChangeNotifier {
|
||||
bool get isRecommendedMode => _isRecommendedMode;
|
||||
|
||||
void init() async {
|
||||
_isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
await getApprovedStates();
|
||||
await getYourTenders(reset: true);
|
||||
await getFeedbackStats();
|
||||
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> getHomeRecommendTenders({bool reset = false}) async {
|
||||
@@ -93,62 +99,59 @@ class HomeViewModel with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> getYourTenders({bool reset = false}) async {
|
||||
if (_isLoadingMore || (!_hasMore && !reset)) {
|
||||
return;
|
||||
}
|
||||
Future<void> getYourTenders({bool reset = false}) async {
|
||||
if (_isLoadingMore || (!_hasMore && !reset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
_currentPage = 0;
|
||||
_hasMore = true;
|
||||
_tenders.clear();
|
||||
}
|
||||
if (reset) {
|
||||
_currentPage = 0;
|
||||
_hasMore = true;
|
||||
_tenders.clear();
|
||||
}
|
||||
|
||||
_isLoadingMore = true;
|
||||
_errorMessage = null;
|
||||
_isRecommendedMode = false;
|
||||
notifyListeners();
|
||||
_isLoadingMore = true;
|
||||
_errorMessage = null;
|
||||
_isRecommendedMode = false;
|
||||
notifyListeners();
|
||||
|
||||
final result = await _homeRepository.getYourTenders(
|
||||
limit: _pageSize,
|
||||
offset: _currentPage * _pageSize,
|
||||
);
|
||||
final result = await _homeRepository.getYourTenders(
|
||||
limit: _pageSize,
|
||||
offset: _currentPage * _pageSize,
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<TenderApprovalsResponse>():
|
||||
data = result.value;
|
||||
switch (result) {
|
||||
case Ok<TenderApprovalsResponse>():
|
||||
data = result.value;
|
||||
|
||||
final tendersList = data?.data?.tenders ?? [];
|
||||
final metadata = data?.data?.metadata;
|
||||
final tendersList = data?.data?.tenders ?? [];
|
||||
final metadata = data?.data?.metadata;
|
||||
|
||||
if (tendersList.isNotEmpty) {
|
||||
_tenders.addAll(
|
||||
tendersList.map((e) => e.tender).whereType<TenderData>(),
|
||||
);
|
||||
_currentPage++;
|
||||
if (tendersList.isNotEmpty) {
|
||||
_tenders.addAll(
|
||||
tendersList.map((e) => e.tender).whereType<TenderData>(),
|
||||
);
|
||||
_currentPage++;
|
||||
|
||||
if (metadata != null && (_currentPage >= metadata.pages!)) {
|
||||
if (metadata != null && (_currentPage >= metadata.pages!)) {
|
||||
_hasMore = false;
|
||||
}
|
||||
} else {
|
||||
_hasMore = false;
|
||||
}
|
||||
} else {
|
||||
_hasMore = false;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case Error<TenderApprovalsResponse>():
|
||||
_errorMessage = result.error.toString();
|
||||
break;
|
||||
case Error<TenderApprovalsResponse>():
|
||||
_errorMessage = result.error.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
_isLoadingMore = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
_isLoadingMore = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
Future<void> getApprovedStates() async {
|
||||
_isLoading = true;
|
||||
_errorMessage = null;
|
||||
notifyListeners();
|
||||
|
||||
final result = await _homeRepository.getTendersApprovalsState();
|
||||
|
||||
@@ -160,15 +163,10 @@ Future<void> getYourTenders({bool reset = false}) async {
|
||||
_errorMessage = result.error.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> getFeedbackStats() async {
|
||||
_isLoading = true;
|
||||
_errorMessage = null;
|
||||
notifyListeners();
|
||||
|
||||
final result = await _homeRepository.getFeedbackStats();
|
||||
|
||||
@@ -180,9 +178,6 @@ Future<void> getYourTenders({bool reset = false}) async {
|
||||
_errorMessage = result.error.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
double get partnershipCount {
|
||||
|
||||
@@ -20,6 +20,12 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
int _offset = 0;
|
||||
final int _limit = 10;
|
||||
String? _currentFeedbackType;
|
||||
|
||||
// Pagination state for tenders
|
||||
bool isLoadingMoreTenders = false;
|
||||
bool hasMoreTenders = true;
|
||||
int _tendersOffset = 0;
|
||||
final int _tendersLimit = 10;
|
||||
// Filter States
|
||||
DateTimeRange? selectedDateRange;
|
||||
String selectedStatus = 'All';
|
||||
@@ -48,20 +54,53 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
Future<void> getApprovedTenders({
|
||||
required int limit,
|
||||
required int offset,
|
||||
bool reset = false,
|
||||
}) async {
|
||||
isLoading = true;
|
||||
if (!reset && (isLoadingMoreTenders || !hasMoreTenders)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
_tendersOffset = 0;
|
||||
hasMoreTenders = true;
|
||||
data = null;
|
||||
}
|
||||
|
||||
if (_tendersOffset == 0) {
|
||||
isLoading = true;
|
||||
} else {
|
||||
isLoadingMoreTenders = true;
|
||||
}
|
||||
notifyListeners();
|
||||
|
||||
final result = await yourTendersRepository.getApprovedTenders(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
limit: _tendersLimit,
|
||||
offset: _tendersOffset,
|
||||
createdFrom: startDateUnix,
|
||||
createdTo: endDateUnix,
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<TenderApprovalsResponse>():
|
||||
data = result.value;
|
||||
final incoming = result.value;
|
||||
final incomingList = incoming.data?.tenders ?? [];
|
||||
|
||||
if (reset || data == null) {
|
||||
data = incoming;
|
||||
} else {
|
||||
final existingList = data!.data?.tenders ?? [];
|
||||
final combined = List.of(existingList)..addAll(incomingList);
|
||||
final newMetadata = incoming.data?.metadata ?? data!.data?.metadata;
|
||||
data = data!.copyWith(
|
||||
data: data!.data!.copyWith(
|
||||
tenders: combined,
|
||||
metadata: newMetadata,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
hasMoreTenders = incomingList.length == _tendersLimit;
|
||||
_tendersOffset += _tendersLimit;
|
||||
errorMessage = null;
|
||||
break;
|
||||
case Error<TenderApprovalsResponse>():
|
||||
@@ -70,6 +109,7 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
isLoadingMoreTenders = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -78,19 +118,53 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
required int offset,
|
||||
required String createdFrom,
|
||||
required String createdTo,
|
||||
bool reset = false,
|
||||
}) async {
|
||||
isLoading = true;
|
||||
if (!reset && (isLoadingMoreTenders || !hasMoreTenders)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
_tendersOffset = 0;
|
||||
hasMoreTenders = true;
|
||||
data = null;
|
||||
}
|
||||
|
||||
if (_tendersOffset == 0) {
|
||||
isLoading = true;
|
||||
} else {
|
||||
isLoadingMoreTenders = true;
|
||||
}
|
||||
notifyListeners();
|
||||
|
||||
final result = await yourTendersRepository.getTenders(
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
limit: _tendersLimit,
|
||||
offset: _tendersOffset,
|
||||
createdFrom: createdFrom,
|
||||
createdTo: createdTo,
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<TenderApprovalsResponse>():
|
||||
data = result.value;
|
||||
final incoming = result.value;
|
||||
final incomingList = incoming.data?.tenders ?? [];
|
||||
|
||||
if (reset || data == null) {
|
||||
data = incoming;
|
||||
} else {
|
||||
final existingList = data!.data?.tenders ?? [];
|
||||
final combined = List.of(existingList)..addAll(incomingList);
|
||||
final newMetadata = incoming.data?.metadata ?? data!.data?.metadata;
|
||||
data = data!.copyWith(
|
||||
data: data!.data!.copyWith(
|
||||
tenders: combined,
|
||||
metadata: newMetadata,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
hasMoreTenders = incomingList.length == _tendersLimit;
|
||||
_tendersOffset += _tendersLimit;
|
||||
errorMessage = null;
|
||||
break;
|
||||
case Error<TenderApprovalsResponse>():
|
||||
@@ -99,6 +173,7 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
isLoadingMoreTenders = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -171,6 +246,28 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
await getTendersFeedback(feedbackType: _currentFeedbackType!, reset: false);
|
||||
}
|
||||
|
||||
Future<void> loadMoreTenders() async {
|
||||
if (isLoadingMoreTenders || !hasMoreTenders) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedStatus == YourTendersStrings.all) {
|
||||
await getTenders(
|
||||
limit: _tendersLimit,
|
||||
offset: _tendersOffset,
|
||||
createdFrom: startDateUnix,
|
||||
createdTo: endDateUnix,
|
||||
reset: false,
|
||||
);
|
||||
} else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
|
||||
await getApprovedTenders(
|
||||
limit: _tendersLimit,
|
||||
offset: _tendersOffset,
|
||||
reset: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Filter Actions ---
|
||||
void setDateRange(DateTimeRange? range) {
|
||||
selectedDateRange = range;
|
||||
@@ -191,13 +288,14 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
Future<void> callWithFilter() async {
|
||||
if (selectedStatus == YourTendersStrings.all) {
|
||||
await getTenders(
|
||||
limit: 10,
|
||||
limit: _tendersLimit,
|
||||
offset: 0,
|
||||
createdFrom: startDateUnix,
|
||||
createdTo: endDateUnix,
|
||||
reset: true,
|
||||
);
|
||||
} else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
|
||||
await getApprovedTenders(limit: 10, offset: 0);
|
||||
await getApprovedTenders(limit: _tendersLimit, offset: 0, reset: true);
|
||||
} else if (selectedStatus == YourTendersStrings.likeTenders) {
|
||||
await getTendersFeedback(feedbackType: 'like', reset: true);
|
||||
} else if (selectedStatus == YourTendersStrings.dislikeTenders) {
|
||||
|
||||
@@ -53,7 +53,7 @@ class LikedListItem extends StatelessWidget {
|
||||
vertical: 5.0.h(),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primary30,
|
||||
color: AppColors.primary20,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Row(
|
||||
@@ -100,7 +100,7 @@ class LikedListItem extends StatelessWidget {
|
||||
vertical: 5.0.h(),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primary30,
|
||||
color: AppColors.primary20,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Row(
|
||||
|
||||
@@ -42,7 +42,10 @@ class _YourTendersMobilePageState extends State<YourTendersMobilePage> {
|
||||
Expanded(
|
||||
child: Consumer<YourTendersViewModel>(
|
||||
builder: (context, viewModel, child) {
|
||||
if (viewModel.isLoading) {
|
||||
if (viewModel.isLoading &&
|
||||
(viewModel.data?.data?.tenders ?? []).isEmpty &&
|
||||
(viewModel.likedTendersData?.data?.feedback ?? [])
|
||||
.isEmpty) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: AppColors.secondary50,
|
||||
|
||||
@@ -48,10 +48,10 @@ class FilterButton extends StatelessWidget {
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.shade50,
|
||||
color: AppColors.primary20,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: const Center(
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -60,7 +60,7 @@ class FilterButton extends StatelessWidget {
|
||||
Text(
|
||||
YourTendersStrings.filter,
|
||||
style: TextStyle(
|
||||
color: Colors.blue,
|
||||
color: AppColors.textBlue,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -165,8 +165,8 @@ class TendersFilterDialog extends StatelessWidget {
|
||||
vm.callWithFilter();
|
||||
},
|
||||
text: YourTendersStrings.confirm,
|
||||
textColor: AppColors.mainBlue,
|
||||
backgroundColor: AppColors.primary30,
|
||||
textColor: AppColors.textBlue,
|
||||
backgroundColor: AppColors.primary20,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/constants/assets.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/your_tenders_view_model.dart';
|
||||
import 'package:tm_app/views/your_tenders/widgets/tender_card.dart';
|
||||
|
||||
import '../../../data/services/model/tender_approvals_response/tender_approvals_response.dart';
|
||||
|
||||
class TendersSubmitted extends StatelessWidget {
|
||||
class TendersSubmitted extends StatefulWidget {
|
||||
const TendersSubmitted({
|
||||
required this.approvedTenders,
|
||||
required this.isDesktop,
|
||||
@@ -15,57 +18,124 @@ class TendersSubmitted extends StatelessWidget {
|
||||
final TenderApprovalsResponse approvedTenders;
|
||||
final bool isDesktop;
|
||||
|
||||
@override
|
||||
State<TendersSubmitted> createState() => _TendersSubmittedState();
|
||||
}
|
||||
|
||||
class _TendersSubmittedState extends State<TendersSubmitted> {
|
||||
late final ScrollController _scrollController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_scrollController = ScrollController()..addListener(_onScroll);
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
if (!_scrollController.hasClients) {
|
||||
return;
|
||||
}
|
||||
final max = _scrollController.position.maxScrollExtent;
|
||||
final pos = _scrollController.position.pixels;
|
||||
const threshold = 200.0;
|
||||
if (max - pos <= threshold) {
|
||||
final vm = Provider.of<YourTendersViewModel>(context, listen: false);
|
||||
vm.loadMoreTenders();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.removeListener(_onScroll);
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return approvedTenders.data == null
|
||||
? const Center(child: Text('No submitted projects yet.'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
itemCount: approvedTenders.data!.tenders!.length,
|
||||
return Consumer<YourTendersViewModel>(
|
||||
builder: (context, viewModel, child) {
|
||||
if (widget.approvedTenders.data == null) {
|
||||
return const Center(child: Text('No submitted projects yet.'));
|
||||
}
|
||||
|
||||
final tenders = widget.approvedTenders.data!.tenders ?? [];
|
||||
if (tenders.isEmpty) {
|
||||
return const Center(child: Text('No submitted projects yet.'));
|
||||
}
|
||||
|
||||
final itemCount =
|
||||
tenders.length + (viewModel.isLoadingMoreTenders ? 1 : 0);
|
||||
|
||||
return ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: EdgeInsets.symmetric(
|
||||
// horizontal: 24.0.w(),
|
||||
vertical: 15.0.h(),
|
||||
),
|
||||
itemCount: itemCount,
|
||||
itemBuilder: (context, index) {
|
||||
final tender = approvedTenders.data!.tenders![index];
|
||||
return TenderCard(
|
||||
date: tender.createdAt!.toString(),
|
||||
title: tender.tender!.title!,
|
||||
description: tender.tender!.description!,
|
||||
location: tender.tender!.countryCode!,
|
||||
countryFlag: AssetsManager.seFlag,
|
||||
status: tender.status,
|
||||
countryCode: tender.tender!.countryCode!,
|
||||
projectStatus: tender.tender!.status!,
|
||||
isDesktop: isDesktop,
|
||||
backgroundColor:
|
||||
tender.status == 'Won'
|
||||
? AppColors.green0
|
||||
: tender.status == 'submitted'
|
||||
? AppColors.grey0
|
||||
: AppColors.red0.withValues(alpha: 0.2),
|
||||
borderColor:
|
||||
tender.status == 'Won'
|
||||
? AppColors.green10
|
||||
: tender.status == 'submitted'
|
||||
? AppColors.grey30
|
||||
: AppColors.red0,
|
||||
statusIcon:
|
||||
tender.status == 'Won'
|
||||
? AssetsManager.tickCircle
|
||||
: tender.status == 'submitted'
|
||||
? null
|
||||
: AssetsManager.closeCircle,
|
||||
statusCardColor:
|
||||
tender.status == 'Won'
|
||||
? AppColors.green20
|
||||
: tender.status == 'submitted'
|
||||
? AppColors.green20
|
||||
: AppColors.red0,
|
||||
statusTextColor:
|
||||
tender.status == 'Won'
|
||||
? AppColors.green30
|
||||
: tender.status == 'submitted'
|
||||
? AppColors.green30
|
||||
: AppColors.red10,
|
||||
);
|
||||
if (index < tenders.length) {
|
||||
final tender = tenders[index];
|
||||
return TenderCard(
|
||||
date: tender.createdAt!.toString(),
|
||||
title: tender.tender!.title!,
|
||||
description: tender.tender!.description!,
|
||||
location: tender.tender!.countryCode!,
|
||||
countryFlag: AssetsManager.seFlag,
|
||||
status: tender.status,
|
||||
countryCode: tender.tender!.countryCode!,
|
||||
projectStatus: tender.tender!.status!,
|
||||
isDesktop: widget.isDesktop,
|
||||
backgroundColor:
|
||||
tender.status == 'Won'
|
||||
? AppColors.green0
|
||||
: tender.status == 'submitted'
|
||||
? AppColors.grey0
|
||||
: AppColors.red0.withValues(alpha: 0.2),
|
||||
borderColor:
|
||||
tender.status == 'Won'
|
||||
? AppColors.green10
|
||||
: tender.status == 'submitted'
|
||||
? AppColors.grey30
|
||||
: AppColors.red0,
|
||||
statusIcon:
|
||||
tender.status == 'Won'
|
||||
? AssetsManager.tickCircle
|
||||
: tender.status == 'submitted'
|
||||
? null
|
||||
: AssetsManager.closeCircle,
|
||||
statusCardColor:
|
||||
tender.status == 'Won'
|
||||
? AppColors.green20
|
||||
: tender.status == 'submitted'
|
||||
? AppColors.green20
|
||||
: AppColors.red0,
|
||||
statusTextColor:
|
||||
tender.status == 'Won'
|
||||
? AppColors.green30
|
||||
: tender.status == 'submitted'
|
||||
? AppColors.green30
|
||||
: AppColors.red10,
|
||||
);
|
||||
} else {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 20.0.h()),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 24.0.w(),
|
||||
height: 24.0.h(),
|
||||
child: CircularProgressIndicator(
|
||||
color: AppColors.secondary50,
|
||||
strokeWidth: 2,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -37,10 +37,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
version: "2.13.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -245,10 +245,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -500,10 +500,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.8"
|
||||
version: "10.0.9"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -937,10 +937,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.1"
|
||||
version: "15.0.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
Reference in New Issue
Block a user