383 lines
11 KiB
Dart
383 lines
11 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:tm_app/core/theme/colors.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 '../core/constants/assets.dart';
|
|
import '../core/constants/tender_approval_status.dart';
|
|
import '../core/constants/tender_feedback.dart';
|
|
import '../data/services/model/request_models/get_tenders_request_model/get_tenders_request_model.dart';
|
|
import '../data/services/model/request_models/tender_feedback_request_model/tender_feedback_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 = (currentPage - 1) * _limit;
|
|
hasMore = true;
|
|
_currentFeedbackType = feedbackType;
|
|
}
|
|
|
|
if (!reset && (isLoadingMore || !hasMore)) {
|
|
return;
|
|
}
|
|
|
|
if (_offset == 0) {
|
|
isLoading = true;
|
|
} else {
|
|
isLoadingMore = true;
|
|
}
|
|
notifyListeners();
|
|
|
|
final requestModel = TenderFeedbackRequestModel(
|
|
offset: _offset,
|
|
limit: _limit,
|
|
feedbackType: _currentFeedbackType ?? feedbackType,
|
|
dateFrom: startDateUnix,
|
|
dateTo: endDateUnix,
|
|
);
|
|
|
|
final result = await yourTendersRepository.getTendersFeedback(
|
|
requestModel: requestModel,
|
|
);
|
|
|
|
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: TenderApprovalStatus.submitted.value,
|
|
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;
|
|
currentPage = 1;
|
|
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 {
|
|
likedTendersData = null;
|
|
data = null;
|
|
isLoading = true;
|
|
notifyListeners();
|
|
|
|
if (selectedStatus == YourTendersStrings.all) {
|
|
final requestModel = GetTendersRequestModel(
|
|
status: '',
|
|
createdFrom: startDateUnix,
|
|
createdTo: endDateUnix,
|
|
limit: _tendersLimit,
|
|
offset: _tendersOffset,
|
|
);
|
|
await getTenders(requestModel: requestModel, reset: true);
|
|
} else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
|
|
final requestModel = GetTendersRequestModel(
|
|
status: TenderApprovalStatus.submitted.value,
|
|
createdFrom: startDateUnix,
|
|
createdTo: endDateUnix,
|
|
limit: _tendersLimit,
|
|
offset: _tendersOffset,
|
|
);
|
|
await getTenders(requestModel: requestModel, reset: true);
|
|
} else if (selectedStatus == YourTendersStrings.likeTenders) {
|
|
await getTendersFeedback(
|
|
feedbackType: TenderFeedback.liked.value,
|
|
reset: true,
|
|
);
|
|
} else if (selectedStatus == YourTendersStrings.dislikeTenders) {
|
|
await getTendersFeedback(
|
|
feedbackType: TenderFeedback.disliked.value,
|
|
reset: true,
|
|
);
|
|
}
|
|
}
|
|
|
|
int currentPage = 1;
|
|
|
|
int get totalPages {
|
|
if (likedTendersData?.data?.meta?.pages != null) {
|
|
return likedTendersData!.data!.meta!.pages!;
|
|
}
|
|
if (data?.data?.metadata?.pages != null) {
|
|
return data!.data!.metadata!.pages!;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
Future<void> jumpToPage(int page) async {
|
|
currentPage = page;
|
|
_offset = (page - 1) * _limit;
|
|
_tendersOffset = (page - 1) * _tendersLimit;
|
|
|
|
likedTendersData = null;
|
|
data = null;
|
|
hasMore = true;
|
|
hasMoreTenders = true;
|
|
|
|
await callWithFilter();
|
|
}
|
|
|
|
Color getBackGroundColorByStatus(String status) {
|
|
if (status == TenderFeedback.liked.value ||
|
|
status == TenderApprovalStatus.submitted.value) {
|
|
return AppColors.green0;
|
|
} else if (status == TenderFeedback.disliked.value ||
|
|
status == TenderApprovalStatus.rejected.value) {
|
|
return AppColors.red0;
|
|
}
|
|
return AppColors.grey0;
|
|
}
|
|
|
|
Color getBorderColorByStatus(String status) {
|
|
if (status == TenderFeedback.liked.value ||
|
|
status == TenderApprovalStatus.submitted.value) {
|
|
return AppColors.green10;
|
|
} else if (status == TenderFeedback.disliked.value ||
|
|
status == TenderApprovalStatus.rejected.value) {
|
|
return AppColors.red10;
|
|
}
|
|
return AppColors.grey30;
|
|
}
|
|
|
|
Color getStatusCardColorByStatus(String status) {
|
|
if (status == TenderFeedback.liked.value ||
|
|
status == TenderApprovalStatus.submitted.value) {
|
|
return AppColors.green20;
|
|
} else if (status == TenderFeedback.disliked.value ||
|
|
status == TenderApprovalStatus.rejected.value) {
|
|
return AppColors.red10;
|
|
}
|
|
return AppColors.grey0;
|
|
}
|
|
|
|
Color getStatusTextColorByStatus(String status) {
|
|
if (status == TenderFeedback.liked.value ||
|
|
status == TenderApprovalStatus.submitted.value) {
|
|
return AppColors.green30;
|
|
} else if (status == TenderFeedback.disliked.value ||
|
|
status == TenderApprovalStatus.rejected.value) {
|
|
return AppColors.red20;
|
|
}
|
|
return AppColors.grey60;
|
|
}
|
|
|
|
String? getStatusIconByStatus(String status) {
|
|
if (status == TenderFeedback.liked.value ||
|
|
status == TenderApprovalStatus.submitted.value) {
|
|
return AssetsManager.tickCircle;
|
|
} else if (status == TenderFeedback.disliked.value ||
|
|
status == TenderApprovalStatus.rejected.value) {
|
|
return AssetsManager.closeCircle;
|
|
}
|
|
return null;
|
|
}
|
|
}
|