From dad572af60b71ba183b2a096e2d111d40c67eb2b Mon Sep 17 00:00:00 2001 From: amirrezaghabeli Date: Sat, 6 Sep 2025 14:10:49 +0330 Subject: [PATCH] show message when there is error in submit or remove approvals --- lib/core/network/app_exceptions.dart | 18 +-- lib/data/services/liked_tenders_service.dart | 26 ++-- lib/view_models/liked_tenders_view_model.dart | 8 +- .../pages/liked_tenders_desktop_page.dart | 17 +++ .../pages/liked_tenders_mobile_page.dart | 139 ++++++++++-------- .../pages/liked_tenders_tablet_page.dart | 17 +++ 6 files changed, 137 insertions(+), 88 deletions(-) diff --git a/lib/core/network/app_exceptions.dart b/lib/core/network/app_exceptions.dart index 1529f1c..2dd2dd7 100644 --- a/lib/core/network/app_exceptions.dart +++ b/lib/core/network/app_exceptions.dart @@ -21,7 +21,7 @@ class FetchDataException extends AppException { FetchDataException([String? message, int? statusCode, originalError]) : super( message ?? 'Error During Communication: ', - 'Network Error', + 'Network Error : ', statusCode, originalError, ); @@ -31,7 +31,7 @@ class AuthenticationException extends AppException { AuthenticationException([String? message, int? statusCode, originalError]) : super( message ?? 'Authentication Failed.', - 'Auth Error: ', + 'Auth Error : ', statusCode, originalError, ); @@ -41,7 +41,7 @@ class NetworkConnectionException extends AppException { NetworkConnectionException([String? message, originalError]) : super( message ?? 'No internet connection available.', - 'Connection Error: ', + 'Connection Error : ', null, originalError, ); @@ -51,7 +51,7 @@ class TimeoutException extends AppException { TimeoutException([String? message, originalError]) : super( message ?? 'Request timed out.', - 'Timeout Error: ', + 'Timeout Error : ', null, originalError, ); @@ -61,7 +61,7 @@ class ServerException extends AppException { ServerException([String? message, int? statusCode, originalError]) : super( message ?? 'Server error occurred.', - 'Server Error: ', + 'Server Error : ', statusCode, originalError, ); @@ -71,7 +71,7 @@ class BadRequestException extends AppException { BadRequestException([String? message, int? statusCode, originalError]) : super( message ?? 'Bad request.', - 'Bad Request Error: ', + 'Bad Request Error : ', statusCode, originalError, ); @@ -81,7 +81,7 @@ class NotFoundException extends AppException { NotFoundException([String? message, int? statusCode, originalError]) : super( message ?? 'Resource not found.', - 'Not Found Error: ', + 'Not Found Error : ', statusCode, originalError, ); @@ -91,7 +91,7 @@ class ForbiddenException extends AppException { ForbiddenException([String? message, int? statusCode, originalError]) : super( message ?? 'Access forbidden.', - 'Forbidden Error: ', + 'Forbidden Error : ', statusCode, originalError, ); @@ -101,7 +101,7 @@ class RateLimitException extends AppException { RateLimitException([String? message, int? statusCode, originalError]) : super( message ?? 'Rate limit exceeded.', - 'Rate Limit Error: ', + 'Rate Limit Error : ', statusCode, originalError, ); diff --git a/lib/data/services/liked_tenders_service.dart b/lib/data/services/liked_tenders_service.dart index 40f777c..b58a79d 100644 --- a/lib/data/services/liked_tenders_service.dart +++ b/lib/data/services/liked_tenders_service.dart @@ -6,22 +6,22 @@ import '../../../core/network/network_manager.dart'; class LikedTendersService { LikedTendersService({required NetworkManager networkManager}) - : _networkManager = networkManager; + : _networkManager = networkManager; final NetworkManager _networkManager; -Future> getLikedTenders({ - int offset = 0, - int limit = 20, -}) async { - final uri = '${LikedTendersApi.likedTenders}&limit=$limit&offset=$offset'; + Future> getLikedTenders({ + int offset = 0, + int limit = 20, + }) async { + final uri = '${LikedTendersApi.likedTenders}&limit=$limit&offset=$offset'; - final result = await _networkManager.makeRequest( - uri, - (json) => LikedTendersResponse.fromJson(json), - method: 'GET', - ); + final result = await _networkManager.makeRequest( + uri, + (json) => LikedTendersResponse.fromJson(json), + method: 'GET', + ); - return result; -} + return result; + } } diff --git a/lib/view_models/liked_tenders_view_model.dart b/lib/view_models/liked_tenders_view_model.dart index 149d280..4dd0c66 100644 --- a/lib/view_models/liked_tenders_view_model.dart +++ b/lib/view_models/liked_tenders_view_model.dart @@ -55,6 +55,11 @@ class LikedTendersViewModel with ChangeNotifier { _homeViewModel.init(); } + void clearApprovalErrorMessage() { + _errorMessage = null; + notifyListeners(); + } + Future getLikedTenders({bool reset = false}) async { if (!reset && (isLoadingMore || !hasMore)) { return; @@ -303,7 +308,7 @@ class LikedTendersViewModel with ChangeNotifier { approvalStatus = false; break; } - + approvalStatus = false; _isSubmitApprovalLoading = false; notifyListeners(); } @@ -370,6 +375,7 @@ class LikedTendersViewModel with ChangeNotifier { break; } + approvalStatus = false; _isRejectApprovalLoading = false; notifyListeners(); } diff --git a/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart b/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart index 1d7b251..75ddb6c 100644 --- a/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart +++ b/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart @@ -24,9 +24,26 @@ class _LikedTendersDesktopPageState extends State { @override void initState() { viewModel = context.read(); + viewModel.addListener(_viewModelListener); super.initState(); } + void _viewModelListener() { + if (viewModel.approvalErrorMessage?.isNotEmpty == true && + viewModel.approvalStatus == false) { + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(viewModel.approvalErrorMessage!))); + viewModel.clearApprovalErrorMessage(); + } + } + + @override + void dispose() { + viewModel.removeListener(_viewModelListener); + super.dispose(); + } + @override Widget build(BuildContext context) { return PopScope( diff --git a/lib/views/liked_tenders/pages/liked_tenders_mobile_page.dart b/lib/views/liked_tenders/pages/liked_tenders_mobile_page.dart index 0dfc95c..1ae8380 100644 --- a/lib/views/liked_tenders/pages/liked_tenders_mobile_page.dart +++ b/lib/views/liked_tenders/pages/liked_tenders_mobile_page.dart @@ -27,6 +27,18 @@ class _LikedTendersMobilePageState extends State { viewModel = context.read(); super.initState(); _scrollController = ScrollController()..addListener(_onScroll); + viewModel.addListener(_viewModelListener); + } + + void _viewModelListener() { + if (mounted && + viewModel.approvalErrorMessage?.isNotEmpty == true && + viewModel.approvalStatus == false) { + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(viewModel.approvalErrorMessage!))); + viewModel.clearApprovalErrorMessage(); + } } void _onScroll() { @@ -46,6 +58,7 @@ class _LikedTendersMobilePageState extends State { void dispose() { _scrollController.removeListener(_onScroll); _scrollController.dispose(); + viewModel.removeListener(_viewModelListener); super.dispose(); } @@ -94,75 +107,71 @@ class _LikedTendersMobilePageState extends State { final itemCount = feedback.length + (viewModel.isLoadingMore ? 1 : 0); - return RefreshIndicator( - onRefresh: () async { - await viewModel.getLikedTenders(reset: true); - }, - child: ListView.builder( - controller: _scrollController, - padding: EdgeInsets.symmetric( - horizontal: 24.0.w(), - vertical: 15.0.h(), - ), - itemCount: itemCount, - itemBuilder: (context, index) { - if (index < feedback.length) { - final item = feedback[index]; - TenderApprovalsData? approval; - bool hasApproval = viewModel - .hasTenderApprovalForTender(item.tenderId!); - if (hasApproval) { - approval = viewModel.getApprovalStatusForTender( - item.tenderId!, - ); - } else { - approval = null; - } - - return Padding( - padding: EdgeInsets.only(bottom: 20.0.h()), - child: Dismissible( - key: ValueKey(item.tenderId ?? index), - direction: DismissDirection.endToStart, - background: Container( - alignment: Alignment.centerRight, - padding: EdgeInsets.symmetric( - horizontal: 20.0.w(), - ), - child: SvgPicture.asset( - AssetsManager.trash, - width: 32.0.w(), - height: 32.0.h(), - ), - ), - onDismissed: (_) { - if (item.tenderId != null) { - viewModel.removeTenderById(item.tenderId!); - } - }, - child: LikedListItem( - tender: item.tender!, - approval: approval, - ), - ), + return ListView.builder( + controller: _scrollController, + padding: EdgeInsets.symmetric( + horizontal: 24.0.w(), + vertical: 15.0.h(), + ), + itemCount: itemCount, + itemBuilder: (context, index) { + if (index < feedback.length) { + final item = feedback[index]; + TenderApprovalsData? approval; + bool hasApproval = viewModel.hasTenderApprovalForTender( + item.tenderId!, + ); + if (hasApproval) { + approval = viewModel.getApprovalStatusForTender( + item.tenderId!, ); } else { - return Padding( - padding: EdgeInsets.symmetric(vertical: 20.0.h()), - child: Center( - child: SizedBox( - width: 24.0.w(), - height: 24.0.h(), - child: CircularProgressIndicator( - color: AppColors.secondary50, - strokeWidth: 2, - ), + approval = null; + } + + return Padding( + padding: EdgeInsets.only(bottom: 20.0.h()), + child: Dismissible( + key: ValueKey(item.tenderId ?? index), + direction: DismissDirection.endToStart, + background: Container( + alignment: Alignment.centerRight, + padding: EdgeInsets.symmetric( + horizontal: 20.0.w(), + ), + child: SvgPicture.asset( + AssetsManager.trash, + width: 32.0.w(), + height: 32.0.h(), ), ), - ); - } - }, - ), + onDismissed: (_) { + if (item.tenderId != null) { + viewModel.removeTenderById(item.tenderId!); + } + }, + child: LikedListItem( + tender: item.tender!, + approval: approval, + ), + ), + ); + } else { + return Padding( + padding: EdgeInsets.symmetric(vertical: 20.0.h()), + child: Center( + child: SizedBox( + width: 24.0.w(), + height: 24.0.h(), + child: CircularProgressIndicator( + color: AppColors.secondary50, + strokeWidth: 2, + ), + ), + ), + ); + } + }, ); }, ), diff --git a/lib/views/liked_tenders/pages/liked_tenders_tablet_page.dart b/lib/views/liked_tenders/pages/liked_tenders_tablet_page.dart index 15c3489..e01792b 100644 --- a/lib/views/liked_tenders/pages/liked_tenders_tablet_page.dart +++ b/lib/views/liked_tenders/pages/liked_tenders_tablet_page.dart @@ -26,6 +26,23 @@ class _LikedTendersTabletPageState extends State { void initState() { viewModel = context.read(); super.initState(); + viewModel.addListener(_viewModelListener); + } + + void _viewModelListener() { + if (viewModel.approvalErrorMessage?.isNotEmpty == true && + viewModel.approvalStatus == false) { + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(viewModel.approvalErrorMessage!))); + viewModel.clearApprovalErrorMessage(); + } + } + + @override + void dispose() { + viewModel.removeListener(_viewModelListener); + super.dispose(); } @override