tenders pagination added

This commit is contained in:
amirrezaghabeli
2025-08-19 08:08:31 +03:30
parent 0c1b27fd1e
commit da6b1f28cf
4 changed files with 111 additions and 13 deletions
@@ -8,8 +8,11 @@ class TendersRepository {
: _tendersService = tendersService;
final TendersService _tendersService;
Future<Result<TendersResponse>> getTenders() async {
return _tendersService.getTenders();
Future<Result<TendersResponse>> getTenders({
required int limit,
required int offset,
}) async {
return _tendersService.getTenders(limit: limit, offset: offset);
}
Future<Result<FeedbackResponse>> getTenderFeedback({
+5 -2
View File
@@ -11,9 +11,12 @@ class TendersService {
: _networkManager = networkManager;
final NetworkManager _networkManager;
Future<Result<TendersResponse>> getTenders() async {
Future<Result<TendersResponse>> getTenders({
required int limit,
required int offset,
}) async {
final result = await _networkManager.makeRequest(
'/api/v1/tenders',
'/api/v1/tenders?limit=$limit&offset=$offset',
method: 'GET',
(json) => TendersResponse.fromJson(json),
);
+68 -2
View File
@@ -19,11 +19,13 @@ class TendersViewModel with ChangeNotifier {
}
bool _isLoading = false;
bool _isLoadingMore = false;
String? _errorMessage;
TendersResponse? _tendersResponse;
FeedbackData? _feedbackData;
bool get isLoading => _isLoading;
bool get isLoadingMore => _isLoadingMore;
String? get errorMessage => _errorMessage;
TendersResponse? get tendersResponse => _tendersResponse;
FeedbackData? get feedbackData => _feedbackData;
@@ -31,6 +33,11 @@ class TendersViewModel with ChangeNotifier {
List<FeedbackData> feedbacks = [];
int currentPage = 1;
int _currentOffset = 0;
static const int _pageSize = 10;
bool _hasMoreData = true;
bool get hasMoreData => _hasMoreData;
/// Get feedback for a specific tender
FeedbackData? getFeedbackForTender(String tenderId) {
@@ -49,13 +56,24 @@ class TendersViewModel with ChangeNotifier {
Future<void> getTenders() async {
_isLoading = true;
_errorMessage = null;
_currentOffset = 0;
_hasMoreData = true;
notifyListeners();
final result = await _tendersRepository.getTenders();
final result = await _tendersRepository.getTenders(
limit: _pageSize,
offset: _currentOffset,
);
switch (result) {
case Ok<TendersResponse>():
_tendersResponse = result.value;
getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!);
// Check if we have more data
if (_tendersResponse?.data?.tenders != null) {
_hasMoreData = _tendersResponse!.data!.tenders!.length >= _pageSize;
}
if (_tendersResponse?.data?.tenders?.isNotEmpty == true) {
getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!);
}
break;
case Error<TendersResponse>():
_errorMessage = result.error.toString();
@@ -67,6 +85,54 @@ class TendersViewModel with ChangeNotifier {
notifyListeners();
}
Future<void> loadMoreTenders() async {
if (_isLoadingMore || !_hasMoreData) return;
_isLoadingMore = true;
_errorMessage = null;
notifyListeners();
_currentOffset += _pageSize;
final result = await _tendersRepository.getTenders(
limit: _pageSize,
offset: _currentOffset,
);
switch (result) {
case Ok<TendersResponse>():
if (result.value.data?.tenders != null &&
result.value.data!.tenders!.isNotEmpty) {
// Create a new modifiable list by combining existing and new tenders
if (_tendersResponse?.data?.tenders != null) {
final existingTenders = _tendersResponse!.data!.tenders!;
final newTenders = result.value.data!.tenders!;
final combinedTenders = [...existingTenders, ...newTenders];
// Create a new TendersData with the combined list
_tendersResponse = _tendersResponse!.copyWith(
data: _tendersResponse!.data!.copyWith(tenders: combinedTenders),
);
} else {
_tendersResponse = result.value;
}
// Check if we have more data
_hasMoreData = result.value.data!.tenders!.length >= _pageSize;
} else {
_hasMoreData = false;
}
break;
case Error<TendersResponse>():
_errorMessage = result.error.toString();
_currentOffset -= _pageSize; // Revert offset on error
break;
}
_isLoadingMore = false;
notifyListeners();
_errorMessage = null;
notifyListeners();
}
Future<void> getTenderFeedback(String tenderId) async {
// _isLoading = true;
_errorMessage = null;
@@ -94,11 +94,19 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
setState(() {
currentPage = index + 1;
});
// Fetch feedback for the new tender if not already loaded
final viewModel = context.read<TendersViewModel>();
if (!viewModel.hasFeedbackForTender(widget.tenders[index].id!)) {
viewModel.getTenderFeedback(widget.tenders[index].id!);
}
// Check if we need to load more tenders (when user reaches near the end)
if (index >= widget.tenders.length - 1 &&
viewModel.hasMoreData &&
!viewModel.isLoadingMore) {
viewModel.loadMoreTenders();
}
},
itemBuilder: (context, index) {
final tender = widget.tenders[index];
@@ -142,13 +150,31 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
}
Widget _pageNumberText() {
return Text(
'$currentPage/${widget.tenders.length}',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.grey,
),
final viewModel = context.watch<TendersViewModel>();
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'$currentPage/${widget.tenders.length}',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.grey,
),
),
if (viewModel.isLoadingMore)
Padding(
padding: EdgeInsets.only(top: 4.0.h()),
child: SizedBox(
width: 16.0.w(),
height: 16.0.w(),
child: CircularProgressIndicator(
strokeWidth: 2.0,
color: AppColors.jellyBean,
),
),
),
],
);
}