Files
tm_app/lib/views/tenders/pages/d_tenders_page.dart
T
llsajjad 6e6f248702 Fixed pagination tenders for desktop and
added new config for notification
2025-09-21 14:03:32 +03:30

278 lines
8.5 KiB
Dart

import 'package:flutter/material.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/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/tenders_view_model.dart';
import 'package:tm_app/views/shared/base_button.dart';
import 'package:tm_app/views/shared/desktop_navigation_widget.dart';
import 'package:tm_app/views/shared/page_selection_dialog.dart';
import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
import '../../../core/constants/common_strings.dart';
import '../../../core/utils/app_toast.dart';
class DesktopTendersPage extends StatefulWidget {
const DesktopTendersPage({super.key});
@override
State<DesktopTendersPage> createState() => _DesktopTendersPageState();
}
class _DesktopTendersPageState extends State<DesktopTendersPage> {
late final TendersViewModel viewModel;
@override
void initState() {
super.initState();
viewModel = context.read<TendersViewModel>();
viewModel.addListener(_viewModelListener);
}
void _viewModelListener() {
if (viewModel.feedbackErrorMessage != null) {
AppToast.error(context, viewModel.feedbackErrorMessage!);
}
if (viewModel.tenderApprovalErrorMessage != null) {
AppToast.error(context, viewModel.tenderApprovalErrorMessage!);
}
}
@override
void dispose() {
viewModel.removeListener(_viewModelListener);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.backgroundColor,
body: Column(
children: [
const DesktopNavigationWidget(currentIndex: 1),
SizedBox(height: 48.0.h()),
const _SearchBox(),
const _ActionButtons(),
Expanded(
child: Consumer<TendersViewModel>(
builder: (context, vm, child) {
if (vm.isLoading) {
return const Center(
child: CircularProgressIndicator(color: AppColors.jellyBean),
);
}
if (vm.errorMessage != null) {
return Center(child: Text(vm.errorMessage!));
}
final tenders = vm.tendersResponse?.data?.tenders ?? [];
if (tenders.isEmpty) {
return const Center(child: Text(CommonStrings.noData));
}
return Column(
children: [
Expanded(
child: SingleChildScrollView(
child: SizedBox(
width: 740,
height: 800,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 4.0.h()),
child: MainTendersSlider(
tenders: tenders,
isDesktop: true,
),
),
),
),
),
_DesktopPagination(
totalPages: vm.totalPages,
currentPage: vm.currentPage,
onPageSelected: vm.jumpToPage,
),
],
);
},
),
),
],
),
);
}
}
class _SearchBox extends StatelessWidget {
const _SearchBox();
@override
Widget build(BuildContext context) {
return SizedBox(
height: 48.0.h(),
width: 680,
child: TextField(
style: TextStyle(fontSize: 16.0.sp(), color: AppColors.grey0),
decoration: InputDecoration(
hintText: 'Search',
hintStyle: TextStyle(fontSize: 16.0.sp(), color: AppColors.grey60),
prefixIcon: Padding(
padding: EdgeInsets.all(12.0.w()),
child: SvgPicture.asset(
AssetsManager.normalSearch,
width: 24.0.w(),
height: 24.0.h(),
),
),
filled: true,
fillColor: AppColors.grey0,
contentPadding: EdgeInsets.symmetric(
horizontal: 12.0.w(),
vertical: 12.0.h(),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0.w()),
borderSide: const BorderSide(color: AppColors.mainBlue, width: 1),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0.w()),
borderSide: BorderSide(color: AppColors.grey40, width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0.w()),
borderSide: const BorderSide(color: AppColors.grey, width: 1.5),
),
),
),
);
}
}
class _ActionButtons extends StatelessWidget {
const _ActionButtons();
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 25.0.h()),
height: 40.0.h(),
width: 680,
child: Row(
children: [
BaseButton(
width: 178.0.w(),
isEnabled: true,
onPressed: () {},
text: 'Filter',
icon: AssetsManager.filter,
iconColor: AppColors.textBlue,
backgroundColor: AppColors.primary2,
textColor: AppColors.textBlue,
),
SizedBox(width: 10.0.w()),
BaseButton(
width: 178.0.w(),
isEnabled: true,
onPressed: () {},
text: 'Sort',
icon: AssetsManager.sort,
iconColor: AppColors.textBlue,
backgroundColor: AppColors.primary2,
textColor: AppColors.textBlue,
),
],
),
);
}
}
class _DesktopPagination extends StatelessWidget {
final int totalPages;
final int currentPage;
final ValueChanged<int> onPageSelected;
const _DesktopPagination({
required this.totalPages,
required this.currentPage,
required this.onPageSelected,
});
@override
Widget build(BuildContext context) {
return SizedBox(
width: 680,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 12.0.h()),
child: Row(
children: [
const Spacer(),
Text(
TendersStrings.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) =>
PageSelectionDialog(totalPages: totalPages),
);
if (selectedPage != null) {
onPageSelected(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(
TendersStrings.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,
),
),
],
),
),
);
}
}