TF-997 Custom date ranges in search
This commit is contained in:
+103
-1
@@ -1,6 +1,7 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_date_range_picker/multiple_view_date_range_picker.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||||
@@ -19,7 +20,9 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller
|
|||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_receive_time_type.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_receive_time_type.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/search_email_filter.dart';
|
||||||
|
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||||
|
|
||||||
@@ -45,12 +48,20 @@ class AdvancedFilterController extends BaseController {
|
|||||||
final SearchController searchController = Get.find<SearchController>();
|
final SearchController searchController = Get.find<SearchController>();
|
||||||
final MailboxDashBoardController _mailboxDashBoardController =
|
final MailboxDashBoardController _mailboxDashBoardController =
|
||||||
Get.find<MailboxDashBoardController>();
|
Get.find<MailboxDashBoardController>();
|
||||||
|
final _appToast = Get.find<AppToast>();
|
||||||
|
final _imagePaths = Get.find<ImagePaths>();
|
||||||
|
|
||||||
SearchEmailFilter get searchEmailFilter =>
|
SearchEmailFilter get searchEmailFilter =>
|
||||||
searchController.searchEmailFilter.value;
|
searchController.searchEmailFilter.value;
|
||||||
|
|
||||||
final focusManager = InputFieldFocusManager.initial();
|
final focusManager = InputFieldFocusManager.initial();
|
||||||
|
|
||||||
|
DateTime? _startDate, _endDate;
|
||||||
|
|
||||||
|
DateTime? get startDate => _startDate;
|
||||||
|
|
||||||
|
DateTime? get endDate => _endDate;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onReady() {
|
void onReady() {
|
||||||
if (!BuildUtils.isWeb) {
|
if (!BuildUtils.isWeb) {
|
||||||
@@ -71,6 +82,7 @@ class AdvancedFilterController extends BaseController {
|
|||||||
void cleanSearchFilter(BuildContext context) {
|
void cleanSearchFilter(BuildContext context) {
|
||||||
searchController.cleanSearchFilter();
|
searchController.cleanSearchFilter();
|
||||||
dateFilterSelectedFormAdvancedSearch.value = EmailReceiveTimeType.allTime;
|
dateFilterSelectedFormAdvancedSearch.value = EmailReceiveTimeType.allTime;
|
||||||
|
clearDateRangeOfFilter();
|
||||||
subjectFilterInputController.text = '';
|
subjectFilterInputController.text = '';
|
||||||
hasKeyWordFilterInputController.text = '';
|
hasKeyWordFilterInputController.text = '';
|
||||||
notKeyWordFilterInputController.text = '';
|
notKeyWordFilterInputController.text = '';
|
||||||
@@ -117,6 +129,8 @@ class AdvancedFilterController extends BaseController {
|
|||||||
StringConvert.writeEmptyToNull(subjectFilterInputController.text),
|
StringConvert.writeEmptyToNull(subjectFilterInputController.text),
|
||||||
emailReceiveTimeType: dateFilterSelectedFormAdvancedSearch.value,
|
emailReceiveTimeType: dateFilterSelectedFormAdvancedSearch.value,
|
||||||
hasAttachment: hasAttachment.value,
|
hasAttachment: hasAttachment.value,
|
||||||
|
endDate: _endDate.toUTCDate(),
|
||||||
|
startDate: _startDate.toUTCDate()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +241,10 @@ class AdvancedFilterController extends BaseController {
|
|||||||
notKeyWordFilterInputController.text = StringConvert.writeNullToEmpty(
|
notKeyWordFilterInputController.text = StringConvert.writeNullToEmpty(
|
||||||
searchEmailFilter.notKeyword.firstOrNull);
|
searchEmailFilter.notKeyword.firstOrNull);
|
||||||
dateFilterInputController.text = StringConvert.writeNullToEmpty(
|
dateFilterInputController.text = StringConvert.writeNullToEmpty(
|
||||||
searchEmailFilter.emailReceiveTimeType.getTitle(context));
|
searchEmailFilter.emailReceiveTimeType.getTitle(
|
||||||
|
context,
|
||||||
|
startDate: _startDate,
|
||||||
|
endDate: _endDate));
|
||||||
mailBoxFilterInputController.text =
|
mailBoxFilterInputController.text =
|
||||||
StringConvert.writeNullToEmpty(searchEmailFilter.mailbox?.name?.name);
|
StringConvert.writeNullToEmpty(searchEmailFilter.mailbox?.name?.name);
|
||||||
dateFilterSelectedFormAdvancedSearch.value =
|
dateFilterSelectedFormAdvancedSearch.value =
|
||||||
@@ -235,6 +252,91 @@ class AdvancedFilterController extends BaseController {
|
|||||||
hasAttachment.value = searchEmailFilter.hasAttachment;
|
hasAttachment.value = searchEmailFilter.hasAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void selectDateRange(BuildContext context) {
|
||||||
|
showGeneralDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: true,
|
||||||
|
barrierLabel: '',
|
||||||
|
barrierColor: Colors.black54,
|
||||||
|
pageBuilder: (context, animation, secondaryAnimation) {
|
||||||
|
return Dialog(
|
||||||
|
elevation: 0,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(18.0)),
|
||||||
|
child: MultipleViewDateRangePicker(
|
||||||
|
confirmText: AppLocalizations.of(context).setDate,
|
||||||
|
cancelText: AppLocalizations.of(context).cancel,
|
||||||
|
last7daysTitle: AppLocalizations.of(context).last7Days,
|
||||||
|
last30daysTitle: AppLocalizations.of(context).last30Days,
|
||||||
|
last6monthsTitle: AppLocalizations.of(context).last6Months,
|
||||||
|
lastYearTitle: AppLocalizations.of(context).lastYears,
|
||||||
|
startDate: _startDate,
|
||||||
|
endDate: _endDate,
|
||||||
|
setDateActionCallback: ({startDate, endDate}) {
|
||||||
|
_handleSelectDateRangeResult(context, startDate, endDate);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleSelectDateRangeResult(
|
||||||
|
BuildContext context,
|
||||||
|
DateTime? startDate,
|
||||||
|
DateTime? endDate
|
||||||
|
) {
|
||||||
|
log('AdvancedFilterController::_handleSelectDateRangeResult(): startDate: $startDate');
|
||||||
|
log('AdvancedFilterController::_handleSelectDateRangeResult(): endDate: $endDate');
|
||||||
|
if (startDate == null) {
|
||||||
|
_appToast.showToastWithIcon(
|
||||||
|
context,
|
||||||
|
textColor: Colors.black,
|
||||||
|
message: AppLocalizations.of(context).toastMessageErrorWhenSelectStartDateIsEmpty,
|
||||||
|
icon: _imagePaths.icNotConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (endDate == null) {
|
||||||
|
_appToast.showToastWithIcon(
|
||||||
|
context,
|
||||||
|
textColor: Colors.black,
|
||||||
|
message: AppLocalizations.of(context).toastMessageErrorWhenSelectEndDateIsEmpty,
|
||||||
|
icon: _imagePaths.icNotConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endDate.isBefore(startDate)) {
|
||||||
|
_appToast.showToastWithIcon(
|
||||||
|
context,
|
||||||
|
textColor: Colors.black,
|
||||||
|
message: AppLocalizations.of(context).toastMessageErrorWhenSelectDateIsInValid,
|
||||||
|
icon: _imagePaths.icNotConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_startDate = startDate;
|
||||||
|
_endDate = endDate;
|
||||||
|
dateFilterSelectedFormAdvancedSearch.value = EmailReceiveTimeType.customRange;
|
||||||
|
dateFilterInputController.text = EmailReceiveTimeType.customRange.getTitle(
|
||||||
|
context,
|
||||||
|
startDate: startDate,
|
||||||
|
endDate: endDate);
|
||||||
|
dateFilterSelectedFormAdvancedSearch.refresh();
|
||||||
|
|
||||||
|
popBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearDateRangeOfFilter() {
|
||||||
|
_startDate = null;
|
||||||
|
_endDate = null;
|
||||||
|
|
||||||
|
searchController.searchEmailFilter.value =
|
||||||
|
searchController.searchEmailFilter.value.withDateRange(
|
||||||
|
startDate: _startDate.toUTCDate(),
|
||||||
|
endDate: _endDate.toUTCDate());
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
focusManager.dispose();
|
focusManager.dispose();
|
||||||
|
|||||||
@@ -129,6 +129,8 @@ class SearchController extends BaseController {
|
|||||||
EmailReceiveTimeType? emailReceiveTimeType,
|
EmailReceiveTimeType? emailReceiveTimeType,
|
||||||
bool? hasAttachment,
|
bool? hasAttachment,
|
||||||
UTCDate? before,
|
UTCDate? before,
|
||||||
|
UTCDate? startDate,
|
||||||
|
UTCDate? endDate,
|
||||||
}) {
|
}) {
|
||||||
searchEmailFilter.value = searchEmailFilter.value.copyWith(
|
searchEmailFilter.value = searchEmailFilter.value.copyWith(
|
||||||
from: from,
|
from: from,
|
||||||
@@ -140,6 +142,8 @@ class SearchController extends BaseController {
|
|||||||
emailReceiveTimeType: emailReceiveTimeType,
|
emailReceiveTimeType: emailReceiveTimeType,
|
||||||
hasAttachment: hasAttachment,
|
hasAttachment: hasAttachment,
|
||||||
before: before,
|
before: before,
|
||||||
|
startDate: startDate,
|
||||||
|
endDate: endDate,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-6
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
|
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
|
||||||
|
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
enum EmailReceiveTimeType {
|
enum EmailReceiveTimeType {
|
||||||
@@ -8,9 +9,10 @@ enum EmailReceiveTimeType {
|
|||||||
last7Days,
|
last7Days,
|
||||||
last30Days,
|
last30Days,
|
||||||
last6Months,
|
last6Months,
|
||||||
lastYear;
|
lastYear,
|
||||||
|
customRange;
|
||||||
|
|
||||||
String getTitle(BuildContext context) {
|
String getTitle(BuildContext context, {DateTime? startDate, DateTime? endDate}) {
|
||||||
switch(this) {
|
switch(this) {
|
||||||
case EmailReceiveTimeType.allTime:
|
case EmailReceiveTimeType.allTime:
|
||||||
return AppLocalizations.of(context).allTime;
|
return AppLocalizations.of(context).allTime;
|
||||||
@@ -22,6 +24,16 @@ enum EmailReceiveTimeType {
|
|||||||
return AppLocalizations.of(context).last6Months;
|
return AppLocalizations.of(context).last6Months;
|
||||||
case EmailReceiveTimeType.lastYear:
|
case EmailReceiveTimeType.lastYear:
|
||||||
return AppLocalizations.of(context).lastYears;
|
return AppLocalizations.of(context).lastYears;
|
||||||
|
case EmailReceiveTimeType.customRange:
|
||||||
|
if (startDate != null && endDate != null) {
|
||||||
|
final startDateString = startDate.formatDate(pattern: 'yyyy-dd-MM');
|
||||||
|
final endDateString = endDate.formatDate(pattern: 'yyyy-dd-MM');
|
||||||
|
return AppLocalizations.of(context).dateRangeAdvancedSearchFilter(
|
||||||
|
startDateString,
|
||||||
|
endDateString);
|
||||||
|
} else {
|
||||||
|
return AppLocalizations.of(context).customRange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,13 +42,23 @@ enum EmailReceiveTimeType {
|
|||||||
case EmailReceiveTimeType.allTime:
|
case EmailReceiveTimeType.allTime:
|
||||||
return null;
|
return null;
|
||||||
case EmailReceiveTimeType.last7Days:
|
case EmailReceiveTimeType.last7Days:
|
||||||
return UTCDate(DateTime.now().subtract(const Duration(days: 7)));
|
final today = DateTime.now();
|
||||||
|
final last7Days = today.subtract(const Duration(days: 7));
|
||||||
|
return last7Days.toUTCDate();
|
||||||
case EmailReceiveTimeType.last30Days:
|
case EmailReceiveTimeType.last30Days:
|
||||||
return UTCDate(DateTime.now().subtract(const Duration(days: 30)));
|
final today = DateTime.now();
|
||||||
|
final last30Days = today.subtract(const Duration(days: 30));
|
||||||
|
return last30Days.toUTCDate();
|
||||||
case EmailReceiveTimeType.last6Months:
|
case EmailReceiveTimeType.last6Months:
|
||||||
return UTCDate(DateTime.now().subtract(const Duration(days: 180)));
|
final today = DateTime.now();
|
||||||
|
final last6months = DateTime(today.year, today.month - 6, today.day);
|
||||||
|
return last6months.toUTCDate();
|
||||||
case EmailReceiveTimeType.lastYear:
|
case EmailReceiveTimeType.lastYear:
|
||||||
return UTCDate(DateTime.now().subtract(const Duration(days: 365)));
|
final today = DateTime.now();
|
||||||
|
final lastYear = DateTime(today.year - 1, today.month, today.day);
|
||||||
|
return lastYear.toUTCDate();
|
||||||
|
case EmailReceiveTimeType.customRange:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ class SearchEmailFilter {
|
|||||||
final EmailReceiveTimeType emailReceiveTimeType;
|
final EmailReceiveTimeType emailReceiveTimeType;
|
||||||
final bool hasAttachment;
|
final bool hasAttachment;
|
||||||
final UTCDate? before;
|
final UTCDate? before;
|
||||||
|
final UTCDate? startDate;
|
||||||
|
final UTCDate? endDate;
|
||||||
|
|
||||||
SearchEmailFilter({
|
SearchEmailFilter({
|
||||||
Set<String>? from,
|
Set<String>? from,
|
||||||
@@ -28,6 +30,8 @@ class SearchEmailFilter {
|
|||||||
Set<String>? notKeyword,
|
Set<String>? notKeyword,
|
||||||
this.mailbox,
|
this.mailbox,
|
||||||
this.before,
|
this.before,
|
||||||
|
this.startDate,
|
||||||
|
this.endDate,
|
||||||
}) : from = from ?? <String>{},
|
}) : from = from ?? <String>{},
|
||||||
to = to ?? <String>{},
|
to = to ?? <String>{},
|
||||||
notKeyword = notKeyword ?? <String>{},
|
notKeyword = notKeyword ?? <String>{},
|
||||||
@@ -45,6 +49,8 @@ class SearchEmailFilter {
|
|||||||
EmailReceiveTimeType? emailReceiveTimeType,
|
EmailReceiveTimeType? emailReceiveTimeType,
|
||||||
bool? hasAttachment,
|
bool? hasAttachment,
|
||||||
UTCDate? before,
|
UTCDate? before,
|
||||||
|
UTCDate? startDate,
|
||||||
|
UTCDate? endDate,
|
||||||
}) {
|
}) {
|
||||||
return SearchEmailFilter(
|
return SearchEmailFilter(
|
||||||
from: from ?? this.from,
|
from: from ?? this.from,
|
||||||
@@ -56,6 +62,8 @@ class SearchEmailFilter {
|
|||||||
emailReceiveTimeType: emailReceiveTimeType ?? this.emailReceiveTimeType,
|
emailReceiveTimeType: emailReceiveTimeType ?? this.emailReceiveTimeType,
|
||||||
hasAttachment: hasAttachment ?? this.hasAttachment,
|
hasAttachment: hasAttachment ?? this.hasAttachment,
|
||||||
before: before ?? this.before,
|
before: before ?? this.before,
|
||||||
|
startDate: startDate ?? this.startDate,
|
||||||
|
endDate: endDate ?? this.endDate,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,10 +75,14 @@ class SearchEmailFilter {
|
|||||||
inMailbox: mailbox == PresentationMailbox.unifiedMailbox
|
inMailbox: mailbox == PresentationMailbox.unifiedMailbox
|
||||||
? null
|
? null
|
||||||
: mailbox?.id,
|
: mailbox?.id,
|
||||||
after: emailReceiveTimeType.toUTCDate(),
|
after: emailReceiveTimeType == EmailReceiveTimeType.customRange
|
||||||
|
? startDate
|
||||||
|
: emailReceiveTimeType.toUTCDate(),
|
||||||
hasAttachment: hasAttachment == false ? null : hasAttachment,
|
hasAttachment: hasAttachment == false ? null : hasAttachment,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
before: before,
|
before: emailReceiveTimeType == EmailReceiveTimeType.customRange
|
||||||
|
? endDate
|
||||||
|
: before,
|
||||||
);
|
);
|
||||||
|
|
||||||
final listEmailCondition = {
|
final listEmailCondition = {
|
||||||
@@ -113,4 +125,20 @@ extension SearchEmailFilterExtension on SearchEmailFilter {
|
|||||||
before: newBefore,
|
before: newBefore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SearchEmailFilter withDateRange({UTCDate? startDate, UTCDate? endDate}) {
|
||||||
|
return SearchEmailFilter(
|
||||||
|
from: from,
|
||||||
|
to: to,
|
||||||
|
text: text,
|
||||||
|
subject: subject,
|
||||||
|
notKeyword: notKeyword,
|
||||||
|
mailbox: mailbox,
|
||||||
|
emailReceiveTimeType: emailReceiveTimeType,
|
||||||
|
hasAttachment: hasAttachment,
|
||||||
|
before: before,
|
||||||
|
startDate: startDate,
|
||||||
|
endDate: endDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+37
-14
@@ -10,6 +10,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/sear
|
|||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/drop_down_button_filter_widget.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/drop_down_button_filter_widget.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_auto_complete_email_adress.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_auto_complete_email_adress.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController>
|
class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController>
|
||||||
with PopupContextMenuActionMixin {
|
with PopupContextMenuActionMixin {
|
||||||
@@ -70,18 +71,30 @@ class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController>
|
|||||||
nextFocusNode: controller.focusManager.attachmentCheckboxFocusNode,
|
nextFocusNode: controller.focusManager.attachmentCheckboxFocusNode,
|
||||||
mouseCursor: SystemMouseCursors.click,
|
mouseCursor: SystemMouseCursors.click,
|
||||||
onTap: () => controller.selectedMailBox()),
|
onTap: () => controller.selectedMailBox()),
|
||||||
_buildFilterField(
|
Row(children: [
|
||||||
textEditingController: controller.dateFilterInputController,
|
Expanded(child: _buildFilterField(
|
||||||
context: context,
|
textEditingController: controller.dateFilterInputController,
|
||||||
advancedSearchFilterField: AdvancedSearchFilterField.date,
|
context: context,
|
||||||
isSelectFormList: true,
|
advancedSearchFilterField: AdvancedSearchFilterField.date,
|
||||||
onTap: () {
|
isSelectFormList: true,
|
||||||
openContextMenuAction(
|
onTap: () {
|
||||||
context,
|
openContextMenuAction(
|
||||||
_buildEmailReceiveTimeTypeActionTiles(context),
|
context,
|
||||||
);
|
_buildEmailReceiveTimeTypeActionTiles(context),
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
|
)),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
buildIconWeb(
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
_imagePaths.icCalendarSB,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
fit: BoxFit.fill),
|
||||||
|
tooltip: AppLocalizations.of(context).selectDate,
|
||||||
|
iconPadding: EdgeInsets.zero,
|
||||||
|
onTap: () => controller.selectDateRange(context)),
|
||||||
|
]),
|
||||||
AdvancedSearchFilterFormBottomView(focusManager: controller.focusManager)
|
AdvancedSearchFilterFormBottomView(focusManager: controller.focusManager)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -95,7 +108,11 @@ class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController>
|
|||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(e.getTitle(context),
|
child: Text(
|
||||||
|
e.getTitle(
|
||||||
|
context,
|
||||||
|
startDate: controller.startDate,
|
||||||
|
endDate: controller.endDate),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
@@ -112,8 +129,14 @@ class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController>
|
|||||||
]
|
]
|
||||||
]),
|
]),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
if (e != EmailReceiveTimeType.customRange) {
|
||||||
|
controller.clearDateRangeOfFilter();
|
||||||
|
}
|
||||||
controller.dateFilterSelectedFormAdvancedSearch.value = e;
|
controller.dateFilterSelectedFormAdvancedSearch.value = e;
|
||||||
controller.dateFilterInputController.text = e.getTitle(context);
|
controller.dateFilterInputController.text = e.getTitle(
|
||||||
|
context,
|
||||||
|
startDate: controller.startDate,
|
||||||
|
endDate: controller.endDate);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
+19
-3
@@ -17,8 +17,17 @@ class DateDropDownButton extends GetWidget<AdvancedFilterController> {
|
|||||||
items: EmailReceiveTimeType.values,
|
items: EmailReceiveTimeType.values,
|
||||||
itemSelected: controller.dateFilterSelectedFormAdvancedSearch.value,
|
itemSelected: controller.dateFilterSelectedFormAdvancedSearch.value,
|
||||||
context: context,
|
context: context,
|
||||||
|
startDate: controller.startDate,
|
||||||
|
endDate: controller.endDate,
|
||||||
onChanged: (item) {
|
onChanged: (item) {
|
||||||
|
if (item != EmailReceiveTimeType.customRange) {
|
||||||
|
controller.clearDateRangeOfFilter();
|
||||||
|
}
|
||||||
controller.dateFilterSelectedFormAdvancedSearch.value = item!;
|
controller.dateFilterSelectedFormAdvancedSearch.value = item!;
|
||||||
|
controller.dateFilterInputController.text = item.getTitle(
|
||||||
|
context,
|
||||||
|
startDate: controller.startDate,
|
||||||
|
endDate: controller.endDate);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -30,6 +39,8 @@ Widget _buildDropDownButton<T>({
|
|||||||
required T itemSelected,
|
required T itemSelected,
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required Function(T?)? onChanged,
|
required Function(T?)? onChanged,
|
||||||
|
DateTime? startDate,
|
||||||
|
DateTime? endDate
|
||||||
}) {
|
}) {
|
||||||
final ImagePaths _imagePaths = Get.find<ImagePaths>();
|
final ImagePaths _imagePaths = Get.find<ImagePaths>();
|
||||||
|
|
||||||
@@ -43,6 +54,8 @@ Widget _buildDropDownButton<T>({
|
|||||||
StringConvert.writeNullToEmpty(_getTextItemDropdown<T>(
|
StringConvert.writeNullToEmpty(_getTextItemDropdown<T>(
|
||||||
item: item,
|
item: item,
|
||||||
context: context,
|
context: context,
|
||||||
|
startDate: startDate,
|
||||||
|
endDate: endDate,
|
||||||
)),
|
)),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@@ -81,10 +94,13 @@ Widget _buildDropDownButton<T>({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _getTextItemDropdown<T>(
|
String? _getTextItemDropdown<T>({required T item,
|
||||||
{required T item, required BuildContext context}) {
|
required BuildContext context,
|
||||||
|
DateTime? startDate,
|
||||||
|
DateTime? endDate
|
||||||
|
}) {
|
||||||
if (item is EmailReceiveTimeType) {
|
if (item is EmailReceiveTimeType) {
|
||||||
return item.getTitle(context);
|
return item.getTitle(context, startDate: startDate, endDate: endDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item is Mailbox) {
|
if (item is Mailbox) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
|
||||||
|
|
||||||
extension DateTimeExtension on DateTime? {
|
extension DateTimeExtension on DateTime? {
|
||||||
|
|
||||||
@@ -17,6 +18,14 @@ extension DateTimeExtension on DateTime? {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UTCDate? toUTCDate() {
|
||||||
|
if (this != null) {
|
||||||
|
return UTCDate(this!.toUtc());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TimeOfDayExtension on TimeOfDay? {
|
extension TimeOfDayExtension on TimeOfDay? {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2022-09-30T17:54:08.425416",
|
"@@last_modified": "2022-10-05T22:55:58.696295",
|
||||||
"initializing_data": "Initializing data...",
|
"initializing_data": "Initializing data...",
|
||||||
"@initializing_data": {
|
"@initializing_data": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -2245,5 +2245,53 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"selectDate": "Select date",
|
||||||
|
"@selectDate": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"setDate": "Set date",
|
||||||
|
"@setDate": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"toastMessageErrorWhenSelectStartDateIsEmpty": "The start date cannot be null.",
|
||||||
|
"@toastMessageErrorWhenSelectStartDateIsEmpty": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"toastMessageErrorWhenSelectEndDateIsEmpty": "The end date cannot be null.",
|
||||||
|
"@toastMessageErrorWhenSelectEndDateIsEmpty": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"toastMessageErrorWhenSelectDateIsInValid": "The end time cannot be less than the start time.",
|
||||||
|
"@toastMessageErrorWhenSelectDateIsInValid": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"dateRangeAdvancedSearchFilter": "From {startDate} to {endDate}",
|
||||||
|
"@dateRangeAdvancedSearchFilter": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [
|
||||||
|
"startDate",
|
||||||
|
"endDate"
|
||||||
|
],
|
||||||
|
"placeholders": {
|
||||||
|
"startDate": {},
|
||||||
|
"endDate": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"customRange": "Custom range",
|
||||||
|
"@customRange": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2327,4 +2327,54 @@ class AppLocalizations {
|
|||||||
name: 'titleForeground'
|
name: 'titleForeground'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get selectDate {
|
||||||
|
return Intl.message(
|
||||||
|
'Select date',
|
||||||
|
name: 'selectDate',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get setDate {
|
||||||
|
return Intl.message(
|
||||||
|
'Set date',
|
||||||
|
name: 'setDate',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get toastMessageErrorWhenSelectStartDateIsEmpty {
|
||||||
|
return Intl.message(
|
||||||
|
'The start date cannot be null.',
|
||||||
|
name: 'toastMessageErrorWhenSelectStartDateIsEmpty',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get toastMessageErrorWhenSelectEndDateIsEmpty {
|
||||||
|
return Intl.message(
|
||||||
|
'The end date cannot be null.',
|
||||||
|
name: 'toastMessageErrorWhenSelectEndDateIsEmpty',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get toastMessageErrorWhenSelectDateIsInValid {
|
||||||
|
return Intl.message(
|
||||||
|
'The end time cannot be less than the start time.',
|
||||||
|
name: 'toastMessageErrorWhenSelectDateIsInValid',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String dateRangeAdvancedSearchFilter(String startDate, String endDate) {
|
||||||
|
return Intl.message(
|
||||||
|
'From $startDate to $endDate',
|
||||||
|
name: 'dateRangeAdvancedSearchFilter',
|
||||||
|
args: [startDate, endDate]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get customRange {
|
||||||
|
return Intl.message(
|
||||||
|
'Custom range',
|
||||||
|
name: 'customRange');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+35
-5
@@ -481,6 +481,15 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "1.0.3"
|
||||||
|
flutter_date_range_picker:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: master
|
||||||
|
resolved-ref: c04608f5daad5e96daf0f419946ad0db23c46811
|
||||||
|
url: "https://github.com/linagora/flutter-date-range-picker.git"
|
||||||
|
source: git
|
||||||
|
version: "1.0.0"
|
||||||
flutter_dotenv:
|
flutter_dotenv:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -891,7 +900,7 @@ packages:
|
|||||||
name: package_info_plus_web
|
name: package_info_plus_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.0.6"
|
||||||
package_info_plus_windows:
|
package_info_plus_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -955,6 +964,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.3"
|
version: "2.1.3"
|
||||||
|
pattern_formatter:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pattern_formatter
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -989,7 +1005,7 @@ packages:
|
|||||||
name: permission_handler_apple
|
name: permission_handler_apple
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.0.4"
|
version: "9.0.6"
|
||||||
permission_handler_platform_interface:
|
permission_handler_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1003,7 +1019,7 @@ packages:
|
|||||||
name: permission_handler_windows
|
name: permission_handler_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.0"
|
version: "0.1.1"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1088,7 +1104,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: master
|
ref: master
|
||||||
resolved-ref: "85fe10cd4d3b29bbf803ac796ebe722710fa1d36"
|
resolved-ref: "45ed9a973331ac4209917e365792967d7ca7b5bb"
|
||||||
url: "https://github.com/linagora/rich-text-composer.git"
|
url: "https://github.com/linagora/rich-text-composer.git"
|
||||||
source: git
|
source: git
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
@@ -1251,6 +1267,20 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
|
syncfusion_flutter_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: syncfusion_flutter_core
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "20.3.48"
|
||||||
|
syncfusion_flutter_datepicker:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: syncfusion_flutter_datepicker
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "20.3.48"
|
||||||
synchronized:
|
synchronized:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1425,7 +1455,7 @@ packages:
|
|||||||
name: webview_flutter_android
|
name: webview_flutter_android
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.10.3"
|
version: "2.10.4"
|
||||||
webview_flutter_platform_interface:
|
webview_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -191,6 +191,11 @@ dependencies:
|
|||||||
|
|
||||||
byte_converter: 1.3.0
|
byte_converter: 1.3.0
|
||||||
|
|
||||||
|
flutter_date_range_picker:
|
||||||
|
git:
|
||||||
|
url: https://github.com/linagora/flutter-date-range-picker.git
|
||||||
|
ref: master
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
Reference in New Issue
Block a user