From dd46eb605465bf933e72ab8d1c1b150329b6c3b0 Mon Sep 17 00:00:00 2001 From: amirrezaghabeli Date: Wed, 27 Aug 2025 13:22:35 +0330 Subject: [PATCH] refactor home --- .../routes/app_shell/app_shell_screen.dart | 3 + lib/core/theme/colors.dart | 1 + lib/data/repositories/tenders_repository.dart | 2 +- lib/view_models/home_view_model.dart | 23 +++ lib/view_models/tenders_view_model.dart | 4 +- lib/views/home/pages/d_home_page.dart | 159 ++++++++---------- lib/views/home/pages/m_home_page.dart | 43 ++--- lib/views/home/pages/t_home_page.dart | 106 +++++------- lib/views/home/progress_bar_column.dart | 2 +- lib/views/home/tender_card.dart | 3 +- lib/views/home/tenders_list_item.dart | 18 -- .../widgets/tender_action_buttons_row.dart | 7 +- 12 files changed, 169 insertions(+), 202 deletions(-) diff --git a/lib/core/routes/app_shell/app_shell_screen.dart b/lib/core/routes/app_shell/app_shell_screen.dart index d157f03..54b561f 100644 --- a/lib/core/routes/app_shell/app_shell_screen.dart +++ b/lib/core/routes/app_shell/app_shell_screen.dart @@ -13,6 +13,9 @@ class AppShellScreen extends StatelessWidget { final StatefulNavigationShell navigationShell; void _gotoBranch(int index, BuildContext context) { + if (index == navigationShell.currentIndex) { + return; + } navigationShell.goBranch( index, initialLocation: index == navigationShell.currentIndex, diff --git a/lib/core/theme/colors.dart b/lib/core/theme/colors.dart index 4407c30..0d87b8e 100644 --- a/lib/core/theme/colors.dart +++ b/lib/core/theme/colors.dart @@ -153,6 +153,7 @@ class AppColors { // static const Color red0 = Color(0xFF312F2F); // static const Color red10 = Color(0xFF524545); static const Color red = Color(0xFFFF3B30); + static const Color orange = Color(0xFFE5821E); // Other colors static const Color lightBlue = Color(0xFFe8ecfc); diff --git a/lib/data/repositories/tenders_repository.dart b/lib/data/repositories/tenders_repository.dart index a54a1f5..ed366af 100644 --- a/lib/data/repositories/tenders_repository.dart +++ b/lib/data/repositories/tenders_repository.dart @@ -24,7 +24,7 @@ class TendersRepository { return _tendersService.getTenderFeedback(tenderId: tenderId); } - Future> feedback({ + Future> toggleFeedback({ required String tenderId, required String feedbackType, }) async { diff --git a/lib/view_models/home_view_model.dart b/lib/view_models/home_view_model.dart index cc947f2..0eba9d9 100644 --- a/lib/view_models/home_view_model.dart +++ b/lib/view_models/home_view_model.dart @@ -165,4 +165,27 @@ class HomeViewModel with ChangeNotifier { _isLoading = false; notifyListeners(); } + + // Calculation methods for progress bars + double get partnershipCount { + return tenderApprovalsStateResponse?.data?.partnershipCount?.toDouble() ?? + 0.0; + } + + double get selfApplyCount { + return tenderApprovalsStateResponse?.data?.selfApplyCount?.toDouble() ?? + 0.0; + } + + double get totalCount { + return partnershipCount + selfApplyCount; + } + + double get partnershipPercent { + return totalCount > 0 ? (partnershipCount / totalCount) * 100 : 0; + } + + double get selfApplyPercent { + return totalCount > 0 ? (selfApplyCount / totalCount) * 100 : 0; + } } diff --git a/lib/view_models/tenders_view_model.dart b/lib/view_models/tenders_view_model.dart index af0a25a..24d6971 100644 --- a/lib/view_models/tenders_view_model.dart +++ b/lib/view_models/tenders_view_model.dart @@ -248,14 +248,14 @@ class TendersViewModel with ChangeNotifier { notifyListeners(); } - Future feedback({ + Future toogleFeedback({ required String tenderId, required String feedbackType, }) async { _feedbackErrorMessage = null; notifyListeners(); - final result = await _tendersRepository.feedback( + final result = await _tendersRepository.toggleFeedback( tenderId: tenderId, feedbackType: feedbackType, ); diff --git a/lib/views/home/pages/d_home_page.dart b/lib/views/home/pages/d_home_page.dart index f89dfd1..9c79fdc 100644 --- a/lib/views/home/pages/d_home_page.dart +++ b/lib/views/home/pages/d_home_page.dart @@ -6,7 +6,6 @@ import 'package:tm_app/core/constants/strings.dart'; import 'package:tm_app/core/routes/app_routes.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_state_response/tender_approvals_state_response.dart'; import 'package:tm_app/view_models/home_view_model.dart'; import 'package:tm_app/views/shared/desktop_navigation_widget.dart'; @@ -30,111 +29,99 @@ class DesktopHomePage extends StatelessWidget { return Center(child: Text(homeViewModel.errorMessage!)); } - return Column( - children: [ - DesktopNavigationWidget( - currentIndex: 0, // Home index - onTabChanged: (index) { - // Navigate to different screens based on index - switch (index) { - case 0: - // Already on home - break; - case 1: - // Navigate to tenders - Router.neglect(context, () => context.go('/tenders')); - break; - case 2: - // Navigate to profile - Router.neglect(context, () => context.go('/profile')); - break; - } - }, - ), - Expanded( - child: Center( - child: SizedBox( - width: 780, - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox(height: 55), - // SizedBox(width: 780, child: NotificationCard()), - SizedBox(height: 40.0), - _progressBarsRow( - homeViewModel.tenderApprovalsStateResponse!, - ), - SizedBox(height: 32.0.h()), - Padding( - padding: EdgeInsets.symmetric(horizontal: 15.0.w()), - child: _firstTenderCardsRow( - context, - homeViewModel.tenderApprovalsStateResponse!, - homeViewModel, + if (homeViewModel.tenderApprovalsStateResponse != null && + homeViewModel.data != null && + homeViewModel.feedbackStats != null) { + return Column( + children: [ + DesktopNavigationWidget( + currentIndex: 0, // Home index + onTabChanged: (index) { + // Navigate to different screens based on index + switch (index) { + case 0: + // Already on home + break; + case 1: + // Navigate to tenders + Router.neglect(context, () => context.go('/tenders')); + break; + case 2: + // Navigate to profile + Router.neglect(context, () => context.go('/profile')); + break; + } + }, + ), + Expanded( + child: Center( + child: SizedBox( + width: 780, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: 55), + // SizedBox(width: 780, child: NotificationCard()), + SizedBox(height: 40.0), + _progressBarsRow(homeViewModel), + SizedBox(height: 32.0.h()), + Padding( + padding: EdgeInsets.symmetric( + horizontal: 15.0.w(), + ), + child: _firstTenderCardsRow( + context, + homeViewModel, + ), ), - ), - SizedBox(height: 32.0.h()), - _yourTenderText(homeViewModel), - SizedBox(height: 8.0.h()), - _bottomListView(homeViewModel), - ], + SizedBox(height: 32.0.h()), + _yourTenderText(homeViewModel), + SizedBox(height: 8.0.h()), + _bottomListView(homeViewModel), + ], + ), ), ), ), ), - ), - ], + ], + ); + } + return const Center( + child: CircularProgressIndicator(color: AppColors.secondary50), ); }, ), ); } - Widget _progressBarsRow( - TenderApprovalsStateResponse tenderApprovalsStateResponse, - ) { - final partnership = - tenderApprovalsStateResponse.data!.partnershipCount ?? 0; - final selfApply = tenderApprovalsStateResponse.data!.selfApplyCount ?? 0; - final total = (partnership + selfApply); - - final partnershipPercent = total > 0 ? (partnership / total) * 100 : 0; - final selfApplyPercent = total > 0 ? (selfApply / total) * 100 : 0; + Widget _progressBarsRow(HomeViewModel homeViewModel) { return Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.center, children: [ ProgressBarColumn( text: AppStrings.partnership, - value: double.parse('$partnershipPercent'), - amount: double.parse('$partnershipPercent').toString(), + value: homeViewModel.partnershipPercent, + amount: homeViewModel.partnershipPercent.toString(), circularProgressIndicatorWidth: 176, circularProgressIndicatorHeight: 176, ), SizedBox(width: 106), ProgressBarColumn( text: AppStrings.selfApply, - value: double.parse(selfApplyPercent.toString()), - amount: double.parse(selfApplyPercent.toString()).toString(), + value: homeViewModel.selfApplyPercent, + amount: homeViewModel.selfApplyPercent.toString(), circularProgressIndicatorWidth: 176, circularProgressIndicatorHeight: 176, ), - //SizedBox(width: 106), - // ProgressBarColumn( - // text: AppStrings.contracting, - // value: double.parse(homeResponse.contracting ?? '0'), - // amount: homeResponse.contracting ?? '0', - // circularProgressIndicatorWidth: 176, - // circularProgressIndicatorHeight: 176, - // ), ], ); } Widget _firstTenderCardsRow( BuildContext context, - TenderApprovalsStateResponse tenderApprovalsStateResponse, HomeViewModel homeViewModel, ) { return Row( @@ -143,16 +130,16 @@ class DesktopHomePage extends StatelessWidget { Expanded( child: TenderCard( backgroundColor: AppColors.primary20, - iconPath: 'assets/icons/arrows.svg', + iconPath: AssetsManager.arrows, title: AppStrings.tenderSubmitted, amount: - tenderApprovalsStateResponse.data!.submittedTenders.toString(), - // tenderApprovalsStateResponse - // .data! - // .approvalsBySubmission! - // .selfApply - // .toString(), - textColor: Color(0xFF0164FF), + homeViewModel + .tenderApprovalsStateResponse! + .data! + .submittedTenders + .toString(), + + textColor: AppColors.mainBlue, enableTap: true, width: 178, height: 148, @@ -168,7 +155,7 @@ class DesktopHomePage extends StatelessWidget { iconPath: AssetsManager.approve, title: AppStrings.approvedTenders, amount: '0', - textColor: Color(0xFF24848E), + textColor: AppColors.jellyBean, enableTap: true, width: 178, height: 148, @@ -180,10 +167,10 @@ class DesktopHomePage extends StatelessWidget { SizedBox(width: 10), TenderCard( backgroundColor: AppColors.orange10, - iconPath: 'assets/icons/shield.svg', + iconPath: AssetsManager.shield, title: AppStrings.tenderValue, amount: '3', - textColor: Color(0xFFE5821E), + textColor: AppColors.orange, enableTap: true, width: 178, height: 148, @@ -195,7 +182,7 @@ class DesktopHomePage extends StatelessWidget { iconPath: AssetsManager.thumbLike, title: AppStrings.likedTenders, amount: homeViewModel.feedbackStats?.totalLikes.toString() ?? '0', - textColor: Color(0xFF9E9E9E), + textColor: AppColors.grey80, enableTap: false, width: 178, height: 148, diff --git a/lib/views/home/pages/m_home_page.dart b/lib/views/home/pages/m_home_page.dart index 194c95e..0c41598 100644 --- a/lib/views/home/pages/m_home_page.dart +++ b/lib/views/home/pages/m_home_page.dart @@ -31,7 +31,8 @@ class MobileHomePage extends StatelessWidget { } if (homeViewModel.tenderApprovalsStateResponse != null && - homeViewModel.data != null) { + homeViewModel.data != null && + homeViewModel.feedbackStats != null) { return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -39,7 +40,7 @@ class MobileHomePage extends StatelessWidget { // SizedBox(height: 18.0.h()), // NotificationCard(), SizedBox(height: 32.0.h()), - _progressBarsRow(homeViewModel.tenderApprovalsStateResponse!), + _progressBarsRow(homeViewModel), SizedBox(height: 32.0.h()), _firstTenderCardsRow( context, @@ -62,17 +63,7 @@ class MobileHomePage extends StatelessWidget { ); } - Widget _progressBarsRow( - TenderApprovalsStateResponse tenderApprovalsStateResponse, - ) { - final partnership = - tenderApprovalsStateResponse.data!.partnershipCount ?? 0; - final selfApply = tenderApprovalsStateResponse.data!.selfApplyCount ?? 0; - final total = (partnership + selfApply); - - final partnershipPercent = total > 0 ? (partnership / total) * 100 : 0; - final selfApplyPercent = total > 0 ? (selfApply / total) * 100 : 0; - + Widget _progressBarsRow(HomeViewModel homeViewModel) { return Padding( padding: EdgeInsets.symmetric(horizontal: 24.0.w()), child: Row( @@ -81,22 +72,17 @@ class MobileHomePage extends StatelessWidget { SizedBox(width: 20.0.w()), ProgressBarColumn( text: AppStrings.partnership, - value: double.parse('$partnershipPercent'), - amount: double.parse('$partnershipPercent').toString(), + value: homeViewModel.partnershipPercent, + amount: homeViewModel.partnershipPercent.toString(), ), Spacer(), ProgressBarColumn( text: AppStrings.selfApply, - value: double.parse(selfApplyPercent.toString()), - amount: double.parse(selfApplyPercent.toString()).toString(), + value: homeViewModel.selfApplyPercent, + amount: homeViewModel.selfApplyPercent.toString(), ), SizedBox(width: 20.0.w()), Spacer(), - // ProgressBarColumn( - // text: AppStrings.contracting, - // value: double.parse(tenderApprovalsStateResponse.data.contracting ?? '0'), - // amount: tenderApprovalsStateResponse.data.contracting ?? '0', - // ), ], ), ); @@ -117,12 +103,7 @@ class MobileHomePage extends StatelessWidget { title: AppStrings.tenderSubmitted, amount: tenderApprovalsStateResponse.data!.submittedTenders.toString(), - // tenderApprovalsStateResponse - // .data! - // .approvalsBySubmission! - // .selfApply - // .toString(), - textColor: Color(0xFF0164FF), + textColor: AppColors.mainBlue, enableTap: true, onTap: () { YourTendersRouteData().push(context); @@ -134,7 +115,7 @@ class MobileHomePage extends StatelessWidget { title: AppStrings.approvedTenders, amount: '0', - textColor: Color(0xFF24848E), + textColor: AppColors.jellyBean, enableTap: true, onTap: () { YourTendersRouteData().push(context); @@ -157,7 +138,7 @@ class MobileHomePage extends StatelessWidget { iconPath: AssetsManager.shield, title: AppStrings.tenderValue, amount: '3', - textColor: Color(0xFFE5821E), + textColor: AppColors.orange, enableTap: true, onTap: () {}, ), @@ -166,7 +147,7 @@ class MobileHomePage extends StatelessWidget { iconPath: AssetsManager.thumbLike, title: AppStrings.likedTenders, amount: homeViewModel.feedbackStats?.totalLikes.toString() ?? '0', - textColor: Color(0xFF9E9E9E), + textColor: AppColors.grey80, enableTap: false, onTap: () {}, ), diff --git a/lib/views/home/pages/t_home_page.dart b/lib/views/home/pages/t_home_page.dart index 38547e5..22aa5b4 100644 --- a/lib/views/home/pages/t_home_page.dart +++ b/lib/views/home/pages/t_home_page.dart @@ -81,58 +81,56 @@ class TabletHomePage extends StatelessWidget { return Center(child: Text(homeViewModel.errorMessage!)); } - return SingleChildScrollView( - child: Padding( - padding: EdgeInsetsDirectional.fromSTEB( - 24.0.w(), - 24.0.h(), - 24.0.w(), - 24.0.h(), + if (homeViewModel.tenderApprovalsStateResponse != null && + homeViewModel.data != null && + homeViewModel.feedbackStats != null) { + return SingleChildScrollView( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 24.0.w(), + 24.0.h(), + 24.0.w(), + 24.0.h(), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // NotificationCard(), + SizedBox(height: 40.0.h()), + _progressBarsRow(homeViewModel), + SizedBox(height: 32.0.h()), + _firstTenderCardsRow( + context, + homeViewModel.tenderApprovalsStateResponse!, + ), + SizedBox(height: 8.0.h()), + _secondTenderCardsRow(homeViewModel), + SizedBox(height: 32.0.h()), + _yourTenderText(homeViewModel), + SizedBox(height: 8.0.h()), + _bottomListView(homeViewModel), + ], + ), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // NotificationCard(), - SizedBox(height: 40.0.h()), - _progressBarsRow(homeViewModel.tenderApprovalsStateResponse!), - SizedBox(height: 32.0.h()), - _firstTenderCardsRow( - context, - homeViewModel.tenderApprovalsStateResponse!, - ), - SizedBox(height: 8.0.h()), - _secondTenderCardsRow(homeViewModel), - SizedBox(height: 32.0.h()), - _yourTenderText(homeViewModel), - SizedBox(height: 8.0.h()), - _bottomListView(homeViewModel), - ], - ), - ), + ); + } + return const Center( + child: CircularProgressIndicator(color: AppColors.secondary50), ); }, ), ); } - Widget _progressBarsRow( - TenderApprovalsStateResponse tenderApprovalsStateResponse, - ) { - final partnership = - tenderApprovalsStateResponse.data!.partnershipCount ?? 0; - final selfApply = tenderApprovalsStateResponse.data!.selfApplyCount ?? 0; - final total = (partnership + selfApply); - - final partnershipPercent = total > 0 ? (partnership / total) * 100 : 0; - final selfApplyPercent = total > 0 ? (selfApply / total) * 100 : 0; + Widget _progressBarsRow(HomeViewModel homeViewModel) { return Row( children: [ Spacer(), SizedBox(width: 20.0.w()), ProgressBarColumn( text: AppStrings.partnership, - value: double.parse('$partnershipPercent'), - amount: double.parse('$partnershipPercent').toString(), + value: homeViewModel.partnershipPercent, + amount: homeViewModel.partnershipPercent.toString(), circularProgressIndicatorWidth: 176.0, circularProgressIndicatorHeight: 176.0, strokeWidth: 8.0, @@ -140,22 +138,14 @@ class TabletHomePage extends StatelessWidget { Spacer(), ProgressBarColumn( text: AppStrings.selfApply, - value: double.parse(selfApplyPercent.toString()), - amount: double.parse(selfApplyPercent.toString()).toString(), + value: homeViewModel.selfApplyPercent, + amount: homeViewModel.selfApplyPercent.toString(), circularProgressIndicatorWidth: 176.0, circularProgressIndicatorHeight: 176.0, strokeWidth: 8.0, ), SizedBox(width: 20.0.w()), Spacer(), - // ProgressBarColumn( - // text: AppStrings.contracting, - // value: double.parse(homeResponse.contracting ?? '0'), - // amount: homeResponse.contracting ?? '0', - // circularProgressIndicatorWidth: 176.0, - // circularProgressIndicatorHeight: 176.0, - // strokeWidth: 8.0, - // ), ], ); } @@ -170,16 +160,12 @@ class TabletHomePage extends StatelessWidget { Expanded( child: TenderCard( backgroundColor: AppColors.primary20, - iconPath: 'assets/icons/arrows.svg', + iconPath: AssetsManager.arrows, title: AppStrings.tenderSubmitted, amount: tenderApprovalsStateResponse.data!.submittedTenders.toString(), - // tenderApprovalsStateResponse - // .data! - // .approvalsBySubmission! - // .selfApply - // .toString(), - textColor: Color(0xFF0164FF), + + textColor: AppColors.mainBlue, enableTap: true, width: double.infinity, height: 148, @@ -196,7 +182,7 @@ class TabletHomePage extends StatelessWidget { title: AppStrings.approvedTenders, amount: '0', - textColor: Color(0xFF24848E), + textColor: AppColors.jellyBean, enableTap: true, width: double.infinity, height: 148, @@ -217,10 +203,10 @@ class TabletHomePage extends StatelessWidget { Expanded( child: TenderCard( backgroundColor: AppColors.orange10, - iconPath: 'assets/icons/shield.svg', + iconPath: AssetsManager.shield, title: AppStrings.tenderValue, amount: '3', - textColor: Color(0xFFE5821E), + textColor: AppColors.orange, enableTap: true, width: double.infinity, height: 148, @@ -234,7 +220,7 @@ class TabletHomePage extends StatelessWidget { iconPath: AssetsManager.thumbLike, title: AppStrings.likedTenders, amount: homeViewModel.feedbackStats?.totalLikes.toString() ?? '0', - textColor: Color(0xFF9E9E9E), + textColor: AppColors.grey80, enableTap: false, width: double.infinity, height: 148, diff --git a/lib/views/home/progress_bar_column.dart b/lib/views/home/progress_bar_column.dart index d57ec15..4a799a0 100644 --- a/lib/views/home/progress_bar_column.dart +++ b/lib/views/home/progress_bar_column.dart @@ -78,7 +78,7 @@ class _ProgressBarColumnState extends State animation: _animation, builder: (context, child) => CircularProgressIndicator( - backgroundColor: Color(0xFFE1E1E1), + backgroundColor: AppColors.grey10, strokeCap: StrokeCap.round, strokeWidth: widget.strokeWidth ?? 6.0, valueColor: AlwaysStoppedAnimation(AppColors.jellyBean), diff --git a/lib/views/home/tender_card.dart b/lib/views/home/tender_card.dart index 1b23f49..a9e1be1 100644 --- a/lib/views/home/tender_card.dart +++ b/lib/views/home/tender_card.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import '../../core/constants/assets.dart'; +import '../../core/theme/colors.dart'; import '../../core/utils/size_config.dart'; class TenderCard extends StatelessWidget { @@ -50,7 +51,7 @@ class TenderCard extends StatelessWidget { style: TextStyle( fontSize: 16.0.sp(), fontWeight: FontWeight.bold, - color: Color(0xFF777777), + color: AppColors.grey80, ), ), Spacer(), diff --git a/lib/views/home/tenders_list_item.dart b/lib/views/home/tenders_list_item.dart index e9f3d42..1a5fee9 100644 --- a/lib/views/home/tenders_list_item.dart +++ b/lib/views/home/tenders_list_item.dart @@ -97,7 +97,6 @@ class TendersListItem extends StatelessWidget { ), ), Spacer(), - // SizedBox(height: 18.0.h()), TenderCardProgressBar(), SizedBox(height: 15.0.h()), @@ -123,23 +122,6 @@ class TendersListItem extends StatelessWidget { ), ), Spacer(), - // Container( - // width: 96.0.w(), - // height: 24.0.h(), - // decoration: BoxDecoration( - // color: AppColors.grey30, - // borderRadius: BorderRadius.circular(88), - // ), - // alignment: Alignment.center, - // child: Text( - // 'tender.type', - // style: TextStyle( - // fontSize: 12.0.sp(), - // fontWeight: FontWeight.w500, - // color: AppColors.grey60, - // ), - // ), - // ), ], ), ], diff --git a/lib/views/tenders/widgets/tender_action_buttons_row.dart b/lib/views/tenders/widgets/tender_action_buttons_row.dart index f58dc5e..725a39e 100644 --- a/lib/views/tenders/widgets/tender_action_buttons_row.dart +++ b/lib/views/tenders/widgets/tender_action_buttons_row.dart @@ -207,7 +207,10 @@ class TenderActionButtonsRow extends StatelessWidget { child: InkWell( splashColor: Colors.transparent, onTap: () { - viewModel.feedback(tenderId: tender.id!, feedbackType: 'dislike'); + viewModel.toogleFeedback( + tenderId: tender.id!, + feedbackType: 'dislike', + ); }, child: Column( children: [ @@ -251,7 +254,7 @@ class TenderActionButtonsRow extends StatelessWidget { child: InkWell( splashColor: Colors.transparent, onTap: () { - viewModel.feedback(tenderId: tender.id!, feedbackType: 'like'); + viewModel.toogleFeedback(tenderId: tender.id!, feedbackType: 'like'); }, child: Column( children: [