diff --git a/lib/view_models/liked_tenders_view_model.dart b/lib/view_models/liked_tenders_view_model.dart index 6370122..55c5b05 100644 --- a/lib/view_models/liked_tenders_view_model.dart +++ b/lib/view_models/liked_tenders_view_model.dart @@ -6,6 +6,8 @@ import 'package:tm_app/data/services/model/liked_tender_feedback/liked_tender_fe import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart'; import '../data/services/model/feedback_response/feedback_response.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 LikedTendersViewModel with ChangeNotifier { final LikedTendersRepository _likedTendersRepository; @@ -21,6 +23,11 @@ class LikedTendersViewModel with ChangeNotifier { bool hasMore = true; String? errorMessage; LikedTendersResponse? data; + TenderApprovalsData? _tenderApprovalData; + + TenderApprovalsData? get tenderApprovalData => _tenderApprovalData; + + List tenderApprovals = []; int _offset = 0; final int _limit = 7; @@ -60,6 +67,10 @@ class LikedTendersViewModel with ChangeNotifier { final incoming = result.value; final incomingList = incoming.data?.feedback ?? []; + for (var element in incomingList) { + await getTenderApproval(element.tenderId!); + } + if (reset) { data = incoming; } else { @@ -151,4 +162,98 @@ class LikedTendersViewModel with ChangeNotifier { notifyListeners(); } + + Future getTenderApproval(String tenderId) async { + errorMessage = null; + notifyListeners(); + + final result = await _tendersRepository.getTenderApprovals( + tenderId: tenderId, + ); + + switch (result) { + case Ok(): + _tenderApprovalData = result.value.data; + tenderApprovals.add(_tenderApprovalData!); + break; + case Error(): + errorMessage = result.error.toString(); + break; + } + + notifyListeners(); + errorMessage = null; + notifyListeners(); + } + + TenderApprovalsData? getApprovalStatusForTender(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); + } + + // Future submitTenderApproval({ + // required String tenderId, + // required String submissionMode, + // }) async { + + // errorMessage = null; + // notifyListeners(); + // final result = await _tendersRepository.toggleApprovals( + // tenderId: tenderId, + // status: 'submitted', + // submissionMode: submissionMode, + // ); + // switch (result) { + // case Ok(): + // approvalStatus = true; + // _status = result.value.data?.status ?? ''; + // break; + // case Error(): + // _errorMessage = result.error.toString(); + // approvalStatus = false; + // break; + // } + // _isSubmitApprovalLoading = false; + // notifyListeners(); + // _errorMessage = null; + // approvalStatus = false; + // notifyListeners(); + // } + + // Future rejectTenderApproval({ + // required String tenderId, + // required String submissionMode, + // }) async { + // _isRejectApprovalLoading = true; + // _errorMessage = null; + // notifyListeners(); + // final result = await _tendersRepository.toggleApprovals( + // tenderId: tenderId, + // status: 'rejected', + // submissionMode: submissionMode, + // ); + // switch (result) { + // case Ok(): + // approvalStatus = true; + // _status = result.value.data?.status ?? ''; + // break; + // case Error(): + // _errorMessage = result.error.toString(); + // approvalStatus = false; + // break; + // } + // _isRejectApprovalLoading = false; + // notifyListeners(); + // _errorMessage = null; + // approvalStatus = false; + // notifyListeners(); + // } } diff --git a/lib/views/detail/pages/detail_mobile_page.dart b/lib/views/detail/pages/detail_mobile_page.dart index 567771f..a2b18e7 100644 --- a/lib/views/detail/pages/detail_mobile_page.dart +++ b/lib/views/detail/pages/detail_mobile_page.dart @@ -119,7 +119,10 @@ class _TenderDetailMobilePageState extends State { return SingleChildScrollView( child: Padding( - padding: const EdgeInsets.all(16.0), + padding: EdgeInsets.symmetric( + horizontal: 16.0.w(), + vertical: 16.0.h(), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/views/home/pages/d_home_page.dart b/lib/views/home/pages/d_home_page.dart index 409aa74..d121f33 100644 --- a/lib/views/home/pages/d_home_page.dart +++ b/lib/views/home/pages/d_home_page.dart @@ -174,7 +174,7 @@ class DesktopHomePage extends StatelessWidget { backgroundColor: AppColors.orange10, iconPath: AssetsManager.shield, title: HomeStrings.tenderValue, - amount: '3', + amount: '0', textColor: AppColors.orange, enableTap: true, width: 178, diff --git a/lib/views/home/pages/m_home_page.dart b/lib/views/home/pages/m_home_page.dart index db6e7e7..20aad8e 100644 --- a/lib/views/home/pages/m_home_page.dart +++ b/lib/views/home/pages/m_home_page.dart @@ -139,7 +139,7 @@ class MobileHomePage extends StatelessWidget { backgroundColor: AppColors.orange10, iconPath: AssetsManager.shield, title: HomeStrings.tenderValue, - amount: '3', + amount: '0', textColor: AppColors.orange, enableTap: true, onTap: () {}, diff --git a/lib/views/home/pages/t_home_page.dart b/lib/views/home/pages/t_home_page.dart index a1e598c..239b469 100644 --- a/lib/views/home/pages/t_home_page.dart +++ b/lib/views/home/pages/t_home_page.dart @@ -81,7 +81,7 @@ class TabletHomePage extends StatelessWidget { homeViewModel.tenderApprovalsStateResponse!, ), SizedBox(height: 8.0.h()), - _secondTenderCardsRow(homeViewModel,context), + _secondTenderCardsRow(homeViewModel, context), SizedBox(height: 32.0.h()), _yourTenderText(homeViewModel), SizedBox(height: 8.0.h()), @@ -185,7 +185,7 @@ class TabletHomePage extends StatelessWidget { backgroundColor: AppColors.orange10, iconPath: AssetsManager.shield, title: HomeStrings.tenderValue, - amount: '3', + amount: '0', textColor: AppColors.orange, enableTap: true, width: double.infinity, 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 6759750..8c697ab 100644 --- a/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart +++ b/lib/views/liked_tenders/pages/liked_tenders_desktop_page.dart @@ -4,6 +4,7 @@ import 'package:provider/provider.dart'; import 'package:tm_app/core/constants/assets.dart'; import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/utils/size_config.dart'; +import 'package:tm_app/data/services/model/tender_approvals_data/tender_approvals_data.dart'; import 'package:tm_app/view_models/liked_tenders_view_model.dart'; import 'package:tm_app/views/liked_tenders/widgets/liked_tenders_list_item.dart'; @@ -84,11 +85,42 @@ class _LikedTendersDesktopPageState extends State { itemCount: feedback.length, itemBuilder: (context, index) { 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: LikedListItem( - tender: item.tender!, - isDesktop: true, + 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, + ), + ), + onDismissed: (_) { + if (item.tenderId != null) { + viewModel.removeTenderById( + item.tenderId!, + ); + } + }, + child: LikedListItem( + tender: item.tender!, + approval: approval, + isDesktop: true, + ), ), ); }, 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 71991eb..e727c63 100644 --- a/lib/views/liked_tenders/pages/liked_tenders_mobile_page.dart +++ b/lib/views/liked_tenders/pages/liked_tenders_mobile_page.dart @@ -4,6 +4,7 @@ import 'package:provider/provider.dart'; import 'package:tm_app/core/constants/assets.dart'; import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/utils/size_config.dart'; +import 'package:tm_app/data/services/model/tender_approvals_data/tender_approvals_data.dart'; import 'package:tm_app/view_models/liked_tenders_view_model.dart'; import 'package:tm_app/views/liked_tenders/strings/liked_tenders_strings.dart'; import 'package:tm_app/views/liked_tenders/widgets/liked_tenders_list_item.dart'; @@ -93,6 +94,18 @@ class _LikedTendersMobilePageState extends State { 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( @@ -110,7 +123,10 @@ class _LikedTendersMobilePageState extends State { viewModel.removeTenderById(item.tenderId!); } }, - child: LikedListItem(tender: item.tender!), + child: LikedListItem( + tender: item.tender!, + approval: approval, + ), ), ); } else { 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 b594e9a..f185b33 100644 --- a/lib/views/liked_tenders/pages/liked_tenders_tablet_page.dart +++ b/lib/views/liked_tenders/pages/liked_tenders_tablet_page.dart @@ -10,6 +10,7 @@ import 'package:tm_app/view_models/liked_tenders_view_model.dart'; import 'package:tm_app/views/liked_tenders/strings/liked_tenders_strings.dart'; import 'package:tm_app/views/liked_tenders/widgets/liked_tenders_list_item.dart'; +import '../../../data/services/model/tender_approvals_data/tender_approvals_data.dart'; import '../../shared/tablet_navigation_widget.dart'; import '../../shared/tender_app_bar.dart'; @@ -91,6 +92,17 @@ class _LikedTendersTabletPageState extends State { itemCount: feedback.length, itemBuilder: (context, index) { 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( @@ -113,7 +125,10 @@ class _LikedTendersTabletPageState extends State { ); } }, - child: LikedListItem(tender: item.tender!), + child: LikedListItem( + tender: item.tender!, + approval: approval!, + ), ), ); }, diff --git a/lib/views/liked_tenders/widgets/liked_tenders_list_item.dart b/lib/views/liked_tenders/widgets/liked_tenders_list_item.dart index 329fdeb..9eecb80 100644 --- a/lib/views/liked_tenders/widgets/liked_tenders_list_item.dart +++ b/lib/views/liked_tenders/widgets/liked_tenders_list_item.dart @@ -9,13 +9,18 @@ import 'package:tm_app/data/services/model/tender_data/tender_data.dart'; import 'package:tm_app/view_models/liked_tenders_view_model.dart'; import 'package:tm_app/views/home/strings/home_strings.dart'; +import '../../../data/services/model/tender_approvals_data/tender_approvals_data.dart'; + class LikedListItem extends StatelessWidget { const LikedListItem({ required this.tender, - super.key, + this.approval, this.isDesktop = false, + super.key, }); final TenderData tender; + final TenderApprovalsData? approval; + final bool isDesktop; @override @@ -36,83 +41,88 @@ class LikedListItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 10.0.h()), - isDesktop ? - Row( - children: [ - Expanded( - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 10.0.w(), - vertical: 5.0.h(), - ), - decoration: BoxDecoration( - color: AppColors.primary30, - borderRadius: BorderRadius.circular(4), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '${HomeStrings.tenderDeadline} :', - style: TextStyle( - fontSize: 15.0.sp(), - fontWeight: FontWeight.w500, - color: AppColors.textBlue, - ), + isDesktop + ? Row( + children: [ + Expanded( + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 10.0.w(), + vertical: 5.0.h(), ), - Text( - timeConvertor(tender.tenderDeadline!), - style: TextStyle( - fontSize: 14.0.sp(), - fontWeight: FontWeight.w500, - color: AppColors.grey80, - ), + decoration: BoxDecoration( + color: AppColors.primary30, + borderRadius: BorderRadius.circular(4), ), - ], + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '${HomeStrings.tenderDeadline} :', + style: TextStyle( + fontSize: 15.0.sp(), + fontWeight: FontWeight.w500, + color: AppColors.textBlue, + ), + ), + Text( + timeConvertor(tender.tenderDeadline!), + style: TextStyle( + fontSize: 14.0.sp(), + fontWeight: FontWeight.w500, + color: AppColors.grey80, + ), + ), + ], + ), + ), ), + SizedBox(width: 8.0.w()), + InkWell( + child: SvgPicture.asset( + AssetsManager.trash, + width: 32.0.w(), + height: 32.0.h(), + ), + onTap: () { + if (tender.id != null) { + viewModel.removeTenderById(tender.id!); + } + }, + ), + ], + ) + : Container( + padding: EdgeInsets.symmetric( + horizontal: 10.0.w(), + vertical: 5.0.h(), + ), + decoration: BoxDecoration( + color: AppColors.primary30, + borderRadius: BorderRadius.circular(4), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '${HomeStrings.tenderDeadline} :', + style: TextStyle( + fontSize: 15.0.sp(), + fontWeight: FontWeight.w500, + color: AppColors.textBlue, + ), + ), + Text( + timeConvertor(tender.tenderDeadline!), + style: TextStyle( + fontSize: 14.0.sp(), + fontWeight: FontWeight.w500, + color: AppColors.grey80, + ), + ), + ], ), ), - SizedBox(width: 8.0.w()), - InkWell( - child: SvgPicture.asset(AssetsManager.trash,width: 32.0.w(),height: 32.0.h(),), - onTap: () { - if (tender.id != null) { - viewModel.removeTenderById(tender.id!); - } - }, - ), - ], - ) : Container( - padding: EdgeInsets.symmetric( - horizontal: 10.0.w(), - vertical: 5.0.h(), - ), - decoration: BoxDecoration( - color: AppColors.primary30, - borderRadius: BorderRadius.circular(4), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '${HomeStrings.tenderDeadline} :', - style: TextStyle( - fontSize: 15.0.sp(), - fontWeight: FontWeight.w500, - color: AppColors.textBlue, - ), - ), - Text( - timeConvertor(tender.tenderDeadline!), - style: TextStyle( - fontSize: 14.0.sp(), - fontWeight: FontWeight.w500, - color: AppColors.grey80, - ), - ), - ], - ), - ), SizedBox(height: 12.0.h()), Text( tender.title!, @@ -167,10 +177,23 @@ class LikedListItem extends StatelessWidget { height: 32.0.h(), decoration: BoxDecoration( shape: BoxShape.circle, - border: Border.all(color: AppColors.grey60, width: 1.5.w()), + border: Border.all( + color: + approval?.status == 'rejected' + ? AppColors.errorColor + : AppColors.grey60, + width: 1.5.w(), + ), ), alignment: Alignment.center, - child: Icon(Icons.close, color: AppColors.grey60, size: 16), + child: Icon( + Icons.close, + color: + approval?.status == 'rejected' + ? AppColors.errorColor + : AppColors.grey60, + size: 16, + ), ), SizedBox(width: 30.0.w()), Container( @@ -178,10 +201,23 @@ class LikedListItem extends StatelessWidget { height: 32.0.h(), decoration: BoxDecoration( shape: BoxShape.circle, - border: Border.all(color: AppColors.grey60, width: 1.5.w()), + border: Border.all( + color: + approval?.status == 'submitted' + ? AppColors.successColor + : AppColors.grey60, + width: 1.5.w(), + ), ), alignment: Alignment.center, - child: Icon(Icons.check, color: AppColors.grey60, size: 16), + child: Icon( + Icons.check, + color: + approval?.status == 'submitted' + ? AppColors.successColor + : AppColors.grey60, + size: 16, + ), ), ], ),