Add filter dialog and bottom sheet for tenders
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'tenders_filter_dialog.dart';
|
||||
|
||||
enum PlatformType { mobile, tabletDesktop }
|
||||
|
||||
class FilterButton extends StatelessWidget {
|
||||
final PlatformType platformType;
|
||||
const FilterButton({required this.platformType, super.key});
|
||||
|
||||
void _openFilter(BuildContext context) {
|
||||
if (platformType == PlatformType.mobile) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.white,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||
),
|
||||
builder: (_) => const TendersFilterDialog(),
|
||||
);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder:
|
||||
(_) => Dialog(
|
||||
backgroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: const TendersFilterDialog(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Mobile style: container with icon and text
|
||||
return InkWell(
|
||||
onTap: () => _openFilter(context),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(12),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.shade50,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: const Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.filter_list, color: Colors.blue),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
'Filter',
|
||||
style: TextStyle(
|
||||
color: Colors.blue,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
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';
|
||||
|
||||
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 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 ? 'YYYY/MM/DD' : viewModel.startDateFormatted,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0.sp(),
|
||||
fontWeight: FontWeight.w400,
|
||||
color: AppColors.grey70,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
end == null ? 'YYYY/MM/DD' : 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: [
|
||||
Center(
|
||||
child: Text(
|
||||
'Filter',
|
||||
style: TextStyle(
|
||||
fontSize: 20.0.sp(),
|
||||
fontWeight: FontWeight.w700,
|
||||
color: AppColors.grey70,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.0.h()),
|
||||
Text(
|
||||
'Select date range',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0.sp(),
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.grey80,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.0.h()),
|
||||
_dateRangePill(context),
|
||||
SizedBox(height: 16.0.h()),
|
||||
Text(
|
||||
'Status',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0.sp(),
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.grey70,
|
||||
),
|
||||
),
|
||||
...[
|
||||
'All',
|
||||
'Like tenders',
|
||||
'Dislike tenders',
|
||||
'Approved tenders',
|
||||
'Tenders submitted',
|
||||
].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()),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: BaseButton(
|
||||
isEnabled: true,
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
},
|
||||
text: 'Confirm',
|
||||
textColor: AppColors.mainBlue,
|
||||
backgroundColor: AppColors.primary30,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user