added Filter and Sort dialog design in tenders page
This commit is contained in:
@@ -12,6 +12,8 @@ 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/shared/page_selection_dialog.dart';
|
||||||
import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
|
import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
|
||||||
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
|
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
|
||||||
|
import 'package:tm_app/views/tenders/widgets/tenders_filter_dialog.dart';
|
||||||
|
import 'package:tm_app/views/tenders/widgets/tenders_sort_dialog.dart';
|
||||||
|
|
||||||
import '../../../core/constants/common_strings.dart';
|
import '../../../core/constants/common_strings.dart';
|
||||||
import '../../../core/utils/app_toast.dart';
|
import '../../../core/utils/app_toast.dart';
|
||||||
@@ -190,7 +192,22 @@ class _ActionButtons extends StatelessWidget {
|
|||||||
BaseButton(
|
BaseButton(
|
||||||
width: 178.0.w(),
|
width: 178.0.w(),
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(_) => Dialog(
|
||||||
|
backgroundColor: AppColors.backgroundColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
child: const SizedBox(
|
||||||
|
width: 560,
|
||||||
|
child: TendersFilterDialog(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
text: 'Filter',
|
text: 'Filter',
|
||||||
icon: AssetsManager.filter,
|
icon: AssetsManager.filter,
|
||||||
iconColor: AppColors.textBlue,
|
iconColor: AppColors.textBlue,
|
||||||
@@ -201,7 +218,22 @@ class _ActionButtons extends StatelessWidget {
|
|||||||
BaseButton(
|
BaseButton(
|
||||||
width: 178.0.w(),
|
width: 178.0.w(),
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(_) => Dialog(
|
||||||
|
backgroundColor: AppColors.backgroundColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
child: const SizedBox(
|
||||||
|
width: 560,
|
||||||
|
child: TendersSortDialog(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
text: 'Sort',
|
text: 'Sort',
|
||||||
icon: AssetsManager.sort,
|
icon: AssetsManager.sort,
|
||||||
iconColor: AppColors.textBlue,
|
iconColor: AppColors.textBlue,
|
||||||
|
|||||||
@@ -12,5 +12,19 @@ class TendersStrings {
|
|||||||
static const String notifications = 'Notifications';
|
static const String notifications = 'Notifications';
|
||||||
static const String of = 'Of';
|
static const String of = 'Of';
|
||||||
static const String page = 'Page';
|
static const String page = 'Page';
|
||||||
static const String search = 'Search tenders...';
|
static const String all = 'All';
|
||||||
|
static const String read = 'Read';
|
||||||
|
static const String selectDataRange = 'Select date range';
|
||||||
|
static const String unread = 'Unread';
|
||||||
|
static const String search = 'Search';
|
||||||
|
static const String status = 'Status';
|
||||||
|
static const String confirm = 'Confirm';
|
||||||
|
static const String filter = 'Filter';
|
||||||
|
static const String endDate = 'end Date';
|
||||||
|
static const String startDate = 'Start Date';
|
||||||
|
static const String sort = 'Sort';
|
||||||
|
static const String mostOfTheTime = 'Most of the time';
|
||||||
|
static const String minimumTime = 'Minimum time';
|
||||||
|
static const String lessBudget = 'Less budget';
|
||||||
|
static const String moreBudget = 'More budget';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
import 'package:flutter/material.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/theme/colors.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/views/shared/base_button.dart';
|
||||||
|
import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
|
||||||
|
|
||||||
|
class TendersFilterDialog extends StatelessWidget {
|
||||||
|
const TendersFilterDialog({super.key});
|
||||||
|
|
||||||
|
Widget _dateRangePill(BuildContext context) {
|
||||||
|
final viewModel = context.watch<YourTendersViewModel>();
|
||||||
|
final start = viewModel.selectedDateRange?.start;
|
||||||
|
final end = viewModel.selectedDateRange?.end;
|
||||||
|
|
||||||
|
Future<void> pick() async {
|
||||||
|
final picked = await showDateRangePicker(
|
||||||
|
context: context,
|
||||||
|
firstDate: DateTime(2020),
|
||||||
|
lastDate: DateTime(2035),
|
||||||
|
initialDateRange: viewModel.selectedDateRange,
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
viewModel.setDateRange(picked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
width: 560,
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
onTap: pick,
|
||||||
|
child: Container(
|
||||||
|
height: 56.0.h(),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColors.grey0,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: AppColors.grey40),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Container(
|
||||||
|
width: 1,
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
color: AppColors.grey40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: SizedBox(
|
||||||
|
width: 26.0.w(),
|
||||||
|
height: 26.0.h(),
|
||||||
|
child: SvgPicture.asset(AssetsManager.trailingIcon),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
start == null
|
||||||
|
? TendersStrings.startDate
|
||||||
|
: viewModel.startDateFormatted,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16.0.sp(),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: AppColors.grey70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
end == null
|
||||||
|
? TendersStrings.endDate
|
||||||
|
: viewModel.endDateFormatted,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16.0.sp(),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: AppColors.grey70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer<YourTendersViewModel>(
|
||||||
|
builder: (context, vm, child) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
TendersStrings.filter,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20.0.sp(),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColors.grey70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
AssetsManager.closeCircle,
|
||||||
|
colorFilter: ColorFilter.mode(
|
||||||
|
AppColors.grey80,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
|
width: 24.0.w(),
|
||||||
|
height: 24.0.h(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.0.h()),
|
||||||
|
Divider(color: AppColors.grey20),
|
||||||
|
SizedBox(height: 20.0.h()),
|
||||||
|
Text(
|
||||||
|
TendersStrings.selectDataRange,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16.0.sp(),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColors.grey80,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 10.0.h()),
|
||||||
|
_dateRangePill(context),
|
||||||
|
SizedBox(height: 16.0.h()),
|
||||||
|
Text(
|
||||||
|
TendersStrings.status,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16.0.sp(),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColors.grey70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...[
|
||||||
|
TendersStrings.all,
|
||||||
|
TendersStrings.read,
|
||||||
|
TendersStrings.unread,
|
||||||
|
].map((status) {
|
||||||
|
return RadioListTile(
|
||||||
|
value: status,
|
||||||
|
groupValue: vm.selectedStatus,
|
||||||
|
activeColor: AppColors.mainBlue,
|
||||||
|
onChanged: (value) => vm.setStatus(value!),
|
||||||
|
title: Text(
|
||||||
|
status,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16.0.sp(),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: AppColors.grey70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
SizedBox(height: 16.0.h()),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Spacer(),
|
||||||
|
SizedBox(
|
||||||
|
width: 156.0.w(),
|
||||||
|
child: BaseButton(
|
||||||
|
isEnabled: true,
|
||||||
|
onPressed: () {
|
||||||
|
context.pop();
|
||||||
|
vm.callWithFilter();
|
||||||
|
},
|
||||||
|
text: TendersStrings.confirm,
|
||||||
|
textColor: AppColors.textBlue,
|
||||||
|
backgroundColor: AppColors.primary2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import 'package:flutter/material.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/theme/colors.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/views/shared/base_button.dart';
|
||||||
|
import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
|
||||||
|
|
||||||
|
class TendersSortDialog extends StatelessWidget {
|
||||||
|
const TendersSortDialog({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer<YourTendersViewModel>(
|
||||||
|
builder: (context, vm, child) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
TendersStrings.sort,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20.0.sp(),
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColors.grey70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
AssetsManager.closeCircle,
|
||||||
|
colorFilter: ColorFilter.mode(
|
||||||
|
AppColors.grey80,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
|
width: 24.0.w(),
|
||||||
|
height: 24.0.h(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.0.h()),
|
||||||
|
Divider(color: AppColors.grey20),
|
||||||
|
SizedBox(height: 20.0.h()),
|
||||||
|
...[
|
||||||
|
TendersStrings.minimumTime,
|
||||||
|
TendersStrings.mostOfTheTime,
|
||||||
|
TendersStrings.lessBudget,
|
||||||
|
TendersStrings.moreBudget,
|
||||||
|
].map((status) {
|
||||||
|
return RadioListTile(
|
||||||
|
value: status,
|
||||||
|
groupValue: vm.selectedStatus,
|
||||||
|
activeColor: AppColors.mainBlue,
|
||||||
|
onChanged: (value) => vm.setStatus(value!),
|
||||||
|
title: Text(
|
||||||
|
status,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16.0.sp(),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: AppColors.grey70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
SizedBox(height: 16.0.h()),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Spacer(),
|
||||||
|
SizedBox(
|
||||||
|
width: 156.0.w(),
|
||||||
|
child: BaseButton(
|
||||||
|
isEnabled: true,
|
||||||
|
onPressed: () {
|
||||||
|
context.pop();
|
||||||
|
vm.callWithFilter();
|
||||||
|
},
|
||||||
|
text: TendersStrings.confirm,
|
||||||
|
textColor: AppColors.textBlue,
|
||||||
|
backgroundColor: AppColors.primary2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:tm_app/core/theme/colors.dart';
|
import 'package:tm_app/core/theme/colors.dart';
|
||||||
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
|
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
|
||||||
|
|
||||||
import 'tenders_filter_dialog.dart';
|
import 'your_tenders_filter_dialog.dart';
|
||||||
|
|
||||||
enum PlatformType { mobile, tabletDesktop }
|
enum PlatformType { mobile, tabletDesktop }
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ class FilterButton extends StatelessWidget {
|
|||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||||
),
|
),
|
||||||
builder: (_) => const TendersFilterDialog(),
|
builder: (_) => const YourTendersFilterDialog(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showDialog(
|
showDialog(
|
||||||
@@ -30,7 +30,7 @@ class FilterButton extends StatelessWidget {
|
|||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
),
|
||||||
child: const TendersFilterDialog(),
|
child: const YourTendersFilterDialog(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -9,8 +9,8 @@ import 'package:tm_app/view_models/your_tenders_view_model.dart';
|
|||||||
import 'package:tm_app/views/shared/base_button.dart';
|
import 'package:tm_app/views/shared/base_button.dart';
|
||||||
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
|
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';
|
||||||
|
|
||||||
class TendersFilterDialog extends StatelessWidget {
|
class YourTendersFilterDialog extends StatelessWidget {
|
||||||
const TendersFilterDialog({super.key});
|
const YourTendersFilterDialog({super.key});
|
||||||
|
|
||||||
Widget _dateRangePill(BuildContext context) {
|
Widget _dateRangePill(BuildContext context) {
|
||||||
final viewModel = context.watch<YourTendersViewModel>();
|
final viewModel = context.watch<YourTendersViewModel>();
|
||||||
Reference in New Issue
Block a user