merge branches

This commit is contained in:
amirrezaghabeli
2025-08-20 13:11:22 +03:30
parent 1af9c0a76b
commit 4b51071aad
36 changed files with 1894 additions and 167 deletions
-7
View File
@@ -74,13 +74,6 @@ class AuthViewModel with ChangeNotifier {
notifyListeners();
}
void forceLogout() {
_loggedInUser = null;
usernameController.clear();
passwordController.clear();
notifyListeners();
}
Future<void> logout() async {
_errorMessage = null;
notifyListeners();
+16 -23
View File
@@ -1,8 +1,6 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/data/repositories/auth_repository.dart';
import 'package:tm_app/data/services/model/profile_data/profile_data.dart';
import 'package:tm_app/view_models/auth_view_model.dart';
import '../core/utils/result.dart';
import '../data/repositories/profile_repository.dart';
@@ -55,30 +53,25 @@ class ProfileViewModel with ChangeNotifier {
Future<void> localLogout() async {
await _authRepository.localLogout();
_loggedOut = true;
notifyListeners();
}
Future<void> logout(BuildContext context) async {
_errorMessage = null;
notifyListeners();
Future<void> logout(BuildContext context) async {
_errorMessage = null;
notifyListeners();
final result = await _authRepository.logout();
final result = await _authRepository.logout();
switch (result) {
case Ok<LogoutResponse>():
await localLogout();
// دسترسی به AuthViewModel و ریست یوزر
// چون با Provider کار می‌کنی:
final authViewModel = Provider.of<AuthViewModel>(context, listen: false);
authViewModel.forceLogout();
_loggedOut = true;
break;
case Error<LogoutResponse>():
_errorMessage = result.error.toString();
break;
switch (result) {
case Ok<LogoutResponse>():
localLogout();
break;
case Error<LogoutResponse>():
_errorMessage = result.error.toString();
break;
}
_errorMessage = null;
notifyListeners();
}
_errorMessage = null;
notifyListeners();
}
}
+65 -1
View File
@@ -1,21 +1,33 @@
import 'package:flutter/material.dart';
import 'package:tm_app/core/utils/result.dart';
import 'package:tm_app/data/repositories/tender_detail_repository.dart';
import 'package:tm_app/data/repositories/tenders_repository.dart';
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
import 'package:tm_app/data/services/model/tender_detail_response/tender_detail_response_model.dart';
import '../data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
class TenderDetailViewModel with ChangeNotifier {
final TenderDetailRepository _tenderDetailRepository;
final TendersRepository _tendersRepository;
TenderDetailViewModel({
required TenderDetailRepository tenderDetailRepository,
}) : _tenderDetailRepository = tenderDetailRepository;
required TendersRepository tendersRepository,
}) : _tenderDetailRepository = tenderDetailRepository,
_tendersRepository = tendersRepository;
bool _isLoading = false;
bool _isSubmitApprovalLoading = false;
bool _isRejectApprovalLoading = false;
String? _errorMessage;
TenderData? _tenderDetail;
bool approvalStatus = false;
bool get isLoading => _isLoading;
bool get isSubmitApprovalLoading => _isSubmitApprovalLoading;
bool get isRejectApprovalLoading => _isRejectApprovalLoading;
String? get errorMessage => _errorMessage;
TenderData? get tenderDetail => _tenderDetail;
@@ -37,4 +49,56 @@ class TenderDetailViewModel with ChangeNotifier {
_isLoading = false;
notifyListeners();
}
Future<void> submitTenderApproval({
required String tenderId,
required String submissionMode,
}) async {
_isSubmitApprovalLoading = true;
notifyListeners();
final result = await _tendersRepository.toggleApprovals(
tenderId: tenderId,
status: 'approved',
submissionMode: submissionMode,
);
switch (result) {
case Ok<TenderApprovalsToggleResponse>():
approvalStatus = true;
break;
case Error<TenderApprovalsToggleResponse>():
_errorMessage = result.error.toString();
approvalStatus = false;
break;
}
_isSubmitApprovalLoading = false;
notifyListeners();
_errorMessage = null;
notifyListeners();
}
Future<void> rejectTenderApproval({
required String tenderId,
required String submissionMode,
}) async {
_isRejectApprovalLoading = true;
notifyListeners();
final result = await _tendersRepository.toggleApprovals(
tenderId: tenderId,
status: 'rejected',
submissionMode: submissionMode,
);
switch (result) {
case Ok<TenderApprovalsToggleResponse>():
approvalStatus = true;
break;
case Error<TenderApprovalsToggleResponse>():
_errorMessage = result.error.toString();
approvalStatus = false;
break;
}
_isRejectApprovalLoading = false;
notifyListeners();
_errorMessage = null;
notifyListeners();
}
}
+116
View File
@@ -4,9 +4,13 @@ import 'package:flutter/material.dart';
import 'package:tm_app/data/repositories/tenders_repository.dart';
import 'package:tm_app/data/services/model/feedback_data/feedback_data.dart';
import 'package:tm_app/data/services/model/feedback_response/feedback_response.dart';
import 'package:tm_app/data/services/model/tender_approvals_toggle_data/tender_approvals_toggle_data.dart';
import 'package:tm_app/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
import 'package:tm_app/data/services/model/tenders/tenders_response/tenders_response.dart';
import '../core/utils/result.dart';
import '../data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart';
import '../data/services/model/tender_approvals_data/tender_approvals_data.dart';
class TendersViewModel with ChangeNotifier {
final TendersRepository _tendersRepository;
@@ -23,14 +27,20 @@ class TendersViewModel with ChangeNotifier {
String? _errorMessage;
TendersResponse? _tendersResponse;
FeedbackData? _feedbackData;
TenderApprovalsData? _tenderApprovalData;
TenderApprovalsToggleData? _tenderApprovalToggleData;
bool get isLoading => _isLoading;
bool get isLoadingMore => _isLoadingMore;
String? get errorMessage => _errorMessage;
TendersResponse? get tendersResponse => _tendersResponse;
FeedbackData? get feedbackData => _feedbackData;
TenderApprovalsData? get tenderApprovalData => _tenderApprovalData;
TenderApprovalsToggleData? get tenderApprovalToggleData =>
_tenderApprovalToggleData;
List<FeedbackData> feedbacks = [];
List<TenderApprovalsData> tenderApprovals = [];
int currentPage = 1;
int _currentOffset = 0;
@@ -53,6 +63,26 @@ class TendersViewModel with ChangeNotifier {
return feedbacks.any((f) => f.tender == tenderId);
}
/// Get tender approval for a specific tender
TenderApprovalsData? getTenderApprovalForTender(String tenderId) {
try {
return tenderApprovals.firstWhere((a) => a.tenderId == tenderId);
} catch (e) {
return null;
}
}
/// Check if tender approval exists for a specific tender
bool hasTenderApprovalForTender(String tenderId) {
return tenderApprovals.any((a) => a.tenderId == tenderId);
}
/// Get approval status for a specific tender
String? getApprovalStatusForTender(String tenderId) {
final approval = getTenderApprovalForTender(tenderId);
return approval?.status;
}
Future<void> getTenders() async {
_isLoading = true;
_errorMessage = null;
@@ -72,7 +102,9 @@ class TendersViewModel with ChangeNotifier {
_hasMoreData = _tendersResponse!.data!.tenders!.length >= _pageSize;
}
if (_tendersResponse?.data?.tenders?.isNotEmpty == true) {
// Fetch feedback and approvals for the first tender only
getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!);
getTenderApprovals(_tendersResponse!.data!.tenders!.first.id!);
}
break;
case Error<TendersResponse>():
@@ -169,6 +201,44 @@ class TendersViewModel with ChangeNotifier {
notifyListeners();
}
Future<void> getTenderApprovals(String tenderId) async {
_errorMessage = null;
notifyListeners();
final result = await _tendersRepository.getTenderApprovals(
tenderId: tenderId,
);
switch (result) {
case Ok<TenderApprovalsByIdResponse>():
_tenderApprovalData = result.value.data;
// Add or update _tenderApprovalData in tenderApprovals list by tender id
if (_tenderApprovalData != null) {
final index = tenderApprovals.indexWhere(
(a) => a.tenderId == _tenderApprovalData!.tenderId,
);
if (index != -1) {
tenderApprovals[index] = _tenderApprovalData!;
log(
'Updated approval for tender: ${_tenderApprovalData!.tenderId}',
);
} else {
tenderApprovals.add(_tenderApprovalData!);
log(
'Added new approval for tender: ${_tenderApprovalData!.tenderId}',
);
}
log('Total approvals: ${tenderApprovals.length}');
}
break;
case Error<TenderApprovalsByIdResponse>():
_errorMessage = result.error.toString();
break;
}
notifyListeners();
_errorMessage = null;
notifyListeners();
}
Future<void> feedback({
required String tenderId,
required String feedbackType,
@@ -202,4 +272,50 @@ class TendersViewModel with ChangeNotifier {
_errorMessage = null;
notifyListeners();
}
Future<void> toggleApprovals({
required String tenderId,
required String submissionMode,
required String status,
}) async {
_errorMessage = null;
notifyListeners();
final result = await _tendersRepository.toggleApprovals(
tenderId: tenderId,
submissionMode: submissionMode,
status: status,
);
switch (result) {
case Ok<TenderApprovalsToggleResponse>():
_tenderApprovalToggleData = result.value.data;
if (_tenderApprovalToggleData != null) {
// Convert TenderApprovalsToggleData to TenderApprovalsData
final approvalData = TenderApprovalsData(
id: _tenderApprovalToggleData!.id,
status: _tenderApprovalToggleData!.status,
tenderId: _tenderApprovalToggleData!.tenderId,
companyId: _tenderApprovalToggleData!.companyId,
submissionMode: _tenderApprovalToggleData!.submissionMode,
createdAt: _tenderApprovalToggleData!.createdAt,
tender: null, // Tender data is not included in toggle response
);
final index = tenderApprovals.indexWhere(
(a) => a.tenderId == approvalData.tenderId,
);
if (index != -1) {
tenderApprovals[index] = approvalData;
} else {
tenderApprovals.add(approvalData);
}
}
break;
case Error<TenderApprovalsToggleResponse>():
_errorMessage = result.error.toString();
break;
}
notifyListeners();
_errorMessage = null;
notifyListeners();
}
}