some changes and fixes

This commit is contained in:
amirrezaghabeli
2025-09-06 13:18:12 +03:30
parent 2fbd8018c8
commit 5649634464
24 changed files with 691 additions and 815 deletions
+1
View File
@@ -122,6 +122,7 @@ List<SingleChildWidget> get viewModels {
(context) => LikedTendersViewModel( (context) => LikedTendersViewModel(
likedTendersRepository: context.read(), likedTendersRepository: context.read(),
tendersRepository: context.read(), tendersRepository: context.read(),
homeViewModel: context.read(),
), ),
), ),
ChangeNotifierProvider( ChangeNotifierProvider(
@@ -5,6 +5,7 @@ import 'package:tm_app/data/repositories/tenders_repository.dart';
import 'package:tm_app/data/services/model/liked_tender_feedback/liked_tender_feedback.dart'; import 'package:tm_app/data/services/model/liked_tender_feedback/liked_tender_feedback.dart';
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart'; import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
import 'package:tm_app/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart'; import 'package:tm_app/data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
import 'package:tm_app/view_models/home_view_model.dart';
import '../data/services/model/feedback_response/feedback_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_by_id_response/tender_approvals_by_id_response.dart';
@@ -13,10 +14,13 @@ import '../data/services/model/tender_approvals_data/tender_approvals_data.dart'
class LikedTendersViewModel with ChangeNotifier { class LikedTendersViewModel with ChangeNotifier {
final LikedTendersRepository _likedTendersRepository; final LikedTendersRepository _likedTendersRepository;
final TendersRepository _tendersRepository; final TendersRepository _tendersRepository;
final HomeViewModel _homeViewModel;
LikedTendersViewModel({ LikedTendersViewModel({
required LikedTendersRepository likedTendersRepository, required LikedTendersRepository likedTendersRepository,
required TendersRepository tendersRepository, required TendersRepository tendersRepository,
required HomeViewModel homeViewModel,
}) : _likedTendersRepository = likedTendersRepository, }) : _likedTendersRepository = likedTendersRepository,
_homeViewModel = homeViewModel,
_tendersRepository = tendersRepository; _tendersRepository = tendersRepository;
bool isLoading = false; bool isLoading = false;
@@ -47,6 +51,10 @@ class LikedTendersViewModel with ChangeNotifier {
bool get isSubmitApprovalLoading => _isSubmitApprovalLoading; bool get isSubmitApprovalLoading => _isSubmitApprovalLoading;
bool get isRejectApprovalLoading => _isRejectApprovalLoading; bool get isRejectApprovalLoading => _isRejectApprovalLoading;
void updateHome() {
_homeViewModel.init();
}
Future<void> getLikedTenders({bool reset = false}) async { Future<void> getLikedTenders({bool reset = false}) async {
if (!reset && (isLoadingMore || !hasMore)) { if (!reset && (isLoadingMore || !hasMore)) {
return; return;
@@ -7,7 +7,6 @@ import 'package:tm_app/views/detail/widgets/tender_detail_action.dart';
import 'package:tm_app/views/detail/widgets/tender_detail_card.dart'; import 'package:tm_app/views/detail/widgets/tender_detail_card.dart';
import 'package:tm_app/views/detail/widgets/tender_detail_header.dart'; import 'package:tm_app/views/detail/widgets/tender_detail_header.dart';
import '../../../core/routes/app_routes.dart';
import '../../shared/desktop_navigation_widget.dart'; import '../../shared/desktop_navigation_widget.dart';
import '../strings/tender_details_strings.dart'; import '../strings/tender_details_strings.dart';
@@ -115,27 +114,6 @@ class _TenderDetailDesktopPageState extends State<TenderDetailDesktopPage> {
children: [ children: [
DesktopNavigationWidget( DesktopNavigationWidget(
currentIndex: 1, // Home index currentIndex: 1, // Home index
onTabChanged: (index) {
// Navigate to different screens based on index
switch (index) {
case 0:
Router.neglect(
context,
() => HomeRouteData().go(context),
);
viewModel.updateHome();
break;
case 1:
break;
case 2:
// Navigate to profile
Router.neglect(
context,
() => ProfileRouteData().go(context),
);
break;
}
},
), ),
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
@@ -1,6 +1,5 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
@@ -10,7 +9,6 @@ import 'package:tm_app/views/detail/widgets/tender_detail_card.dart';
import 'package:tm_app/views/detail/widgets/tender_detail_header.dart'; import 'package:tm_app/views/detail/widgets/tender_detail_header.dart';
import 'package:tm_app/views/shared/tablet_navigation_widget.dart'; import 'package:tm_app/views/shared/tablet_navigation_widget.dart';
import '../../../core/routes/app_routes.dart';
import '../../shared/tender_app_bar.dart'; import '../../shared/tender_app_bar.dart';
import '../strings/tender_details_strings.dart'; import '../strings/tender_details_strings.dart';
@@ -105,22 +103,6 @@ class _TenderDetailTabletPageState extends State<TenderDetailTabletPage> {
drawer: TabletNavigationWidget( drawer: TabletNavigationWidget(
currentIndex: 1, // Home is index 0 currentIndex: 1, // Home is index 0
onTabChanged: (index) {
// Handle navigation to other tabs
switch (index) {
case 0:
Router.neglect(context, () => HomeRouteData().go(context));
viewModel.updateHome();
break;
case 1:
break;
case 2:
// Navigate to profile
context.pop();
Router.neglect(context, () => ProfileRouteData().go(context));
break;
}
},
), ),
body: Consumer<TenderDetailViewModel>( body: Consumer<TenderDetailViewModel>(
builder: (context, tenderViewModel, child) { builder: (context, tenderViewModel, child) {
@@ -162,19 +162,33 @@ class TenderDetailActions extends StatelessWidget {
submissionMode: 'self-apply', submissionMode: 'self-apply',
); );
} else { } else {
showDialog( (MediaQuery.sizeOf(context).width > 600)
context: context, ? showDialog(
builder: (context) { context: context,
return SelectSubmissionDialog( builder: (context) {
onConfirm: (String value) { return SelectSubmissionDialog(
viewModel.submitTenderApproval( onConfirm: (String value) {
tenderId: detail.id!, viewModel.submitTenderApproval(
submissionMode: value, tenderId: detail.id!,
submissionMode: value,
);
},
);
},
)
: showModalBottomSheet(
context: context,
builder: (context) {
return SelectSubmissionBottomSheet(
onConfirm: (String value) {
viewModel.submitTenderApproval(
tenderId: detail.id!,
submissionMode: value,
);
},
); );
}, },
); );
},
);
} }
}, },
width: 120.0.w(), width: 120.0.w(),
+26 -57
View File
@@ -31,66 +31,35 @@ class DesktopHomePage extends StatelessWidget {
if (homeViewModel.tenderApprovalsStateResponse != null && if (homeViewModel.tenderApprovalsStateResponse != null &&
homeViewModel.data != null && homeViewModel.data != null &&
homeViewModel.feedbackStats != null) { homeViewModel.feedbackStats != null) {
return Column( return SingleChildScrollView(
children: [ child: Column(
DesktopNavigationWidget( children: [
currentIndex: 0, // Home index DesktopNavigationWidget(
onTabChanged: (index) { currentIndex: 0, // Home index
// Navigate to different screens based on index ),
switch (index) { SizedBox(
case 0: width: 780,
// Already on home child: Column(
break; crossAxisAlignment: CrossAxisAlignment.center,
case 1: children: [
// Navigate to tenders SizedBox(height: 55),
Router.neglect( // SizedBox(width: 780, child: NotificationCard()),
context, SizedBox(height: 40.0),
() => TendersRouteData().go(context), _progressBarsRow(homeViewModel),
); SizedBox(height: 32.0.h()),
break; Padding(
case 2: padding: EdgeInsets.symmetric(horizontal: 15.0.w()),
// Navigate to profile child: _firstTenderCardsRow(context, homeViewModel),
Router.neglect(
context,
() => ProfileRouteData().go(context),
);
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( return const Center(
-19
View File
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tm_app/core/routes/app_routes.dart'; import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
@@ -27,24 +26,6 @@ class TabletHomePage extends StatelessWidget {
drawer: TabletNavigationWidget( drawer: TabletNavigationWidget(
currentIndex: 0, // Home is index 0 currentIndex: 0, // Home is index 0
onTabChanged: (index) {
// Handle navigation to other tabs
switch (index) {
case 0:
// Already on home
break;
case 1:
// Navigate to tenders
context.pop();
Router.neglect(context, () => TendersRouteData().go(context));
break;
case 2:
// Navigate to profile
context.pop();
Router.neglect(context, () => ProfileRouteData().go(context));
break;
}
},
), ),
body: Consumer<HomeViewModel>( body: Consumer<HomeViewModel>(
builder: (context, homeViewModel, child) { builder: (context, homeViewModel, child) {
@@ -8,8 +8,8 @@ import 'package:tm_app/data/services/model/tender_approvals_data/tender_approval
import 'package:tm_app/view_models/liked_tenders_view_model.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'; import 'package:tm_app/views/liked_tenders/widgets/liked_tenders_list_item.dart';
import '../../../core/routes/app_routes.dart';
import '../../shared/desktop_navigation_widget.dart'; import '../../shared/desktop_navigation_widget.dart';
import '../strings/liked_tenders_strings.dart';
class LikedTendersDesktopPage extends StatefulWidget { class LikedTendersDesktopPage extends StatefulWidget {
const LikedTendersDesktopPage({super.key}); const LikedTendersDesktopPage({super.key});
@@ -20,220 +20,221 @@ class LikedTendersDesktopPage extends StatefulWidget {
} }
class _LikedTendersDesktopPageState extends State<LikedTendersDesktopPage> { class _LikedTendersDesktopPageState extends State<LikedTendersDesktopPage> {
late final LikedTendersViewModel viewModel;
@override
void initState() {
viewModel = context.read<LikedTendersViewModel>();
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return PopScope(
backgroundColor: AppColors.backgroundColor, onPopInvokedWithResult: (didPop, result) {
body: Column( WidgetsBinding.instance.addPostFrameCallback((_) {
children: [ viewModel.updateHome();
DesktopNavigationWidget( });
currentIndex: 1, },
onTabChanged: (index) { child: Scaffold(
switch (index) { backgroundColor: AppColors.backgroundColor,
case 0: body: Column(
Router.neglect(context, () => HomeRouteData().go(context)); children: [
break; DesktopNavigationWidget(currentIndex: 1),
case 1: Expanded(
break; child: SizedBox(
case 2: width: 740,
Router.neglect(context, () => ProfileRouteData().go(context)); child: Consumer<LikedTendersViewModel>(
break; builder: (context, viewModel, child) {
} if (viewModel.isLoading &&
}, (viewModel.data?.data?.feedback ?? []).isEmpty) {
), return const Center(
Expanded( child: CircularProgressIndicator(
child: SizedBox( color: AppColors.secondary50,
width: 740, ),
child: Consumer<LikedTendersViewModel>( );
builder: (context, viewModel, child) { }
if (viewModel.isLoading &&
(viewModel.data?.data?.feedback ?? []).isEmpty) {
return const Center(
child: CircularProgressIndicator(
color: AppColors.secondary50,
),
);
}
if (viewModel.errorMessage != null) { if (viewModel.errorMessage != null) {
return Center(child: Text(viewModel.errorMessage!)); return Center(child: Text(viewModel.errorMessage!));
} }
final feedback = viewModel.data?.data?.feedback ?? []; final feedback = viewModel.data?.data?.feedback ?? [];
if (feedback.isEmpty) { if (feedback.isEmpty) {
return const Center( return const Center(
child: Text('You havent liked any tenders yet.'), child: Text(LikedTendersStrings.noLikedTenders),
); );
} }
final currentPage = viewModel.currentPage; final currentPage = viewModel.currentPage;
final totalPages = viewModel.data?.data?.meta?.pages ?? 1; final totalPages = viewModel.data?.data?.meta?.pages ?? 1;
return Column( return Column(
children: [ children: [
Expanded( Expanded(
child: RefreshIndicator( child: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await viewModel.getLikedTenders(reset: true); await viewModel.getLikedTenders(reset: true);
}, },
child: ListView.builder( child: ListView.builder(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 24.0.w(), horizontal: 24.0.w(),
vertical: 15.0.h(), vertical: 15.0.h(),
), ),
itemCount: feedback.length, itemCount: feedback.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = feedback[index]; final item = feedback[index];
TenderApprovalsData? approval; TenderApprovalsData? approval;
bool hasApproval = viewModel bool hasApproval = viewModel
.hasTenderApprovalForTender(item.tenderId!); .hasTenderApprovalForTender(item.tenderId!);
if (hasApproval) { if (hasApproval) {
approval = viewModel.getApprovalStatusForTender( approval = viewModel
item.tenderId!, .getApprovalStatusForTender(
);
} 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,
),
),
onDismissed: (_) {
if (item.tenderId != null) {
viewModel.removeTenderById(
item.tenderId!, item.tenderId!,
); );
} } else {
}, approval = null;
child: LikedListItem( }
tender: item.tender!, return Padding(
approval: approval, padding: EdgeInsets.only(bottom: 20.0.h()),
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(
SizedBox(height: 10.0.h()), AssetsManager.trash,
Row(
children: [
const Spacer(),
Text(
'Page',
style: TextStyle(
fontSize: 13.0.sp(),
fontWeight: FontWeight.w300,
color: AppColors.grey60,
),
),
SizedBox(width: 10.0.w()),
InkWell(
onTap: () async {
final selectedPage = await showDialog<int>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Select Page'),
content: SizedBox(
width: 200,
height: 300,
child: ListView.builder(
itemCount: totalPages,
itemBuilder: (context, index) {
final pageNumber = index + 1;
return ListTile(
title: Text('Page $pageNumber'),
onTap:
() => Navigator.pop(
context,
pageNumber,
),
);
},
), ),
), ),
); onDismissed: (_) {
}, if (item.tenderId != null) {
); viewModel.removeTenderById(
item.tenderId!,
if (selectedPage != null) { );
await viewModel.jumpToPage(selectedPage); }
} },
}, child: LikedListItem(
child: Container( tender: item.tender!,
decoration: BoxDecoration( approval: approval,
border: Border.all( isDesktop: true,
color: AppColors.grey30,
width: 1,
),
borderRadius: BorderRadius.circular(4),
),
child: Row(
children: [
SizedBox(width: 5.0.w()),
Text(
'$currentPage',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.grey70,
), ),
), ),
SizedBox(width: 5.0.w()), );
SvgPicture.asset( },
AssetsManager.arrowdownSmall, ),
), ),
SizedBox(width: 5.0.w()), ),
],
SizedBox(height: 10.0.h()),
Row(
children: [
const Spacer(),
Text(
'Page',
style: TextStyle(
fontSize: 13.0.sp(),
fontWeight: FontWeight.w300,
color: AppColors.grey60,
), ),
), ),
), SizedBox(width: 10.0.w()),
SizedBox(width: 5.0.w()), InkWell(
Text( onTap: () async {
'Of', final selectedPage = await showDialog<int>(
style: TextStyle( context: context,
fontSize: 14.0.sp(), builder: (context) {
fontWeight: FontWeight.w400, return AlertDialog(
color: AppColors.grey60, title: const Text('Select Page'),
), content: SizedBox(
), width: 200,
SizedBox(width: 5.0.w()), height: 300,
Text( child: ListView.builder(
'$totalPages', itemCount: totalPages,
style: TextStyle( itemBuilder: (context, index) {
fontSize: 13.0.sp(), final pageNumber = index + 1;
fontWeight: FontWeight.w400, return ListTile(
color: AppColors.grey60, title: Text('Page $pageNumber'),
), onTap:
), () => Navigator.pop(
], context,
), pageNumber,
),
);
},
),
),
);
},
);
SizedBox(height: 30.0.h()), if (selectedPage != null) {
], await viewModel.jumpToPage(selectedPage);
); }
}, },
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: AppColors.grey30,
width: 1,
),
borderRadius: BorderRadius.circular(4),
),
child: Row(
children: [
SizedBox(width: 5.0.w()),
Text(
'$currentPage',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.grey70,
),
),
SizedBox(width: 5.0.w()),
SvgPicture.asset(
AssetsManager.arrowdownSmall,
),
SizedBox(width: 5.0.w()),
],
),
),
),
SizedBox(width: 5.0.w()),
Text(
'Of',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w400,
color: AppColors.grey60,
),
),
SizedBox(width: 5.0.w()),
Text(
'$totalPages',
style: TextStyle(
fontSize: 13.0.sp(),
fontWeight: FontWeight.w400,
color: AppColors.grey60,
),
),
],
),
SizedBox(height: 30.0.h()),
],
);
},
),
), ),
), ),
), ],
], ),
), ),
); );
} }
@@ -1,3 +1,4 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -19,9 +20,11 @@ class LikedTendersMobilePage extends StatefulWidget {
class _LikedTendersMobilePageState extends State<LikedTendersMobilePage> { class _LikedTendersMobilePageState extends State<LikedTendersMobilePage> {
late final ScrollController _scrollController; late final ScrollController _scrollController;
late final LikedTendersViewModel viewModel;
@override @override
void initState() { void initState() {
viewModel = context.read<LikedTendersViewModel>();
super.initState(); super.initState();
_scrollController = ScrollController()..addListener(_onScroll); _scrollController = ScrollController()..addListener(_onScroll);
} }
@@ -48,109 +51,124 @@ class _LikedTendersMobilePageState extends State<LikedTendersMobilePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return PopScope(
backgroundColor: AppColors.backgroundColor, onPopInvokedWithResult: (didPop, result) {
appBar: appBar(context: context, title: LikedTendersStrings.likedTenders), if (kIsWeb) {
body: Column( WidgetsBinding.instance.addPostFrameCallback((_) {
children: [ viewModel.updateHome();
Expanded( });
child: Consumer<LikedTendersViewModel>( }
builder: (context, viewModel, child) { },
if (viewModel.isLoading && child: Scaffold(
(viewModel.data?.data?.feedback ?? []).isEmpty) { backgroundColor: AppColors.backgroundColor,
return const Center( appBar: appBar(
child: CircularProgressIndicator( context: context,
color: AppColors.secondary50, title: LikedTendersStrings.likedTenders,
), ),
); body: Column(
} children: [
Expanded(
child: Consumer<LikedTendersViewModel>(
builder: (context, viewModel, child) {
if (viewModel.isLoading &&
(viewModel.data?.data?.feedback ?? []).isEmpty) {
return const Center(
child: CircularProgressIndicator(
color: AppColors.secondary50,
),
);
}
if (viewModel.errorMessage != null) { if (viewModel.errorMessage != null) {
return Center(child: Text(viewModel.errorMessage!)); return Center(child: Text(viewModel.errorMessage!));
} }
final feedback = viewModel.data?.data?.feedback ?? []; final feedback = viewModel.data?.data?.feedback ?? [];
if (feedback.isEmpty) { if (feedback.isEmpty) {
return const Center( return const Center(
child: Text('You havent liked any tenders yet.'), child: Text(LikedTendersStrings.noLikedTenders),
); );
} }
final itemCount = final itemCount =
feedback.length + (viewModel.isLoadingMore ? 1 : 0); feedback.length + (viewModel.isLoadingMore ? 1 : 0);
return RefreshIndicator( return RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await viewModel.getLikedTenders(reset: true); await viewModel.getLikedTenders(reset: true);
}, },
child: ListView.builder( child: ListView.builder(
controller: _scrollController, controller: _scrollController,
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 24.0.w(), horizontal: 24.0.w(),
vertical: 15.0.h(), vertical: 15.0.h(),
), ),
itemCount: itemCount, itemCount: itemCount,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index < feedback.length) { if (index < feedback.length) {
final item = feedback[index]; final item = feedback[index];
TenderApprovalsData? approval; TenderApprovalsData? approval;
bool hasApproval = viewModel.hasTenderApprovalForTender( bool hasApproval = viewModel
item.tenderId!, .hasTenderApprovalForTender(item.tenderId!);
); if (hasApproval) {
if (hasApproval) { approval = viewModel.getApprovalStatusForTender(
approval = viewModel.getApprovalStatusForTender( item.tenderId!,
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,
),
),
); );
} else { } else {
approval = null; 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,
),
),
),
);
} }
},
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,
),
),
),
);
}
},
),
);
},
), ),
), ],
], ),
), ),
); );
} }
@@ -1,9 +1,8 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tm_app/core/constants/assets.dart'; import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/liked_tenders_view_model.dart'; import 'package:tm_app/view_models/liked_tenders_view_model.dart';
@@ -22,226 +21,230 @@ class LikedTendersTabletPage extends StatefulWidget {
} }
class _LikedTendersTabletPageState extends State<LikedTendersTabletPage> { class _LikedTendersTabletPageState extends State<LikedTendersTabletPage> {
late final LikedTendersViewModel viewModel;
@override
void initState() {
viewModel = context.read<LikedTendersViewModel>();
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final GlobalKey<ScaffoldState> key = GlobalKey(); final GlobalKey<ScaffoldState> key = GlobalKey();
return Scaffold( return PopScope(
key: key, onPopInvokedWithResult: (didPop, result) {
backgroundColor: AppColors.backgroundColor, if (kIsWeb) {
appBar: tabletAppBar(title: LikedTendersStrings.likedTenders, key: key), WidgetsBinding.instance.addPostFrameCallback((_) {
drawer: TabletNavigationWidget( viewModel.updateHome();
currentIndex: 1, });
onTabChanged: (index) { }
switch (index) { },
case 0: child: Scaffold(
Router.neglect(context, () => HomeRouteData().go(context)); key: key,
break; backgroundColor: AppColors.backgroundColor,
case 1: appBar: tabletAppBar(title: LikedTendersStrings.likedTenders, key: key),
break; drawer: TabletNavigationWidget(currentIndex: 1),
case 2: body: Center(
context.pop(); child: SizedBox(
Router.neglect(context, () => ProfileRouteData().go(context)); width: 720,
break; child: Column(
} children: [
}, Expanded(
), child: Consumer<LikedTendersViewModel>(
body: Center( builder: (context, viewModel, child) {
child: SizedBox( if (viewModel.isLoading &&
width: 720, (viewModel.data?.data?.feedback ?? []).isEmpty) {
child: Column( return const Center(
children: [ child: CircularProgressIndicator(
Expanded( color: AppColors.secondary50,
child: Consumer<LikedTendersViewModel>( ),
builder: (context, viewModel, child) { );
if (viewModel.isLoading && }
(viewModel.data?.data?.feedback ?? []).isEmpty) {
return const Center(
child: CircularProgressIndicator(
color: AppColors.secondary50,
),
);
}
if (viewModel.errorMessage != null) { if (viewModel.errorMessage != null) {
return Center(child: Text(viewModel.errorMessage!)); return Center(child: Text(viewModel.errorMessage!));
} }
final feedback = viewModel.data?.data?.feedback ?? []; final feedback = viewModel.data?.data?.feedback ?? [];
if (feedback.isEmpty) { if (feedback.isEmpty) {
return const Center( return const Center(
child: Text('You havent liked any tenders yet.'), child: Text(LikedTendersStrings.noLikedTenders),
); );
} }
final currentPage = viewModel.currentPage; final currentPage = viewModel.currentPage;
final totalPages = viewModel.data?.data?.meta?.pages ?? 1; final totalPages = viewModel.data?.data?.meta?.pages ?? 1;
return Column( return Column(
children: [ children: [
Expanded( Expanded(
child: RefreshIndicator( child: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await viewModel.getLikedTenders(reset: true); await viewModel.getLikedTenders(reset: true);
}, },
child: ListView.builder( child: ListView.builder(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 24.0.w(), horizontal: 24.0.w(),
vertical: 15.0.h(), vertical: 15.0.h(),
), ),
itemCount: feedback.length, itemCount: feedback.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = feedback[index]; final item = feedback[index];
TenderApprovalsData? approval; TenderApprovalsData? approval;
bool hasApproval = viewModel bool hasApproval = viewModel
.hasTenderApprovalForTender(item.tenderId!); .hasTenderApprovalForTender(
if (hasApproval) {
approval = viewModel
.getApprovalStatusForTender(
item.tenderId!, item.tenderId!,
); );
} else { if (hasApproval) {
approval = null; approval = viewModel
} .getApprovalStatusForTender(
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!, item.tenderId!,
); );
} } else {
}, approval = null;
child: LikedListItem( }
tender: item.tender!, return Padding(
approval: approval!, 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(),
),
SizedBox(height: 10.0.h()), child: SvgPicture.asset(
AssetsManager.trash,
Row( width: 32.0.w(),
children: [ height: 32.0.h(),
const Spacer(),
Text(
'Page',
style: TextStyle(
fontSize: 13.0.sp(),
fontWeight: FontWeight.w300,
color: AppColors.grey60,
),
),
SizedBox(width: 10.0.w()),
InkWell(
onTap: () async {
final selectedPage = await showDialog<int>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Select Page'),
content: SizedBox(
width: 200,
height: 300,
child: ListView.builder(
itemCount: totalPages,
itemBuilder: (context, index) {
final pageNumber = index + 1;
return ListTile(
title: Text('Page $pageNumber'),
onTap:
() => Navigator.pop(
context,
pageNumber,
),
);
},
), ),
), ),
); onDismissed: (_) {
}, if (item.tenderId != null) {
); viewModel.removeTenderById(
item.tenderId!,
if (selectedPage != null) { );
await viewModel.jumpToPage(selectedPage); }
} },
}, child: LikedListItem(
child: Container( tender: item.tender!,
decoration: BoxDecoration( approval: approval!,
border: Border.all(
color: AppColors.grey30,
width: 1,
),
borderRadius: BorderRadius.circular(4),
),
child: Row(
children: [
SizedBox(width: 5.0.w()),
Text(
'$currentPage',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.grey70,
), ),
), ),
SizedBox(width: 5.0.w()), );
SvgPicture.asset( },
AssetsManager.arrowdownSmall, ),
), ),
SizedBox(width: 5.0.w()), ),
],
SizedBox(height: 10.0.h()),
Row(
children: [
const Spacer(),
Text(
'Page',
style: TextStyle(
fontSize: 13.0.sp(),
fontWeight: FontWeight.w300,
color: AppColors.grey60,
), ),
), ),
), SizedBox(width: 10.0.w()),
SizedBox(width: 5.0.w()), InkWell(
Text( onTap: () async {
'Of', final selectedPage = await showDialog<int>(
style: TextStyle( context: context,
fontSize: 14.0.sp(), builder: (context) {
fontWeight: FontWeight.w400, return AlertDialog(
color: AppColors.grey60, title: const Text('Select Page'),
), content: SizedBox(
), width: 200,
SizedBox(width: 5.0.w()), height: 300,
Text( child: ListView.builder(
'$totalPages', itemCount: totalPages,
style: TextStyle( itemBuilder: (context, index) {
fontSize: 13.0.sp(), final pageNumber = index + 1;
fontWeight: FontWeight.w400, return ListTile(
color: AppColors.grey60, title: Text('Page $pageNumber'),
), onTap:
), () => Navigator.pop(
SizedBox(width: 30.0.w()), context,
], pageNumber,
), ),
);
},
),
),
);
},
);
SizedBox(height: 30.0.h()), if (selectedPage != null) {
], await viewModel.jumpToPage(selectedPage);
); }
}, },
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: AppColors.grey30,
width: 1,
),
borderRadius: BorderRadius.circular(4),
),
child: Row(
children: [
SizedBox(width: 5.0.w()),
Text(
'$currentPage',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w500,
color: AppColors.grey70,
),
),
SizedBox(width: 5.0.w()),
SvgPicture.asset(
AssetsManager.arrowdownSmall,
),
SizedBox(width: 5.0.w()),
],
),
),
),
SizedBox(width: 5.0.w()),
Text(
'Of',
style: TextStyle(
fontSize: 14.0.sp(),
fontWeight: FontWeight.w400,
color: AppColors.grey60,
),
),
SizedBox(width: 5.0.w()),
Text(
'$totalPages',
style: TextStyle(
fontSize: 13.0.sp(),
fontWeight: FontWeight.w400,
color: AppColors.grey60,
),
),
SizedBox(width: 30.0.w()),
],
),
SizedBox(height: 30.0.h()),
],
);
},
),
), ),
), ],
], ),
), ),
), ),
), ),
@@ -12,4 +12,5 @@ class LikedTendersStrings {
static const startDate = 'YYYY/MM/DD'; static const startDate = 'YYYY/MM/DD';
static const endDate = 'YYYY/MM/DD'; static const endDate = 'YYYY/MM/DD';
static const approvedTenders = 'Approved tenders'; static const approvedTenders = 'Approved tenders';
static const noLikedTenders = 'You havent liked any tenders yet.';
} }
@@ -214,7 +214,7 @@ class LikedListItem extends StatelessWidget {
submissionMode: 'self-apply', submissionMode: 'self-apply',
); );
} else { } else {
kIsWeb (kIsWeb && MediaQuery.sizeOf(context).width > 600)
? showDialog( ? showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
@@ -72,28 +72,6 @@ class _DesktopProfilePageState extends State<DesktopProfilePage> {
children: [ children: [
DesktopNavigationWidget( DesktopNavigationWidget(
currentIndex: 2, // Tenders index currentIndex: 2, // Tenders index
onTabChanged: (index) {
// Navigate to different screens based on index
switch (index) {
case 0:
// Navigate to home
Router.neglect(
context,
() => HomeRouteData().go(context),
);
break;
case 1:
// Navigate to profile
Router.neglect(
context,
() => TendersRouteData().go(context),
);
break;
case 2:
// Already on profile
break;
}
},
), ),
SizedBox( SizedBox(
width: 740, width: 740,
+1 -20
View File
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tm_app/core/constants/assets.dart'; import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/constants/common_strings.dart'; import 'package:tm_app/core/constants/common_strings.dart';
@@ -75,25 +74,7 @@ class _TabletProfilePageState extends State<TabletProfilePage> {
backgroundColor: AppColors.backgroundColor, backgroundColor: AppColors.backgroundColor,
appBar: tabletAppBar(title: ProfileStrings.profileTitle, key: key), appBar: tabletAppBar(title: ProfileStrings.profileTitle, key: key),
drawer: TabletNavigationWidget( drawer: TabletNavigationWidget(currentIndex: 2),
currentIndex: 2,
onTabChanged: (index) {
switch (index) {
case 0:
context.pop();
Router.neglect(context, () => HomeRouteData().go(context));
break;
case 1:
context.pop();
Router.neglect(
context,
() => TendersRouteData().go(context),
);
break;
}
},
),
body: Padding( body: Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 24.0.w(), horizontal: 24.0.w(),
@@ -1,21 +1,21 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/constants/assets.dart'; import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/home_view_model.dart';
import 'package:tm_app/view_models/tenders_view_model.dart';
import 'package:tm_app/views/home/strings/home_strings.dart'; import 'package:tm_app/views/home/strings/home_strings.dart';
import 'package:tm_app/views/profile/strings/profile_strings.dart'; import 'package:tm_app/views/profile/strings/profile_strings.dart';
import 'package:tm_app/views/tenders/strings/tenders_strings.dart'; import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
import '../../core/routes/app_routes.dart';
class DesktopNavigationWidget extends StatelessWidget { class DesktopNavigationWidget extends StatelessWidget {
const DesktopNavigationWidget({ const DesktopNavigationWidget({required this.currentIndex, super.key});
required this.currentIndex,
required this.onTabChanged,
super.key,
});
final int currentIndex; final int currentIndex;
final ValueChanged<int> onTabChanged;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -36,7 +36,14 @@ class DesktopNavigationWidget extends StatelessWidget {
context: context, context: context,
text: HomeStrings.home, text: HomeStrings.home,
isActive: currentIndex == 0, isActive: currentIndex == 0,
onTap: () => onTabChanged(0), onTap: () {
if (currentIndex == 0) {
return;
} else {
Router.neglect(context, () => HomeRouteData().go(context));
context.read<HomeViewModel>().init();
}
},
iconPath: AssetsManager.home, iconPath: AssetsManager.home,
activeIconPath: AssetsManager.homeActive, activeIconPath: AssetsManager.homeActive,
), ),
@@ -45,7 +52,14 @@ class DesktopNavigationWidget extends StatelessWidget {
context: context, context: context,
text: TendersStrings.tendersTitle, text: TendersStrings.tendersTitle,
isActive: currentIndex == 1, isActive: currentIndex == 1,
onTap: () => onTabChanged(1), onTap: () {
if (currentIndex == 1) {
return;
} else {
Router.neglect(context, () => TendersRouteData().go(context));
context.read<TendersViewModel>().getTenders();
}
},
iconPath: AssetsManager.tenders, iconPath: AssetsManager.tenders,
activeIconPath: AssetsManager.tendersActive, activeIconPath: AssetsManager.tendersActive,
), ),
@@ -54,7 +68,13 @@ class DesktopNavigationWidget extends StatelessWidget {
context: context, context: context,
text: ProfileStrings.profileTitle, text: ProfileStrings.profileTitle,
isActive: currentIndex == 2, isActive: currentIndex == 2,
onTap: () => onTabChanged(2), onTap: () {
if (currentIndex == 2) {
return;
} else {
Router.neglect(context, () => ProfileRouteData().go(context));
}
},
iconPath: AssetsManager.profile, iconPath: AssetsManager.profile,
activeIconPath: AssetsManager.profileActive, activeIconPath: AssetsManager.profileActive,
), ),
+31 -9
View File
@@ -1,21 +1,22 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/constants/assets.dart'; import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/home_view_model.dart';
import 'package:tm_app/view_models/tenders_view_model.dart';
import 'package:tm_app/views/home/strings/home_strings.dart'; import 'package:tm_app/views/home/strings/home_strings.dart';
import 'package:tm_app/views/profile/strings/profile_strings.dart'; import 'package:tm_app/views/profile/strings/profile_strings.dart';
import 'package:tm_app/views/tenders/strings/tenders_strings.dart'; import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
import '../../core/routes/app_routes.dart';
class TabletNavigationWidget extends StatelessWidget { class TabletNavigationWidget extends StatelessWidget {
const TabletNavigationWidget({ const TabletNavigationWidget({required this.currentIndex, super.key});
required this.currentIndex,
required this.onTabChanged,
super.key,
});
final int currentIndex; final int currentIndex;
final ValueChanged<int> onTabChanged;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -30,7 +31,14 @@ class TabletNavigationWidget extends StatelessWidget {
context: context, context: context,
text: HomeStrings.home, text: HomeStrings.home,
isActive: currentIndex == 0, isActive: currentIndex == 0,
onTap: () => onTabChanged(0), onTap: () {
if (currentIndex == 0) {
return;
} else {
Router.neglect(context, () => HomeRouteData().go(context));
context.read<HomeViewModel>().init();
}
},
iconPath: AssetsManager.home, iconPath: AssetsManager.home,
activeIconPath: AssetsManager.homeActive, activeIconPath: AssetsManager.homeActive,
), ),
@@ -38,7 +46,14 @@ class TabletNavigationWidget extends StatelessWidget {
context: context, context: context,
text: TendersStrings.tendersTitle, text: TendersStrings.tendersTitle,
isActive: currentIndex == 1, isActive: currentIndex == 1,
onTap: () => onTabChanged(1), onTap: () {
if (currentIndex == 1) {
return;
} else {
Router.neglect(context, () => TendersRouteData().go(context));
context.read<TendersViewModel>().getTenders();
}
},
iconPath: AssetsManager.tenders, iconPath: AssetsManager.tenders,
activeIconPath: AssetsManager.tendersActive, activeIconPath: AssetsManager.tendersActive,
), ),
@@ -46,7 +61,14 @@ class TabletNavigationWidget extends StatelessWidget {
context: context, context: context,
text: ProfileStrings.profileTitle, text: ProfileStrings.profileTitle,
isActive: currentIndex == 2, isActive: currentIndex == 2,
onTap: () => onTabChanged(2), onTap: () {
if (currentIndex == 2) {
return;
} else {
context.pop();
Router.neglect(context, () => ProfileRouteData().go(context));
}
},
iconPath: AssetsManager.profile, iconPath: AssetsManager.profile,
activeIconPath: AssetsManager.profileActive, activeIconPath: AssetsManager.profileActive,
), ),
+34 -59
View File
@@ -7,7 +7,6 @@ import 'package:tm_app/views/shared/desktop_navigation_widget.dart';
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart'; import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
import '../../../core/constants/common_strings.dart'; import '../../../core/constants/common_strings.dart';
import '../../../core/routes/app_routes.dart';
class DesktopTendersPage extends StatefulWidget { class DesktopTendersPage extends StatefulWidget {
const DesktopTendersPage({super.key}); const DesktopTendersPage({super.key});
@@ -54,65 +53,41 @@ class _DesktopTendersPageState extends State<DesktopTendersPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: AppColors.backgroundColor, backgroundColor: AppColors.backgroundColor,
body: Column( body: SingleChildScrollView(
children: [ child: Consumer<TendersViewModel>(
DesktopNavigationWidget( builder: (context, viewModel, child) {
currentIndex: 1, // Tenders index if (viewModel.isLoading) {
onTabChanged: (index) { return Center(
// Navigate to different screens based on index child: CircularProgressIndicator(color: AppColors.jellyBean),
switch (index) { );
case 0: }
// Navigate to home if (viewModel.errorMessage != null) {
Router.neglect(context, () => HomeRouteData().go(context)); return Center(child: Text(viewModel.errorMessage!));
viewModel.updateHome(); }
break; if (viewModel.tendersResponse?.data?.tenders == null ||
case 1: viewModel.tendersResponse!.data!.tenders!.isEmpty) {
// Already on tenders return Center(child: Text(CommonStrings.noData));
break; }
case 2: return Column(
// Navigate to profile children: [
Router.neglect(context, () => ProfileRouteData().go(context)); DesktopNavigationWidget(
break; currentIndex: 1, // Tenders index
}
},
),
Expanded(
child: Center(
child: SingleChildScrollView(
child: Consumer<TendersViewModel>(
builder: (context, viewModel, child) {
if (viewModel.isLoading) {
return Center(
child: CircularProgressIndicator(
color: AppColors.jellyBean,
),
);
}
if (viewModel.errorMessage != null) {
return Center(child: Text(viewModel.errorMessage!));
}
if (viewModel.tendersResponse?.data?.tenders == null ||
viewModel.tendersResponse!.data!.tenders!.isEmpty) {
return Center(child: Text(CommonStrings.noData));
}
return SizedBox(
width: 740,
height: 800,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 24.0.h()),
child: MainTendersSlider(
tenders:
viewModel.tendersResponse?.data?.tenders ?? [],
isDesktop: true,
),
),
);
},
), ),
), SizedBox(
), width: 740,
), height: 800,
], child: Padding(
padding: EdgeInsets.symmetric(vertical: 24.0.h()),
child: MainTendersSlider(
tenders: viewModel.tendersResponse?.data?.tenders ?? [],
isDesktop: true,
),
),
),
],
);
},
),
), ),
); );
} }
+1 -19
View File
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
@@ -8,7 +7,6 @@ import 'package:tm_app/views/shared/tablet_navigation_widget.dart';
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart'; import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
import '../../../core/constants/common_strings.dart'; import '../../../core/constants/common_strings.dart';
import '../../../core/routes/app_routes.dart';
import '../../shared/tender_app_bar.dart'; import '../../shared/tender_app_bar.dart';
import '../strings/tenders_strings.dart'; import '../strings/tenders_strings.dart';
@@ -35,23 +33,7 @@ class _TabletTendersPageState extends State<TabletTendersPage> {
key: key, key: key,
backgroundColor: AppColors.backgroundColor, backgroundColor: AppColors.backgroundColor,
appBar: tabletAppBar(title: TendersStrings.tendersTitle, key: key), appBar: tabletAppBar(title: TendersStrings.tendersTitle, key: key),
drawer: TabletNavigationWidget( drawer: TabletNavigationWidget(currentIndex: 1),
currentIndex: 1,
onTabChanged: (index) {
switch (index) {
case 0:
context.pop();
Router.neglect(context, () => HomeRouteData().go(context));
viewModel.updateHome();
break;
case 2:
context.pop();
Router.neglect(context, () => ProfileRouteData().go(context));
break;
}
},
),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Consumer<TendersViewModel>( child: Consumer<TendersViewModel>(
builder: (context, viewModel, child) { builder: (context, viewModel, child) {
@@ -91,7 +91,7 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
Widget _tendersPageView() { Widget _tendersPageView() {
return SizedBox( return SizedBox(
width: double.infinity, width: double.infinity,
height: 719.0.h(), height: 722.0.h(),
child: PageView.builder( child: PageView.builder(
controller: pageController, controller: pageController,
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
@@ -145,8 +145,8 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
borderRadius: BorderRadius.circular(100), borderRadius: BorderRadius.circular(100),
onTap: _goToPreviousPage, onTap: _goToPreviousPage,
child: Container( child: Container(
width: 32.0.w(), width: 32.0.h(),
height: 32.0.w(), height: 32.0.h(),
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all(color: AppColors.iconColor, width: 1.5), border: Border.all(color: AppColors.iconColor, width: 1.5),
@@ -194,8 +194,8 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
borderRadius: BorderRadius.circular(100), borderRadius: BorderRadius.circular(100),
onTap: _goToNextPage, onTap: _goToNextPage,
child: Container( child: Container(
width: 32.0.w(), width: 32.0.h(),
height: 32.0.w(), height: 32.0.h(),
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all(color: AppColors.iconColor, width: 1.5), border: Border.all(color: AppColors.iconColor, width: 1.5),
@@ -8,7 +8,6 @@ import 'package:tm_app/views/your_tenders/widgets/liked_disliked_tenders_list.da
import 'package:tm_app/views/your_tenders/widgets/tablet_desktop_appbar.dart'; import 'package:tm_app/views/your_tenders/widgets/tablet_desktop_appbar.dart';
import 'package:tm_app/views/your_tenders/widgets/tenders_submitted.dart'; import 'package:tm_app/views/your_tenders/widgets/tenders_submitted.dart';
import '../../../core/routes/app_routes.dart';
import '../../shared/desktop_navigation_widget.dart'; import '../../shared/desktop_navigation_widget.dart';
class YourTendersDesktopPage extends StatefulWidget { class YourTendersDesktopPage extends StatefulWidget {
@@ -43,22 +42,6 @@ class _YourTendersDesktopPageState extends State<YourTendersDesktopPage>
children: [ children: [
DesktopNavigationWidget( DesktopNavigationWidget(
currentIndex: 1, // Tenders index currentIndex: 1, // Tenders index
onTabChanged: (index) {
// Navigate to different screens based on index
switch (index) {
case 0:
// Navigate to home
Router.neglect(context, () => HomeRouteData().go(context));
break;
case 1:
// Already on tenders
break;
case 2:
// Navigate to profile
Router.neglect(context, () => ProfileRouteData().go(context));
break;
}
},
), ),
Expanded( Expanded(
child: SizedBox( child: SizedBox(
@@ -68,14 +51,6 @@ class _YourTendersDesktopPageState extends State<YourTendersDesktopPage>
SizedBox(height: 64.0), SizedBox(height: 64.0),
TabletDesktopAppbar(), TabletDesktopAppbar(),
SizedBox(height: 20.0), SizedBox(height: 20.0),
// MainTabBar(
// controller: controller,
// titles: [
// AppStrings.approvedTenders,
// AppStrings.tenderSubmitted,
// ],
// ),
FilterButton(platformType: PlatformType.tabletDesktop), FilterButton(platformType: PlatformType.tabletDesktop),
Expanded( Expanded(
@@ -115,15 +90,10 @@ class _YourTendersDesktopPageState extends State<YourTendersDesktopPage>
isDesktop: true, isDesktop: true,
); );
} else { } else {
return const Center(child: Text('No data available')); return const Center(
child: Text(YourTendersStrings.noTenders),
);
} }
// return TabBarView(
// controller: controller,
// children: [
// // ApprovedTenders(tendersSubmitted: []),
// ],
// );
}, },
), ),
), ),
@@ -85,7 +85,9 @@ class _YourTendersMobilePageState extends State<YourTendersMobilePage> {
) )
else else
const Expanded( const Expanded(
child: Center(child: Text('No data available')), child: Center(
child: Text(YourTendersStrings.noTenders),
),
), ),
], ],
); );
@@ -1,7 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/your_tenders_view_model.dart'; import 'package:tm_app/view_models/your_tenders_view_model.dart';
@@ -46,21 +44,6 @@ class _YourTendersTabletPageState extends State<YourTendersTabletPage>
appBar: tabletAppBar(title: YourTendersStrings.yourTenders, key: key), appBar: tabletAppBar(title: YourTendersStrings.yourTenders, key: key),
drawer: TabletNavigationWidget( drawer: TabletNavigationWidget(
currentIndex: 1, // Home is index 0 currentIndex: 1, // Home is index 0
onTabChanged: (index) {
// Handle navigation to other tabs
switch (index) {
case 0:
Router.neglect(context, () => HomeRouteData().go(context));
break;
case 1:
break;
case 2:
// Navigate to profile
context.pop();
Router.neglect(context, () => ProfileRouteData().go(context));
break;
}
},
), ),
body: Center( body: Center(
child: SizedBox( child: SizedBox(
@@ -114,9 +97,14 @@ class _YourTendersTabletPageState extends State<YourTendersTabletPage>
isDesctop: false, isDesctop: false,
); );
} else if (viewModel.data != null) { } else if (viewModel.data != null) {
return TendersSubmitted(approvedTenders: viewModel.data!,isDesktop: false,); return TendersSubmitted(
approvedTenders: viewModel.data!,
isDesktop: false,
);
} else { } else {
return const Center(child: Text('No data available')); return const Center(
child: Text(YourTendersStrings.noTenders),
);
} }
}, },
), ),
@@ -13,4 +13,6 @@ class YourTendersStrings {
static const startDate = 'YYYY/MM/DD'; static const startDate = 'YYYY/MM/DD';
static const endDate = 'YYYY/MM/DD'; static const endDate = 'YYYY/MM/DD';
static const approvedTenders = 'Approved tenders'; static const approvedTenders = 'Approved tenders';
static const noTenders = 'No data available';
static const selectPublicationRangeDate = 'Select publication date range';
} }
@@ -115,7 +115,7 @@ class TendersFilterDialog extends StatelessWidget {
), ),
SizedBox(height: 16.0.h()), SizedBox(height: 16.0.h()),
Text( Text(
'Select date range', YourTendersStrings.selectPublicationRangeDate,
style: TextStyle( style: TextStyle(
fontSize: 16.0.sp(), fontSize: 16.0.sp(),
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,