Implement tender workflows and dashboard integration
continuous-integration/drone/push Build encountered an error
continuous-integration/drone/push Build encountered an error
This commit is contained in:
@@ -3,9 +3,11 @@ import 'package:intl/intl.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/error_utils.dart';
|
||||
import 'package:tm_app/core/utils/result.dart';
|
||||
import 'package:tm_app/core/network/app_exceptions.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/data/services/model/tender_submission/tender_submission.dart';
|
||||
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
|
||||
|
||||
import '../core/constants/assets.dart';
|
||||
@@ -22,6 +24,21 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
String? errorMessage;
|
||||
TenderApprovalsResponse? data;
|
||||
LikedTendersResponse? likedTendersData;
|
||||
TenderSubmissionsResponse? submissionsData;
|
||||
TenderSubmissionStats? submissionStats;
|
||||
String selectedSubmissionStage = 'opportunity';
|
||||
String? updatingSubmissionId;
|
||||
String? submissionActionError;
|
||||
|
||||
bool get isSubmissionWorkflow =>
|
||||
selectedStatus == TenderApprovalStatus.submitted.value;
|
||||
|
||||
static const submissionStages = <String>[
|
||||
'opportunity',
|
||||
'in_progress',
|
||||
'submitted',
|
||||
'not_applied',
|
||||
];
|
||||
|
||||
// Pagination state for feedback lists
|
||||
bool isLoadingMore = false;
|
||||
@@ -247,6 +264,8 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
// Clear main data
|
||||
data = null;
|
||||
likedTendersData = null;
|
||||
submissionsData = null;
|
||||
submissionStats = null;
|
||||
|
||||
// Clear loading states
|
||||
isLoading = false;
|
||||
@@ -269,6 +288,7 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
Future<void> callWithFilter() async {
|
||||
likedTendersData = null;
|
||||
data = null;
|
||||
submissionsData = null;
|
||||
isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
@@ -282,14 +302,8 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
);
|
||||
await getTenders(requestModel: requestModel, reset: true);
|
||||
} else if (selectedStatus == TenderApprovalStatus.submitted.value) {
|
||||
final requestModel = GetTendersRequestModel(
|
||||
status: TenderApprovalStatus.submitted.value,
|
||||
createdFrom: startDateUnix,
|
||||
createdTo: endDateUnix,
|
||||
limit: _tendersLimit,
|
||||
offset: _tendersOffset,
|
||||
);
|
||||
await getTenders(requestModel: requestModel, reset: true);
|
||||
selectedSubmissionStage = 'submitted';
|
||||
await loadSubmissions();
|
||||
} else if (selectedStatus == TenderFeedback.liked.value) {
|
||||
await getTendersFeedback(
|
||||
feedbackType: TenderFeedback.liked.value,
|
||||
@@ -318,6 +332,11 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
int currentPage = 1;
|
||||
|
||||
int get totalPages {
|
||||
if (isSubmissionWorkflow && submissionsData?.meta != null) {
|
||||
return submissionsData!.meta!.pages == 0
|
||||
? 1
|
||||
: submissionsData!.meta!.pages;
|
||||
}
|
||||
if (likedTendersData?.data?.meta?.pages != null) {
|
||||
return likedTendersData!.data!.meta!.pages!;
|
||||
}
|
||||
@@ -329,6 +348,10 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
|
||||
Future<void> jumpToPage(int page) async {
|
||||
currentPage = page;
|
||||
if (isSubmissionWorkflow) {
|
||||
await loadSubmissions(offset: (page - 1) * 20);
|
||||
return;
|
||||
}
|
||||
_offset = (page - 1) * _limit;
|
||||
_tendersOffset = (page - 1) * _tendersLimit;
|
||||
|
||||
@@ -340,6 +363,94 @@ class YourTendersViewModel with ChangeNotifier {
|
||||
await callWithFilter();
|
||||
}
|
||||
|
||||
Future<void> selectSubmissionStage(String stage) async {
|
||||
if (!submissionStages.contains(stage) || stage == selectedSubmissionStage) {
|
||||
return;
|
||||
}
|
||||
selectedSubmissionStage = stage;
|
||||
submissionActionError = null;
|
||||
currentPage = 1;
|
||||
notifyListeners();
|
||||
await loadSubmissions();
|
||||
}
|
||||
|
||||
Future<void> loadSubmissions({int offset = 0}) async {
|
||||
isLoading = true;
|
||||
errorMessage = null;
|
||||
notifyListeners();
|
||||
|
||||
final result = await yourTendersRepository.getSubmissions(
|
||||
stage: selectedSubmissionStage,
|
||||
limit: 20,
|
||||
offset: offset,
|
||||
);
|
||||
switch (result) {
|
||||
case Ok<TenderSubmissionsResponse>():
|
||||
submissionsData = result.value;
|
||||
currentPage = result.value.meta?.page ?? 1;
|
||||
case Error<TenderSubmissionsResponse>():
|
||||
errorMessage = ErrorUtils.getErrorMessage(result.error);
|
||||
}
|
||||
|
||||
final statsResult = await yourTendersRepository.getSubmissionStats();
|
||||
switch (statsResult) {
|
||||
case Ok<TenderSubmissionStatsResponse>():
|
||||
submissionStats = statsResult.value.data;
|
||||
case Error<TenderSubmissionStatsResponse>():
|
||||
// The list remains useful when stats are temporarily unavailable.
|
||||
break;
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<bool> updateSubmissionStatus({
|
||||
required TenderSubmission submission,
|
||||
required String status,
|
||||
String? reason,
|
||||
String? description,
|
||||
}) async {
|
||||
if (submission.id.isEmpty || submission.isTerminal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
updatingSubmissionId = submission.id;
|
||||
submissionActionError = null;
|
||||
notifyListeners();
|
||||
final result = await yourTendersRepository.updateSubmissionStatus(
|
||||
id: submission.id,
|
||||
status: status,
|
||||
reason: reason,
|
||||
description: description,
|
||||
);
|
||||
|
||||
switch (result) {
|
||||
case Ok<TenderSubmissionResponse>():
|
||||
updatingSubmissionId = null;
|
||||
await loadSubmissions();
|
||||
return true;
|
||||
case Error<TenderSubmissionResponse>():
|
||||
updatingSubmissionId = null;
|
||||
if (result.error is AppException &&
|
||||
(result.error as AppException).statusCode == 409) {
|
||||
await loadSubmissions();
|
||||
submissionActionError =
|
||||
'This submission changed elsewhere. The latest state has been loaded; please try again.';
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
submissionActionError = ErrorUtils.getErrorMessage(result.error);
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void dismissSubmissionActionError() {
|
||||
submissionActionError = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Color getBackGroundColorByStatus(String status) {
|
||||
if (status == TenderFeedback.liked.value ||
|
||||
status == TenderApprovalStatus.submitted.value) {
|
||||
|
||||
Reference in New Issue
Block a user