Files
tm_app/lib/view_models/your_tenders_view_model.dart
T

284 lines
7.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:tm_app/core/utils/result.dart';
import 'package:tm_app/data/repositories/your_tenders_repository.dart';
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart';
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
import '../data/services/model/request_models/get_tenders_request_model/get_tenders_request_model.dart';
class YourTendersViewModel with ChangeNotifier {
final YourTendersRepository yourTendersRepository;
YourTendersViewModel({required this.yourTendersRepository});
bool isLoading = false;
String? errorMessage;
TenderApprovalsResponse? data;
LikedTendersResponse? likedTendersData;
// Pagination state for feedback lists
bool isLoadingMore = false;
bool hasMore = true;
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';
final _fmt = DateFormat('yyyy/MM/dd');
String get startDateFormatted =>
selectedDateRange?.start != null
? _fmt.format(selectedDateRange!.start)
: 'YYYY/MM/DD';
String get endDateFormatted =>
selectedDateRange?.end != null
? _fmt.format(selectedDateRange!.end)
: 'YYYY/MM/DD';
String get startDateUnix =>
selectedDateRange?.start != null
? (selectedDateRange!.start.millisecondsSinceEpoch ~/ 1000).toString()
: '';
String get endDateUnix =>
selectedDateRange?.end != null
? (selectedDateRange!.end.millisecondsSinceEpoch ~/ 1000).toString()
: '';
Future<void> getTenders({
required GetTendersRequestModel requestModel,
bool reset = false,
}) async {
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(
requestModel: requestModel,
);
switch (result) {
case Ok<TenderApprovalsResponse>():
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>():
errorMessage = result.error.toString();
break;
}
isLoading = false;
isLoadingMoreTenders = false;
notifyListeners();
}
Future<void> getTendersFeedback({
required String feedbackType,
bool reset = false,
}) async {
if (reset) {
_offset = 0;
hasMore = true;
_currentFeedbackType = feedbackType;
}
if (!reset && (isLoadingMore || !hasMore)) {
return;
}
if (_offset == 0) {
isLoading = true;
} else {
isLoadingMore = true;
}
notifyListeners();
final result = await yourTendersRepository.getTendersFeedback(
limit: _limit,
offset: _offset,
feedbackType: _currentFeedbackType ?? feedbackType,
dateFrom: startDateUnix,
dateTo: endDateUnix,
);
switch (result) {
case Ok<LikedTendersResponse>():
final incoming = result.value;
final incomingList = incoming.data?.feedback ?? [];
if (reset || likedTendersData == null) {
likedTendersData = incoming;
} else {
final existingList = likedTendersData!.data?.feedback ?? [];
final combined = List.of(existingList)..addAll(incomingList);
final newMeta = incoming.data?.meta ?? likedTendersData!.data?.meta;
likedTendersData = likedTendersData!.copyWith(
data: likedTendersData!.data!.copyWith(
feedback: combined,
meta: newMeta,
),
);
}
hasMore = incomingList.length == _limit;
_offset += _limit;
errorMessage = null;
break;
case Error<LikedTendersResponse>():
errorMessage = result.error.toString();
break;
}
isLoading = false;
isLoadingMore = false;
notifyListeners();
}
Future<void> loadMoreFeedback() async {
if (_currentFeedbackType == null) {
return;
}
await getTendersFeedback(feedbackType: _currentFeedbackType!, reset: false);
}
Future<void> loadMoreTenders() async {
if (isLoadingMoreTenders || !hasMoreTenders) {
return;
}
if (selectedStatus == YourTendersStrings.all) {
final requestModel = GetTendersRequestModel(
status: '',
createdFrom: startDateUnix,
createdTo: endDateUnix,
limit: _tendersLimit,
offset: _tendersOffset,
);
await getTenders(requestModel: requestModel);
} else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
final requestModel = GetTendersRequestModel(
status: 'submitted',
createdFrom: startDateUnix,
createdTo: endDateUnix,
limit: _tendersLimit,
offset: _tendersOffset,
);
await getTenders(requestModel: requestModel);
}
}
// --- Filter Actions ---
void setDateRange(DateTimeRange? range) {
selectedDateRange = range;
notifyListeners();
}
void setStatus(String status) {
// Clear data when status changes
_clearAllData();
selectedStatus = status;
notifyListeners();
}
void clearFilter() {
// Clear data when clearing filter
_clearAllData();
selectedDateRange = null;
selectedStatus = YourTendersStrings.all;
notifyListeners();
}
// Clear all data and reset states
void _clearAllData() {
// Clear main data
data = null;
likedTendersData = null;
// Clear loading states
isLoading = false;
isLoadingMore = false;
isLoadingMoreTenders = false;
// Clear error messages
errorMessage = null;
// Reset pagination states
_offset = 0;
_tendersOffset = 0;
hasMore = true;
hasMoreTenders = true;
_currentFeedbackType = null;
notifyListeners();
}
Future<void> callWithFilter() async {
// Clear data before applying filter
_clearAllData();
// Make fresh request based on selected status
if (selectedStatus == YourTendersStrings.all) {
final requestModel = GetTendersRequestModel(
status: '',
createdFrom: startDateUnix,
createdTo: endDateUnix,
limit: _tendersLimit,
offset: 0,
);
await getTenders(requestModel: requestModel, reset: true);
} else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
final requestModel = GetTendersRequestModel(
status: 'submitted',
createdFrom: startDateUnix,
createdTo: endDateUnix,
limit: _tendersLimit,
offset: 0,
);
await getTenders(requestModel: requestModel, reset: true);
} else if (selectedStatus == YourTendersStrings.likeTenders) {
await getTendersFeedback(feedbackType: 'like', reset: true);
} else if (selectedStatus == YourTendersStrings.dislikeTenders) {
await getTendersFeedback(feedbackType: 'dislike', reset: true);
}
}
}