TF-4004 Apply new design for create rule view on web

This commit is contained in:
dab246
2025-09-08 14:30:17 +07:00
committed by Dat H. Pham
parent dc3b4d46dd
commit 8c3c7b1feb
24 changed files with 819 additions and 764 deletions
@@ -9,6 +9,8 @@ typedef OnTextChange = void Function(String text);
class DefaultInputFieldWidget extends StatelessWidget {
final TextEditingController textEditingController;
final String? hintText;
final String? errorText;
final Color? inputColor;
final FocusNode? focusNode;
final OnTextChange? onTextChange;
final OnTextSubmitted? onTextSubmitted;
@@ -17,7 +19,9 @@ class DefaultInputFieldWidget extends StatelessWidget {
super.key,
required this.textEditingController,
this.hintText,
this.errorText,
this.focusNode,
this.inputColor,
this.onTextChange,
this.onTextSubmitted,
});
@@ -29,16 +33,22 @@ class DefaultInputFieldWidget extends StatelessWidget {
maxLines: 1,
textInputAction: TextInputAction.next,
textStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.m3SurfaceBackground,
color: inputColor ?? AppColor.m3SurfaceBackground,
),
focusNode: focusNode,
onTextSubmitted: onTextSubmitted,
onTextChange: onTextChange,
decoration: InputDecoration(
constraints: const BoxConstraints(maxHeight: 40),
constraints: BoxConstraints(
maxHeight: errorText?.isNotEmpty == true ? 60 : 40,
),
filled: true,
fillColor: Colors.white,
contentPadding: const EdgeInsetsDirectional.only(start: 12, end: 8),
fillColor: errorText?.isNotEmpty == true
? AppColor.colorInputBackgroundErrorVerifyName
: Colors.white,
contentPadding: errorText?.isNotEmpty == true
? const EdgeInsetsDirectional.only(start: 12, end: 8)
: const EdgeInsetsDirectional.only(start: 12, end: 8, top: 12, bottom: 12),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(width: 1, color: AppColor.m3Neutral90),
@@ -51,8 +61,18 @@ class DefaultInputFieldWidget extends StatelessWidget {
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(width: 1, color: AppColor.primaryColor),
),
errorBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(width: 1, color: AppColor.redFF3347),
),
focusedErrorBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(width: 1, color: AppColor.redFF3347),
),
hintText: hintText,
hintStyle: ThemeUtils.textStyleBodyBody3(color: AppColor.m3Tertiary),
errorText: errorText,
errorStyle: ThemeUtils.textStyleBodyBody3(color: AppColor.redFF3347),
),
);
}
@@ -35,6 +35,8 @@ class DropDownButtonWidget<T> extends StatelessWidget {
final double? dropdownWidth;
final double? dropdownMaxHeight;
final String? hintText;
final TextStyle? labelTextStyle;
final TextStyle? hintTextStyle;
const DropDownButtonWidget({
Key? key,
@@ -54,6 +56,8 @@ class DropDownButtonWidget<T> extends StatelessWidget {
this.colorButton = Colors.white,
this.tooltip = '',
this.hintText,
this.labelTextStyle,
this.hintTextStyle,
}) : super(key: key);
@override
@@ -68,7 +72,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
? Row(children: [
Expanded(child: Text(
_getTextItemDropdown(context, item: itemSelected),
style: ThemeUtils.defaultTextStyleInterFont.copyWith(fontSize: 16,
style: hintTextStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black.withValues(alpha: opacity)),
maxLines: 1,
@@ -86,7 +90,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
height: heightItem,
child: Row(children: [
Expanded(child: Text(_getTextItemDropdown(context, item: item),
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
style: labelTextStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black),
@@ -122,7 +126,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
child: Row(children: [
Expanded(child: Text(
_getTextItemDropdown(context, item: itemSelected),
style: ThemeUtils.defaultTextStyleInterFont.copyWith(fontSize: 16,
style: labelTextStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(fontSize: 16,
fontWeight: FontWeight.normal,
color: itemSelected != null ? Colors.black.withValues(alpha: opacity) : AppColor.textFieldHintColor),
maxLines: 1,
@@ -7,8 +7,12 @@ class LabelInputFieldBuilder extends StatelessWidget {
final TextEditingController textEditingController;
final String? errorText;
final String? hintText;
final TextStyle? labelStyle;
final FocusNode? focusNode;
final double? runSpacing;
final double? inputFieldMaxWidth;
final bool arrangeHorizontally;
final bool isLabelHasColon;
final OnTextChange? onTextChange;
const LabelInputFieldBuilder({
@@ -16,19 +20,24 @@ class LabelInputFieldBuilder extends StatelessWidget {
required this.label,
required this.textEditingController,
this.arrangeHorizontally = true,
this.isLabelHasColon = true,
this.hintText,
this.errorText,
this.focusNode,
this.labelStyle,
this.runSpacing,
this.inputFieldMaxWidth,
this.onTextChange,
});
@override
Widget build(BuildContext context) {
Widget bodyWidget = ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 565),
constraints: BoxConstraints(maxWidth: inputFieldMaxWidth ?? 565),
child: DefaultInputFieldWidget(
textEditingController: textEditingController,
hintText: hintText,
errorText: errorText,
focusNode: focusNode,
onTextChange: onTextChange,
),
@@ -41,7 +50,7 @@ class LabelInputFieldBuilder extends StatelessWidget {
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 83),
child: Text(
'$label:',
isLabelHasColon ? '$label:' : label,
style: ThemeUtils.textStyleBodyBody3(color: Colors.black),
),
),
@@ -54,10 +63,10 @@ class LabelInputFieldBuilder extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'$label:',
style: ThemeUtils.textStyleBodyBody3(color: Colors.black),
isLabelHasColon ? '$label:' : label,
style: labelStyle ?? ThemeUtils.textStyleBodyBody3(color: Colors.black),
),
const SizedBox(height: 10),
SizedBox(height: runSpacing ?? 10),
bodyWidget,
],
);
@@ -10,33 +10,37 @@ import 'package:tmail_ui_user/main/routes/route_utils.dart';
extension PresentationMailboxExtension on PresentationMailbox {
String getDisplayName(BuildContext context) {
String getDisplayNameByLocalizations(AppLocalizations appLocalizations) {
if (isDefault) {
switch(role!.value.toLowerCase()) {
case PresentationMailbox.inboxRole:
return AppLocalizations.of(context).inboxMailboxDisplayName;
return appLocalizations.inboxMailboxDisplayName;
case PresentationMailbox.archiveRole:
return AppLocalizations.of(context).archiveMailboxDisplayName;
return appLocalizations.archiveMailboxDisplayName;
case PresentationMailbox.draftsRole:
return AppLocalizations.of(context).draftsMailboxDisplayName;
return appLocalizations.draftsMailboxDisplayName;
case PresentationMailbox.sentRole:
return AppLocalizations.of(context).sentMailboxDisplayName;
return appLocalizations.sentMailboxDisplayName;
case PresentationMailbox.outboxRole:
return AppLocalizations.of(context).outboxMailboxDisplayName;
return appLocalizations.outboxMailboxDisplayName;
case PresentationMailbox.trashRole:
return AppLocalizations.of(context).trashMailboxDisplayName;
return appLocalizations.trashMailboxDisplayName;
case PresentationMailbox.spamRole:
case PresentationMailbox.junkRole:
return AppLocalizations.of(context).spamMailboxDisplayName;
return appLocalizations.spamMailboxDisplayName;
case PresentationMailbox.templatesRole:
return AppLocalizations.of(context).templatesMailboxDisplayName;
return appLocalizations.templatesMailboxDisplayName;
case PresentationMailbox.recoveredRole:
return AppLocalizations.of(context).recoveredMailboxDisplayName;
return appLocalizations.recoveredMailboxDisplayName;
}
}
return name?.name ?? '';
}
String getDisplayName(BuildContext context) {
return getDisplayNameByLocalizations(AppLocalizations.of(context));
}
String getMailboxIcon(ImagePaths imagePaths) {
if (hasRole()) {
switch(role!.value) {
@@ -7,12 +7,12 @@ enum CreatorActionType {
create,
edit;
String getTitle(BuildContext context) {
String getTitle(AppLocalizations appLocalizations) {
switch(this) {
case CreatorActionType.create:
return AppLocalizations.of(context).createNewRule.inCaps;
return appLocalizations.createANewRule;
case CreatorActionType.edit:
return AppLocalizations.of(context).editRule.inCaps;
return appLocalizations.editRule.capitalizeFirstEach;
}
}
@@ -3,19 +3,19 @@ import 'package:flutter/material.dart';
class RulesFilterInputFieldArguments with EquatableMixin {
final FocusNode focusNode;
final String errorText;
final TextEditingController controller;
final String? errorText;
RulesFilterInputFieldArguments({
required this.focusNode,
required this.errorText,
required this.controller,
this.errorText,
});
@override
List<Object?> get props => [
focusNode,
errorText,
controller,
errorText,
];
}
@@ -166,7 +166,6 @@ class RulesFilterCreatorController extends BaseMailboxController {
listRuleCondition.add(newRuleCondition);
RulesFilterInputFieldArguments newRuleConditionValueArguments = RulesFilterInputFieldArguments(
focusNode: FocusNode(),
errorText: '',
controller: TextEditingController(),
);
listRuleConditionValueArguments.add(newRuleConditionValueArguments);
@@ -207,7 +206,6 @@ class RulesFilterCreatorController extends BaseMailboxController {
listRuleCondition.add(condition);
RulesFilterInputFieldArguments newRuleConditionValueArguments = RulesFilterInputFieldArguments(
focusNode: FocusNode(),
errorText: '',
controller: TextEditingController(),
);
listRuleConditionValueArguments.add(newRuleConditionValueArguments);
@@ -300,7 +298,7 @@ class RulesFilterCreatorController extends BaseMailboxController {
String? errorString = _getErrorStringByInputValue(context, listRuleCondition[ruleConditionIndex].value);
RulesFilterInputFieldArguments newRuleConditionValueArguments = RulesFilterInputFieldArguments(
focusNode: listRuleConditionValueArguments[ruleConditionIndex].focusNode,
errorText: errorString ?? '',
errorText: errorString,
controller: listRuleConditionValueArguments[ruleConditionIndex].controller,
);
if (listRuleConditionValueArguments.length > ruleConditionIndex) {
@@ -611,7 +609,6 @@ class RulesFilterCreatorController extends BaseMailboxController {
listRuleCondition.add(newRuleCondition);
listRuleConditionValueArguments.add(RulesFilterInputFieldArguments(
focusNode: FocusNode(),
errorText: '',
controller: TextEditingController(),
));
}
@@ -1,16 +1,22 @@
import 'dart:math' as math;
import 'package:core/core.dart';
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:rule_filter/rule_filter/rule_condition_group.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_close_button_widget.dart';
import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart';
import 'package:tmail_ui_user/features/base/widget/pop_back_barrier_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensions/select_rule_action_field_extension.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_action_arguments.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_condition_type.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/styles/rule_filter_action_styles.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_list.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_list_action_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_title_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -25,402 +31,258 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
@override
Widget build(BuildContext context) {
final responsiveUtil = controller.responsiveUtils;
final isMobile = responsiveUtil.isMobile(context);
final focusScope = FocusScope.of(context);
final currentScreenHeight = responsiveUtil.getSizeScreenHeight(context);
final currentScreenWidth = responsiveUtil.getSizeScreenWidth(context);
return PointerInterceptor(
child: ResponsiveWidget(
responsiveUtils: responsiveUtil,
mobile: Scaffold(
backgroundColor:
PlatformInfo.isWeb ? Colors.black.withAlpha(24) : Colors.black38,
body: PopBackBarrierWidget(
child: SafeArea(
bottom: false,
left: false,
right: false,
child: GestureDetector(
onTap: focusScope.unfocus,
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(
top: Radius.circular(16),
),
color: Colors.white,
),
margin: EdgeInsets.only(top: PlatformInfo.isWeb ? 70 : 0),
child: SafeArea(
child: _buildRulesFilterFormOnMobile(context),
),
),
if (!isMobile) {
return Center(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(16)),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 24,
offset: const Offset(0, 2),
),
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 2,
),
],
),
width: math.min(
currentScreenWidth,
612,
),
constraints: BoxConstraints(
maxHeight: math.min(
currentScreenHeight - 100,
674,
),
),
clipBehavior: Clip.antiAlias,
child: _buildRulesFilterFormOnDesktop(context),
),
tablet: Scaffold(
backgroundColor: Colors.black.withAlpha(24),
body: PopBackBarrierWidget(
child: Align(
alignment: Alignment.bottomCenter,
child: GestureDetector(
onTap: focusScope.unfocus,
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
top: Radius.circular(16),
),
);
}
return ResponsiveWidget(
responsiveUtils: responsiveUtil,
mobile: Scaffold(
backgroundColor:
PlatformInfo.isWeb ? Colors.black.withAlpha(24) : Colors.black38,
body: PopBackBarrierWidget(
child: SafeArea(
bottom: false,
left: false,
right: false,
child: GestureDetector(
onTap: focusScope.unfocus,
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(
top: Radius.circular(16),
),
height: responsiveUtil.getSizeScreenHeight(context) * 0.7,
child: _buildRulesFilterFormOnTablet(context),
),
),
),
),
),
desktop: Scaffold(
backgroundColor: Colors.black.withAlpha(24),
body: PopBackBarrierWidget(
child: Center(
child: GestureDetector(
onTap: focusScope.unfocus,
child: Card(
color: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
),
clipBehavior: Clip.hardEdge,
child: SizedBox(
width: responsiveUtil.getSizeScreenWidth(context) * 0.6,
height: responsiveUtil.getSizeScreenHeight(context) * 0.7,
child: _buildRulesFilterFormOnDesktop(context),
),
),
margin: EdgeInsets.only(top: PlatformInfo.isWeb ? 70 : 0),
child: SafeArea(
child: _buildRulesFilterFormOnMobile(context),
),
),
),
),
),
),
tablet: Scaffold(
backgroundColor: Colors.black.withAlpha(24),
body: Center(
child: GestureDetector(
onTap: focusScope.unfocus,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(16)),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 24,
offset: const Offset(0, 2),
),
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 2,
),
],
),
width: math.min(
currentScreenWidth,
612,
),
constraints: BoxConstraints(
maxHeight: math.min(
currentScreenHeight - 100,
674,
),
),
clipBehavior: Clip.antiAlias,
child: _buildRulesFilterFormOnDesktop(context),
),
),
),
),
);
}
Widget _buildRulesFilterFormOnDesktop(BuildContext context) {
final appLocalizations = AppLocalizations.of(context);
return Stack(
children: [
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Container(
padding: const EdgeInsets.only(top: 16),
alignment: Alignment.center,
child: Obx(() => Text(
controller.actionType.value.getTitle(context),
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.black)))),
Expanded(child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Obx(() => RulesFilterInputField(
hintText: AppLocalizations.of(context).rulesNameHintTextInput,
errorText: controller.errorRuleName.value,
editingController: controller.inputRuleNameController,
focusNode: controller.inputRuleNameFocusNode,
onChangeAction: (value) => controller.updateRuleName(context, value),)),
const SizedBox(height: 24),
Obx(() => RuleFilterTitle(
conditionCombinerType: controller.conditionCombinerType.value,
tapActionCallback: (value) => controller.selectConditionCombiner(value),
ruleFilterConditionScreenType: RuleFilterConditionScreenType.desktop,
)),
const SizedBox(height: 24),
_buildListRuleFilterConditionList(context, RuleFilterConditionScreenType.desktop),
Container(
padding: const EdgeInsets.only(top: 8),
child: InkWell(
onTap: controller.tapAddCondition,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SvgPicture.asset(
controller.imagePaths.icAddNewFolder,
fit: BoxFit.fill,
),
const SizedBox(width: 15,),
Text(
AppLocalizations.of(context).addCondition,
maxLines: 1,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 17,
color: AppColor.primaryColor
)
)
],
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(top: 24, bottom: 12),
alignment: Alignment.center,
child: Obx(
() => Text(
controller.actionType.value.getTitle(appLocalizations),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
color: AppColor.m3SurfaceBackground,
),
),
),
const SizedBox(height: 24),
Text(AppLocalizations.of(context).actionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Obx(() {
return RuleFilterActionListWidget(
responsiveUtils: controller.responsiveUtils,
actionList: controller.listEmailRuleFilterActionSelected,
onActionChanged: (newAction, index) {
controller.updateEmailRuleFilterAction(context, newAction, index);
},
forwardEmailEditingController: controller.forwardEmailController,
forwardEmailFocusNode: controller.forwardEmailFocusNode,
onChangeForwardEmail: (value, index) => controller.updateForwardEmailValue(context, value, index),
tapActionDetailedCallback: (index) {
KeyboardUtils.hideKeyboard(context);
controller.selectMailbox(context, index);
},
tapRemoveCallback: (index) => controller.tapRemoveAction(index),
imagePaths: controller.imagePaths,
errorForwardEmail: controller.errorForwardEmailValue.value,
errorMailboxSelected: controller.errorMailboxSelectedValue.value,
);
}),
Obx(() {
if (controller.isShowAddAction.value == true) {
return Container(
padding: const EdgeInsets.only(top: 8),
child: InkWell(
onTap: controller.tapAddAction,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SvgPicture.asset(
controller.imagePaths.icAddNewFolder,
fit: BoxFit.fill,
),
const SizedBox(width: 15,),
Text(
AppLocalizations.of(context).addAction,
maxLines: RuleFilterActionStyles.maxLines,
style: RuleFilterActionStyles.addActionButtonTextStyle
)
],
),
),
);
} else {
return const SizedBox.shrink();
}
})
]
),
),
),
)),
Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
alignment: Alignment.centerRight,
color: Colors.white,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
buildTextButton(
AppLocalizations.of(context).cancel,
textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 17,
color: AppColor.colorTextButton),
backgroundColor: AppColor.emailAddressChipColor,
width: 128,
height: 44,
radius: 10,
onTap: () => controller.closeView(context)),
const SizedBox(width: 12),
Obx(() => buildTextButton(
controller.actionType.value.getActionName(context),
width: 128,
height: 44,
backgroundColor: AppColor.colorTextButton,
radius: 10,
onTap: () => controller.createNewRuleFilter(context))),
]
),
)
]),
Positioned(top: 8, right: 8,
child: buildIconWeb(
icon: SvgPicture.asset(
controller.imagePaths.icCircleClose,
fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () => controller.closeView(context)))
]
);
}
Widget _buildRulesFilterFormOnTablet(BuildContext context) {
return Stack(
children: [
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Container(
padding: const EdgeInsets.only(top: 16),
alignment: Alignment.center,
child: Obx(() => Text(
controller.actionType.value.getTitle(context),
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.black)))),
Expanded(child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
Expanded(
child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Obx(() => RulesFilterInputField(
hintText: AppLocalizations.of(context).rulesNameHintTextInput,
errorText: controller.errorRuleName.value,
editingController: controller.inputRuleNameController,
focusNode: controller.inputRuleNameFocusNode,
onChangeAction: (value) => controller.updateRuleName(context, value),)),
const SizedBox(height: 24),
Obx(() => RuleFilterTitle(
conditionCombinerType: controller.conditionCombinerType.value,
tapActionCallback: (value) => controller.selectConditionCombiner(value),
ruleFilterConditionScreenType: RuleFilterConditionScreenType.tablet,
)),
const SizedBox(height: 24),
_buildListRuleFilterConditionList(context, RuleFilterConditionScreenType.tablet),
Container(
padding: const EdgeInsets.only(top: 8),
child: InkWell(
onTap: controller.tapAddCondition,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SvgPicture.asset(
controller.imagePaths.icAddNewFolder,
fit: BoxFit.fill,
),
const SizedBox(width: 15,),
Text(
AppLocalizations.of(context).addCondition,
maxLines: 1,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 17,
color: AppColor.primaryColor
)
)
],
Obx(
() => LabelInputFieldBuilder(
label: appLocalizations.ruleName,
hintText: appLocalizations.rulesNameHintTextInput,
textEditingController:
controller.inputRuleNameController,
focusNode: controller.inputRuleNameFocusNode,
errorText: controller.errorRuleName.value,
arrangeHorizontally: false,
isLabelHasColon: false,
labelStyle: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
runSpacing: 16,
inputFieldMaxWidth: double.infinity,
onTextChange: (value) =>
controller.updateRuleName(context, value),
),
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 24,
),
child: Text(
appLocalizations.condition,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
),
const SizedBox(height: 24),
Text(AppLocalizations.of(context).actionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Obx(() {
return RuleFilterActionListWidget(
Obx(
() => RuleFilterTitle(
conditionCombinerType:
controller.conditionCombinerType.value,
responsiveUtils: controller.responsiveUtils,
actionList: controller.listEmailRuleFilterActionSelected,
onActionChanged: (newAction, index) {
controller.updateEmailRuleFilterAction(context, newAction, index);
},
forwardEmailEditingController: controller.forwardEmailController,
forwardEmailFocusNode: controller.forwardEmailFocusNode,
onChangeForwardEmail: (value, index) => controller.updateForwardEmailValue(context, value, index),
tapActionDetailedCallback: (index) {
KeyboardUtils.hideKeyboard(context);
controller.selectMailbox(context, index);
},
tapRemoveCallback: (index) => controller.tapRemoveAction(index),
imagePaths: controller.imagePaths,
errorForwardEmail: controller.errorForwardEmailValue.value,
errorMailboxSelected: controller.errorMailboxSelectedValue.value,
);
}),
tapActionCallback: (value) =>
controller.selectConditionCombiner(value),
ruleFilterConditionScreenType:
RuleFilterConditionScreenType.desktop,
),
),
const SizedBox(height: 8),
_buildListRuleFilterConditionList(
context,
RuleFilterConditionScreenType.desktop,
),
Container(
constraints: const BoxConstraints(minWidth: 161),
height: 36,
margin: const EdgeInsetsDirectional.only(top: 12),
child: ConfirmDialogButton(
label: AppLocalizations.of(context).addACondition,
backgroundColor: Colors.white,
textColor: AppColor.primaryMain,
borderColor: AppColor.primaryMain,
icon: controller.imagePaths.icAddIdentity,
onTapAction: controller.tapAddCondition,
),
),
Padding(
padding: const EdgeInsetsDirectional.only(
top: 24,
bottom: 8,
),
child: Text(
appLocalizations.actionsToPerform,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
),
_buildListRuleFilterActionList(context),
Obx(() {
if (controller.isShowAddAction.value == true) {
return Container(
padding: const EdgeInsets.only(top: 8),
child: InkWell(
onTap: controller.tapAddAction,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SvgPicture.asset(
controller.imagePaths.icAddNewFolder,
fit: BoxFit.fill,
),
const SizedBox(width: 15,),
Text(
AppLocalizations.of(context).addAction,
maxLines: RuleFilterActionStyles.maxLines,
style: RuleFilterActionStyles.addActionButtonTextStyle
)
],
),
constraints: const BoxConstraints(minWidth: 161),
height: 36,
margin: const EdgeInsetsDirectional.only(top: 4),
child: ConfirmDialogButton(
label: AppLocalizations.of(context).addAnAction,
backgroundColor: Colors.white,
textColor: AppColor.primaryMain,
borderColor: AppColor.primaryMain,
icon: controller.imagePaths.icAddIdentity,
onTapAction: controller.tapAddAction,
),
);
} else {
return const SizedBox.shrink();
}
})
]
}),
],
),
),
),
)),
Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
alignment: Alignment.center,
color: Colors.white,
child: Row(
children: [
Expanded(child: buildTextButton(
AppLocalizations.of(context).cancel,
textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 17,
color: AppColor.colorTextButton),
backgroundColor: AppColor.emailAddressChipColor,
width: 128,
height: 44,
radius: 10,
onTap: () => controller.closeView(context))),
const SizedBox(width: 12),
Expanded(child: Obx(() => buildTextButton(
controller.actionType.value.getActionName(context),
width: 128,
height: 44,
backgroundColor: AppColor.colorTextButton,
radius: 10,
onTap: () => controller.createNewRuleFilter(context)))),
]
),
)
]),
Positioned(top: 8, right: 8,
child: buildIconWeb(
icon: SvgPicture.asset(
controller.imagePaths.icCircleClose,
fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () => controller.closeView(context)))
]
),
RuleFilterListActionWidget(
positiveLabel: appLocalizations.createRule,
negativeLabel: appLocalizations.cancel,
padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 32),
onPositiveAction: () => controller.createNewRuleFilter(context),
onNegativeAction: () => controller.closeView(context),
),
],
),
DefaultCloseButtonWidget(
iconClose: controller.imagePaths.icCloseDialog,
onTapActionCallback: () => controller.closeView(context),
),
],
);
}
@@ -432,7 +294,7 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
padding: const EdgeInsets.only(top: 16),
alignment: Alignment.center,
child: Obx(() => Text(
controller.actionType.value.getTitle(context),
controller.actionType.value.getTitle(AppLocalizations.of(context)),
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.bold,
fontSize: 20,
@@ -456,6 +318,7 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
),
Obx(() => RuleFilterTitle(
conditionCombinerType: controller.conditionCombinerType.value,
responsiveUtils: controller.responsiveUtils,
ruleFilterConditionScreenType: RuleFilterConditionScreenType.mobile,
tapActionCallback: (_) {
controller.selectRuleConditionCombinerAction(
@@ -506,58 +369,26 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Obx(() {
return RuleFilterActionListWidget(
responsiveUtils: controller.responsiveUtils,
actionList: controller.listEmailRuleFilterActionSelected,
onActionChangeMobile: (currentAction, index) {
controller.selectRuleFilterAction(
context,
currentAction,
index
);
},
forwardEmailEditingController: controller.forwardEmailController,
forwardEmailFocusNode: controller.forwardEmailFocusNode,
onChangeForwardEmail: (value, index) => controller.updateForwardEmailValue(context, value, index),
tapActionDetailedCallback: (index) {
KeyboardUtils.hideKeyboard(context);
controller.selectMailbox(context, index);
},
tapRemoveCallback: (index) => controller.tapRemoveAction(index),
imagePaths: controller.imagePaths,
errorForwardEmail: controller.errorForwardEmailValue.value,
errorMailboxSelected: controller.errorMailboxSelectedValue.value,
);
}),
_buildListRuleFilterActionList(context),
Obx(() {
if (controller.isShowAddAction.value == true) {
return Container(
padding: const EdgeInsets.only(top: 12),
child: InkWell(
onTap: controller.tapAddAction,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
controller.imagePaths.icAddNewFolder,
fit: BoxFit.fill,
),
const SizedBox(width: 15,),
Text(
AppLocalizations.of(context).addAction,
maxLines: RuleFilterActionStyles.maxLines,
style: RuleFilterActionStyles.addActionButtonTextStyle
)
],
),
constraints: const BoxConstraints(minWidth: 161),
height: 36,
margin: const EdgeInsetsDirectional.only(top: 4),
child: ConfirmDialogButton(
label: AppLocalizations.of(context).addAnAction,
backgroundColor: Colors.white,
textColor: AppColor.primaryMain,
borderColor: AppColor.primaryMain,
icon: controller.imagePaths.icAddIdentity,
onTapAction: controller.tapAddAction,
),
);
} else {
return const SizedBox.shrink();
}
})
}),
]
),
),
@@ -604,21 +435,23 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
Widget _buildListRuleFilterConditionList(
BuildContext context,
RuleFilterConditionScreenType ruleFilterConditionScreenType
RuleFilterConditionScreenType ruleFilterConditionScreenType,
) {
return Obx(() {
return ListView.separated(
return ListView.builder(
shrinkWrap: true,
itemCount: controller.listRuleCondition.length,
itemBuilder: (context, index) {
final conditionItem =
controller.listRuleConditionValueArguments[index];
return RuleFilterConditionWidget(
key: ValueKey(controller.listRuleConditionValueArguments[index].focusNode),
key: ValueKey(conditionItem.focusNode),
ruleFilterConditionScreenType: ruleFilterConditionScreenType,
ruleCondition: controller.listRuleCondition[index],
imagePaths: controller.imagePaths,
conditionValueErrorText: controller.listRuleConditionValueArguments[index].errorText,
conditionValueFocusNode: controller.listRuleConditionValueArguments[index].focusNode,
conditionValueEditingController: controller.listRuleConditionValueArguments[index].controller,
conditionValueErrorText: conditionItem.errorText,
conditionValueFocusNode: conditionItem.focusNode,
textEditingController: conditionItem.controller,
tapRuleConditionFieldCallback: (value) =>
controller.selectRuleConditionFieldAction(
context,
@@ -637,11 +470,66 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
),
conditionValueOnChangeAction: (value) =>
controller.updateConditionValue(context, value, index),
tapRemoveRuleFilterConditionCallback: () => controller.tapRemoveCondition(index),
onDeleteRuleConditionAction: () =>
controller.tapRemoveCondition(index),
);
},
separatorBuilder: (context, index) {
return const SizedBox(height: 12,);
);
});
}
Widget _buildListRuleFilterActionList(BuildContext context) {
return Obx(() {
return ListView.builder(
shrinkWrap: true,
itemCount: controller.listEmailRuleFilterActionSelected.length,
padding: const EdgeInsetsDirectional.only(bottom: 8),
itemBuilder: (context, index) {
final currentAction = controller.listEmailRuleFilterActionSelected[index];
String? errorValue;
if (currentAction is ForwardActionArguments) {
errorValue = controller.errorForwardEmailValue.value;
} else {
errorValue = controller.errorMailboxSelectedValue.value;
}
return RuleFilterActionWidget(
responsiveUtils: controller.responsiveUtils,
mailboxSelected: currentAction is MoveMessageActionArguments
? currentAction.mailbox
: null,
errorValue: errorValue,
onActionChangeMobile: () {
controller.selectRuleFilterAction(
context,
currentAction.action,
index,
);
},
onActionChanged: (newAction) {
if (newAction != currentAction.action) {
controller.updateEmailRuleFilterAction(
context,
newAction,
index,
);
}
},
forwardEmailEditingController: currentAction.action == EmailRuleFilterAction.forwardTo
? controller.forwardEmailController
: null,
forwardEmailFocusNode: currentAction.action == EmailRuleFilterAction.forwardTo
? controller.forwardEmailFocusNode
: null,
onChangeForwardEmail: (value) => controller.updateForwardEmailValue(context, value, index),
actionSelected: currentAction.action,
tapActionDetailedCallback: () {
KeyboardUtils.hideKeyboard(context);
controller.selectMailbox(context, index);
},
onDeleteRuleConditionAction: () =>
controller.tapRemoveAction(index),
imagePaths: controller.imagePaths,
);
},
);
});
@@ -1,24 +1,7 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart';
class RuleFilterActionStyles {
static const double extentRatio = 0.1;
static const double removeButtonRadius = 110.0;
static const double mainPadding = 12.0;
static const double mainBorderRadius = 12.0;
static const int maxLines = 1;
static const double fontSize = 16.0;
static const Color color = Colors.black;
static TextStyle textStyle = ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.normal,
fontSize: fontSize,
color: color,
);
static const double itemDistance = 12.0;
static TextStyle addActionButtonTextStyle = ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 17.0,
color: AppColor.primaryColor,
);
}
}
@@ -1,15 +0,0 @@
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart';
class RuleFilterTitleStyles {
static const double fontSize = 16.0;
static const Color textColor = Colors.black;
static TextStyle textStyle = ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: fontSize,
color: textColor,
);
static const int textMaxLines = 1;
static const double combinerTypeSelectionAreaWith = 200.0;
static const double combinerTypeSelectionAreaPadding = 12.0;
}
@@ -1,6 +1,7 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
@@ -39,12 +40,13 @@ class RuleFilterActionDetailed extends StatelessWidget {
},
);
case EmailRuleFilterAction.forwardTo:
return RulesFilterInputField(
return DefaultInputFieldWidget(
errorText: errorValue,
hintText: AppLocalizations.of(context).forwardEmailHintText,
editingController: forwardEmailEditingController,
textEditingController: forwardEmailEditingController!,
focusNode: forwardEmailFocusNode,
onChangeAction: forwardEmailOnChangeAction,
inputColor: Colors.black,
onTextChange: forwardEmailOnChangeAction,
);
case EmailRuleFilterAction.maskAsSeen:
case EmailRuleFilterAction.starIt:
@@ -1,80 +0,0 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_action_arguments.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_widget.dart';
class RuleFilterActionListWidget extends StatelessWidget {
final ResponsiveUtils responsiveUtils;
final List<RuleFilterActionArguments> actionList;
final Function(EmailRuleFilterAction?, int)? onActionChangeMobile;
final Function(EmailRuleFilterAction?, int)? onActionChanged;
final TextEditingController? forwardEmailEditingController;
final FocusNode? forwardEmailFocusNode;
final Function(int)? tapActionDetailedCallback;
final Function(int)? tapRemoveCallback;
final ImagePaths? imagePaths;
final Function(String?, int)? onChangeForwardEmail;
final String? errorForwardEmail;
final String? errorMailboxSelected;
const RuleFilterActionListWidget({
Key? key,
required this.responsiveUtils,
required this.actionList,
this.onActionChangeMobile,
this.onActionChanged,
this.forwardEmailEditingController,
this.forwardEmailFocusNode,
this.tapActionDetailedCallback,
this.tapRemoveCallback,
this.imagePaths,
this.onChangeForwardEmail,
this.errorForwardEmail,
this.errorMailboxSelected,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Obx(() {
return ListView.separated(
shrinkWrap: true,
itemCount: actionList.length,
separatorBuilder: (context, index) {
return const SizedBox(height: 12,);
},
itemBuilder: (context, index) {
final RuleFilterActionArguments currentAction = actionList[index];
String? errorValue;
if (currentAction is ForwardActionArguments) {
errorValue = errorForwardEmail;
} else {
errorValue = errorMailboxSelected;
}
return RuleFilterActionWidget(
responsiveUtils: responsiveUtils,
mailboxSelected: currentAction is MoveMessageActionArguments ? currentAction.mailbox : null,
errorValue: errorValue,
onActionChangeMobile: () {
onActionChangeMobile!(currentAction.action, index);
},
onActionChanged: (newAction) {
if (newAction != currentAction.action) {
onActionChanged!(newAction, index);
}
},
forwardEmailEditingController: currentAction.action == EmailRuleFilterAction.forwardTo ? forwardEmailEditingController : null,
forwardEmailFocusNode: currentAction.action == EmailRuleFilterAction.forwardTo ? forwardEmailFocusNode : null,
onChangeForwardEmail: (value) => onChangeForwardEmail!(value, index),
actionSelected: currentAction.action,
tapActionDetailedCallback: () => tapActionDetailedCallback!(index),
tapRemoveCallback: () => tapRemoveCallback!(index),
imagePaths: imagePaths,
);
},
);
});
}
}
@@ -1,24 +1,25 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/style_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/styles/rule_filter_action_styles.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_detailed_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_remove_button_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RuleFilterActionRow extends StatelessWidget {
final List<EmailRuleFilterAction> actionList;
final ImagePaths imagePaths;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
final EmailRuleFilterAction? actionSelected;
final Function(EmailRuleFilterAction?)? onActionChanged;
final PresentationMailbox? mailboxSelected;
final String? errorValue;
final Function()? tapActionDetailedCallback;
final ImagePaths? imagePaths;
final Function()? tapRemoveActionCallback;
final TextEditingController? forwardEmailEditingController;
final FocusNode? forwardEmailFocusNode;
final OnChangeFilterInputAction? onChangeForwardEmail;
@@ -26,13 +27,13 @@ class RuleFilterActionRow extends StatelessWidget {
const RuleFilterActionRow({
Key? key,
required this.actionList,
required this.imagePaths,
required this.onDeleteRuleConditionAction,
this.actionSelected,
this.onActionChanged,
this.mailboxSelected,
this.errorValue,
this.tapActionDetailedCallback,
this.imagePaths,
this.tapRemoveActionCallback,
this.forwardEmailEditingController,
this.forwardEmailFocusNode,
this.onChangeForwardEmail,
@@ -40,9 +41,11 @@ class RuleFilterActionRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final supportedAction = actionList.where((action) => action.isSupported).toList();
final supportedAction = actionList
.where((action) => action.isSupported)
.toList();
return Row(
crossAxisAlignment: actionSelected == EmailRuleFilterAction.moveMessage ? CrossAxisAlignment.center : CrossAxisAlignment.start,
children: [
Expanded(
child: DropDownButtonWidget<EmailRuleFilterAction>(
@@ -51,41 +54,54 @@ class RuleFilterActionRow extends StatelessWidget {
onChanged: (newAction) => onActionChanged!(newAction),
supportSelectionIcon: true,
supportHint: true,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
hintText: AppLocalizations.of(context).selectAction,
),
),
actionSelected == EmailRuleFilterAction.moveMessage
? Padding(
padding: const EdgeInsets.symmetric(horizontal: RuleFilterActionStyles.mainPadding),
if (actionSelected == EmailRuleFilterAction.moveMessage)
...[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(
AppLocalizations.of(context).toFolder,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: RuleFilterActionStyles.maxLines,
style: RuleFilterActionStyles.textStyle,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
)
: SizedBox(
width: actionSelected == EmailRuleFilterAction.forwardTo ? RuleFilterActionStyles.itemDistance : 0,
),
Expanded(
child: RuleFilterActionDetailed(
actionType: actionSelected,
mailboxSelected: mailboxSelected,
errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode,
forwardEmailOnChangeAction: onChangeForwardEmail,
),
),
Container(
padding: const EdgeInsets.only(left: RuleFilterActionStyles.mainPadding),
alignment: Alignment.center,
child: RuleFilterConditionRemoveButton(
imagePath: imagePaths,
tapRemoveRuleFilterConditionCallback: tapRemoveActionCallback,
Expanded(
child: RuleFilterButtonField<PresentationMailbox>(
value: mailboxSelected,
borderColor: errorValue?.isNotEmpty == true
? AppColor.redFF3347
: AppColor.m3Neutral90,
tapActionCallback: (_) => tapActionDetailedCallback?.call(),
),
),
]
else if (actionSelected == EmailRuleFilterAction.forwardTo)
Expanded(
child: DefaultInputFieldWidget(
errorText: errorValue,
hintText: AppLocalizations.of(context).forwardEmailHintText,
textEditingController: forwardEmailEditingController!,
focusNode: forwardEmailFocusNode,
inputColor: Colors.black,
onTextChange: onChangeForwardEmail,
),
),
RuleFilterDeleteButtonWidget(
imagePaths: imagePaths,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
)
],
);
@@ -48,10 +48,13 @@ class RuleFilterActionRowMobile extends StatelessWidget {
padding: const EdgeInsets.symmetric(vertical: RuleFilterActionStyles.mainPadding),
child: Text(
AppLocalizations.of(context).toFolder,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: RuleFilterActionStyles.maxLines,
style: RuleFilterActionStyles.textStyle,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
)
: SizedBox(
@@ -9,12 +9,13 @@ import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/e
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/styles/rule_filter_action_styles.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_row_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_row_mobile_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
class RuleFilterActionWidget extends StatelessWidget {
final ResponsiveUtils responsiveUtils;
final Function()? tapRemoveCallback;
final ImagePaths? imagePaths;
final ImagePaths imagePaths;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
final EmailRuleFilterAction? actionSelected;
final Function(EmailRuleFilterAction?)? onActionChanged;
final Function()? onActionChangeMobile;
@@ -28,8 +29,8 @@ class RuleFilterActionWidget extends StatelessWidget {
const RuleFilterActionWidget({
Key? key,
required this.responsiveUtils,
this.tapRemoveCallback,
this.imagePaths,
required this.imagePaths,
required this.onDeleteRuleConditionAction,
this.actionSelected,
this.onActionChanged,
this.mailboxSelected,
@@ -43,6 +44,47 @@ class RuleFilterActionWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final isMobile = responsiveUtils.isMobile(context);
Widget bodyWidget = Container(
padding: const EdgeInsetsDirectional.only(start: 12),
margin: const EdgeInsetsDirectional.only(top: 8),
decoration: const BoxDecoration(
color: AppColor.lightGrayF9FAFB,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
height: 72,
alignment: Alignment.center,
child: isMobile
? RuleFilterActionRowMobile(
actionSelected: actionSelected,
mailboxSelected: mailboxSelected,
errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode,
onChangeForwardEmail: onChangeForwardEmail,
tapActionCallback: onActionChangeMobile,
)
: RuleFilterActionRow(
actionList: EmailRuleFilterAction.values,
actionSelected: actionSelected,
onActionChanged: onActionChanged,
mailboxSelected: mailboxSelected,
errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
imagePaths: imagePaths,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode,
onChangeForwardEmail: onChangeForwardEmail,
),
);
if (!isMobile) {
return bodyWidget;
}
return Slidable(
enabled: responsiveUtils.isMobile(context) ? true : false,
endActionPane: ActionPane(
@@ -55,13 +97,13 @@ class RuleFilterActionWidget extends StatelessWidget {
topRight: Radius.circular(RuleFilterActionStyles.mainBorderRadius),
bottomRight: Radius.circular(RuleFilterActionStyles.mainBorderRadius),
),
onPressed: (_) => tapRemoveCallback!(),
onPressed: (_) => onDeleteRuleConditionAction(),
backgroundColor: AppColor.colorBackgroundFieldConditionRulesFilter,
child: CircleAvatar(
backgroundColor: AppColor.colorRemoveRuleFilterConditionButton,
radius: RuleFilterActionStyles.removeButtonRadius,
child: SvgPicture.asset(
imagePaths!.icMinimize,
imagePaths.icMinimize,
fit: BoxFit.fill,
colorFilter: AppColor.colorDeletePermanentlyButton.asFilter(),
),
@@ -106,7 +148,7 @@ class RuleFilterActionWidget extends StatelessWidget {
errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
imagePaths: imagePaths,
tapRemoveActionCallback: tapRemoveCallback,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode,
onChangeForwardEmail: onChangeForwardEmail,
@@ -50,10 +50,7 @@ class RuleFilterButtonField<T> extends StatelessWidget {
child: Row(children: [
Expanded(child: Text(
_getName(context, value),
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: 16,
fontWeight: FontWeight.normal,
color: textColor),
style: ThemeUtils.textStyleBodyBody3(color: textColor),
maxLines: 1,
softWrap: CommonTextStyle.defaultSoftWrap,
overflow: CommonTextStyle.defaultTextOverFlow,
@@ -1,24 +0,0 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart';
class RuleFilterConditionRemoveButton extends StatelessWidget {
final Function()? tapRemoveRuleFilterConditionCallback;
final ImagePaths? imagePath;
const RuleFilterConditionRemoveButton({
Key? key,
this.tapRemoveRuleFilterConditionCallback,
this.imagePath,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TMailButtonWidget.fromIcon(
icon: imagePath!.icRemoveRule,
backgroundColor: Colors.transparent,
padding: EdgeInsets.zero,
onTapActionCallback: tapRemoveRuleFilterConditionCallback,
);
}
}
@@ -1,123 +1,139 @@
import 'package:core/core.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/keyboard_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_condition_type.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_remove_button_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RuleFilterConditionRow extends StatelessWidget {
final RuleFilterConditionScreenType? ruleFilterConditionScreenType;
final RuleCondition ruleCondition;
final ImagePaths imagePaths;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
final Function(Field?)? tapRuleConditionFieldCallback;
final Function(Comparator?)? tapRuleConditionComparatorCallback;
final String? conditionValueErrorText;
final TextEditingController? conditionValueEditingController;
final TextEditingController textEditingController;
final FocusNode? conditionValueFocusNode;
final OnChangeFilterInputAction? conditionValueOnChangeAction;
final Function()? tapRemoveRuleFilterConditionCallback;
final ImagePaths? imagePaths;
const RuleFilterConditionRow({
Key? key,
required this.ruleFilterConditionScreenType,
required this.ruleCondition,
required this.imagePaths,
required this.textEditingController,
required this.onDeleteRuleConditionAction,
this.tapRuleConditionFieldCallback,
this.tapRuleConditionComparatorCallback,
this.conditionValueErrorText,
this.conditionValueEditingController,
this.conditionValueFocusNode,
this.conditionValueOnChangeAction,
this.tapRemoveRuleFilterConditionCallback,
this.imagePaths,
}) : super(key: key);
@override
Widget build(BuildContext context) {
switch (ruleFilterConditionScreenType) {
case RuleFilterConditionScreenType.mobile:
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RuleFilterButtonField<rule_condition.Field>(
value: ruleCondition.field,
tapActionCallback: (value) {
KeyboardUtils.hideKeyboard(context);
tapRuleConditionFieldCallback!(ruleCondition.field);
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: RuleFilterButtonField<rule_condition.Comparator>(
value: ruleCondition.comparator,
case RuleFilterConditionScreenType.mobile:
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RuleFilterButtonField<rule_condition.Field>(
value: ruleCondition.field,
tapActionCallback: (value) {
KeyboardUtils.hideKeyboard(context);
tapRuleConditionComparatorCallback!(ruleCondition.comparator);
tapRuleConditionFieldCallback!(ruleCondition.field);
},
)
),
RulesFilterInputField(
hintText: AppLocalizations.of(context).conditionValueHintTextInput,
errorText: conditionValueErrorText,
focusNode: conditionValueFocusNode,
onChangeAction: conditionValueOnChangeAction,
editingController: conditionValueEditingController,
),
],
);
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: RuleFilterButtonField<rule_condition.Comparator>(
value: ruleCondition.comparator,
tapActionCallback: (value) {
KeyboardUtils.hideKeyboard(context);
tapRuleConditionComparatorCallback!(ruleCondition.comparator);
},
)
),
RulesFilterInputField(
hintText: AppLocalizations.of(context).conditionValueHintTextInput,
errorText: conditionValueErrorText,
focusNode: conditionValueFocusNode,
onChangeAction: conditionValueOnChangeAction,
editingController: textEditingController,
),
],
);
case RuleFilterConditionScreenType.tablet:
case RuleFilterConditionScreenType.desktop:
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(width: 12),
Expanded(
child: DropDownButtonWidget<rule_condition.Field>(
items: rule_condition.Field.values,
itemSelected: ruleCondition.field,
dropdownMaxHeight: 250,
heightItem: 40,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
onChanged: (newField) => {
tapRuleConditionFieldCallback!(newField)
},
supportSelectionIcon: true,
)
),
Container(
width: 220,
padding: const EdgeInsets.symmetric(horizontal: 12),
const SizedBox(width: 8),
Expanded(
child: DropDownButtonWidget<rule_condition.Comparator>(
items: rule_condition.Comparator.values,
itemSelected: ruleCondition.comparator,
heightItem: 40,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
onChanged: (newComparator) => {
tapRuleConditionComparatorCallback!(newComparator)
},
supportSelectionIcon: true,
)
),
const SizedBox(width: 8),
Expanded(
child: RulesFilterInputField(
child: DefaultInputFieldWidget(
hintText: AppLocalizations.of(context).conditionValueHintTextInput,
errorText: conditionValueErrorText,
focusNode: conditionValueFocusNode,
onChangeAction: conditionValueOnChangeAction,
editingController: conditionValueEditingController,
)
inputColor: Colors.black,
onTextChange: conditionValueOnChangeAction,
textEditingController: textEditingController,
),
),
Container(
padding: const EdgeInsetsDirectional.only(start: 12),
alignment: Alignment.center,
child: RuleFilterConditionRemoveButton(
tapRemoveRuleFilterConditionCallback: tapRemoveRuleFilterConditionCallback,
imagePath: imagePaths,
)
RuleFilterDeleteButtonWidget(
imagePaths: imagePaths,
margin: const EdgeInsetsDirectional.only(top: 2),
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
),
],
);
default:
return const SizedBox.shrink();
return const SizedBox.shrink();
}
}
}
@@ -4,6 +4,7 @@ import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_condition_type.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_row_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
import 'package:core/presentation/resources/image_paths.dart';
@@ -11,31 +12,57 @@ import 'package:core/presentation/resources/image_paths.dart';
class RuleFilterConditionWidget extends StatelessWidget {
final RuleFilterConditionScreenType? ruleFilterConditionScreenType;
final RuleCondition ruleCondition;
final TextEditingController textEditingController;
final Function(Field?)? tapRuleConditionFieldCallback;
final Function(Comparator?)? tapRuleConditionComparatorCallback;
final String? conditionValueErrorText;
final TextEditingController? conditionValueEditingController;
final FocusNode? conditionValueFocusNode;
final OnChangeFilterInputAction? conditionValueOnChangeAction;
final ImagePaths? imagePaths;
final Function()? tapRemoveRuleFilterConditionCallback;
final ImagePaths imagePaths;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
const RuleFilterConditionWidget({
super.key,
this.ruleFilterConditionScreenType,
required this.ruleCondition,
required this.imagePaths,
required this.textEditingController,
required this.onDeleteRuleConditionAction,
this.tapRuleConditionFieldCallback,
this.tapRuleConditionComparatorCallback,
this.conditionValueErrorText,
this.conditionValueEditingController,
this.conditionValueFocusNode,
this.conditionValueOnChangeAction,
this.imagePaths,
this.tapRemoveRuleFilterConditionCallback,
});
@override
Widget build(BuildContext context) {
Widget bodyWidget = Container(
padding: const EdgeInsetsDirectional.symmetric(vertical: 12),
margin: const EdgeInsetsDirectional.only(top: 8),
decoration: const BoxDecoration(
color: AppColor.lightGrayF9FAFB,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
alignment: Alignment.center,
child: RuleFilterConditionRow(
ruleFilterConditionScreenType: ruleFilterConditionScreenType,
ruleCondition: ruleCondition,
tapRuleConditionFieldCallback: tapRuleConditionFieldCallback,
tapRuleConditionComparatorCallback: tapRuleConditionComparatorCallback,
conditionValueErrorText: conditionValueErrorText,
textEditingController: textEditingController,
conditionValueFocusNode: conditionValueFocusNode,
conditionValueOnChangeAction: conditionValueOnChangeAction,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
imagePaths: imagePaths,
),
);
if (ruleFilterConditionScreenType != RuleFilterConditionScreenType.mobile) {
return bodyWidget;
}
return Slidable(
enabled: ruleFilterConditionScreenType == RuleFilterConditionScreenType.mobile ? true : false,
endActionPane: ActionPane(
@@ -45,13 +72,13 @@ class RuleFilterConditionWidget extends StatelessWidget {
CustomSlidableAction(
padding: const EdgeInsets.only(right: 12),
borderRadius: const BorderRadius.only(topRight: Radius.circular(12), bottomRight: Radius.circular(12)),
onPressed: (_) => tapRemoveRuleFilterConditionCallback!(),
onPressed: (_) => onDeleteRuleConditionAction(),
backgroundColor: AppColor.colorBackgroundFieldConditionRulesFilter,
child: CircleAvatar(
backgroundColor: AppColor.colorRemoveRuleFilterConditionButton,
radius: 110,
child: SvgPicture.asset(
imagePaths!.icMinimize,
imagePaths.icMinimize,
fit: BoxFit.fill,
colorFilter: AppColor.colorDeletePermanentlyButton.asFilter(),
),
@@ -59,40 +86,10 @@ class RuleFilterConditionWidget extends StatelessWidget {
)
]
),
child: Builder(builder: (context) {
SlidableController? slideController = Slidable.of(context);
return ValueListenableBuilder<int>(
valueListenable: slideController?.direction ?? ValueNotifier<int>(0),
builder: (context, value, _) {
var borderRadius = value != -1 ?
BorderRadius.circular(12) :
const BorderRadius.only(
bottomLeft: Radius.circular(12),
topLeft: Radius.circular(12)
);
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.colorBackgroundFieldConditionRulesFilter,
borderRadius: borderRadius,
),
child: RuleFilterConditionRow(
ruleFilterConditionScreenType: ruleFilterConditionScreenType,
ruleCondition: ruleCondition,
tapRuleConditionFieldCallback: tapRuleConditionFieldCallback,
tapRuleConditionComparatorCallback: tapRuleConditionComparatorCallback,
conditionValueErrorText: conditionValueErrorText,
conditionValueEditingController: conditionValueEditingController,
conditionValueFocusNode: conditionValueFocusNode,
conditionValueOnChangeAction: conditionValueOnChangeAction,
tapRemoveRuleFilterConditionCallback: tapRemoveRuleFilterConditionCallback,
imagePaths: imagePaths,
)
);
}
);
})
child: ValueListenableBuilder<int>(
valueListenable: Slidable.of(context)?.direction ?? ValueNotifier<int>(0),
builder: (_, __, ___) => bodyWidget,
),
);
}
}
@@ -0,0 +1,31 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart';
typedef OnDeleteRuleConditionAction = Function();
class RuleFilterDeleteButtonWidget extends StatelessWidget {
final ImagePaths imagePaths;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
final EdgeInsetsGeometry? margin;
const RuleFilterDeleteButtonWidget({
Key? key,
required this.imagePaths,
required this.onDeleteRuleConditionAction,
this.margin,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TMailButtonWidget.fromIcon(
icon: imagePaths.icDeleteComposer,
iconSize: 20,
iconColor: AppColor.steelGrayA540,
backgroundColor: Colors.transparent,
margin: margin,
onTapActionCallback: onDeleteRuleConditionAction,
);
}
}
@@ -0,0 +1,58 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
import 'package:flutter/material.dart';
class RuleFilterListActionWidget extends StatelessWidget {
final String positiveLabel;
final String negativeLabel;
final VoidCallback onNegativeAction;
final VoidCallback onPositiveAction;
final EdgeInsetsGeometry? padding;
const RuleFilterListActionWidget({
super.key,
required this.positiveLabel,
required this.negativeLabel,
required this.onPositiveAction,
required this.onNegativeAction,
this.padding,
});
@override
Widget build(BuildContext context) {
Widget negativeButton = Container(
constraints: const BoxConstraints(minWidth: 67),
height: 48,
child: ConfirmDialogButton(
label: negativeLabel,
onTapAction: onNegativeAction,
),
);
Widget positiveButton = Container(
constraints: const BoxConstraints(minWidth: 143),
height: 48,
child: ConfirmDialogButton(
label: positiveLabel,
backgroundColor: AppColor.primaryMain,
textColor: Colors.white,
onTapAction: onPositiveAction,
),
);
Widget bodyWidget = Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Flexible(child: negativeButton),
const SizedBox(width: 8),
Flexible(child: positiveButton),
],
);
if (padding != null) {
return Padding(padding: padding!, child: bodyWidget);
} else {
return bodyWidget;
}
}
}
@@ -1,71 +1,87 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/utils/keyboard_utils.dart';
import 'package:core/presentation/utils/style_utils.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart';
import 'package:rule_filter/rule_filter/rule_condition_group.dart';
import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_condition_type.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/styles/rule_filter_title_styles.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnTapActionCallback<RuleConditionCombiner> = Function(ConditionCombiner? value);
typedef OnTapActionCallback<RuleConditionCombiner> = Function(
ConditionCombiner? value,
);
class RuleFilterTitle extends StatelessWidget {
final ConditionCombiner? conditionCombinerType;
final OnTapActionCallback? tapActionCallback;
final RuleFilterConditionScreenType ruleFilterConditionScreenType;
final ResponsiveUtils responsiveUtils;
const RuleFilterTitle({
Key? key,
required this.ruleFilterConditionScreenType,
required this.responsiveUtils,
this.conditionCombinerType,
this.tapActionCallback,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final appLocalizations = AppLocalizations.of(context);
final isMobile = responsiveUtils.isMobile(context);
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
return Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
runAlignment: WrapAlignment.center,
runSpacing: 8,
children: [
Text(
AppLocalizations.of(context).conditionTitleRulesFilterBeforeCombiner,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: RuleFilterTitleStyles.textMaxLines,
style: RuleFilterTitleStyles.textStyle,
appLocalizations.conditionTitleRulesFilterBeforeCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: RuleFilterTitleStyles.combinerTypeSelectionAreaPadding),
width: RuleFilterTitleStyles.combinerTypeSelectionAreaWith,
child: ruleFilterConditionScreenType == RuleFilterConditionScreenType.mobile
padding: const EdgeInsets.symmetric(horizontal: 12),
width: isMobile ? double.infinity : 158,
child: ruleFilterConditionScreenType ==
RuleFilterConditionScreenType.mobile
? RuleFilterButtonField<ConditionCombiner>(
value: conditionCombinerType,
tapActionCallback: (value) {
KeyboardUtils.hideKeyboard(context);
tapActionCallback?.call(value);
},
)
value: conditionCombinerType,
tapActionCallback: (value) {
KeyboardUtils.hideKeyboard(context);
tapActionCallback?.call(value);
},
)
: DropDownButtonWidget<ConditionCombiner>(
items: ConditionCombiner.values,
itemSelected: conditionCombinerType,
supportSelectionIcon: true,
onChanged: (value) {
KeyboardUtils.hideKeyboard(context);
tapActionCallback?.call(value);
},
),
items: ConditionCombiner.values,
itemSelected: conditionCombinerType,
supportSelectionIcon: true,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
onChanged: (value) {
KeyboardUtils.hideKeyboard(context);
tapActionCallback?.call(value);
},
),
),
Expanded(
child: Text(
AppLocalizations.of(context).conditionTitleRulesFilterAfterCombiner,
overflow: CommonTextStyle.defaultTextOverFlow,
style: RuleFilterTitleStyles.textStyle,
Text(
appLocalizations.conditionTitleRulesFilterAfterCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
)
]
],
);
}
}
+42
View File
@@ -4723,5 +4723,47 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"createANewRule": "Create a New Rule",
"@createANewRule": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"ruleName": "Rule Name",
"@ruleName": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"condition": "Condition",
"@condition": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"addACondition": "Add a condition",
"@addACondition": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"actionsToPerform": "Actions to Perform",
"@actionsToPerform": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"addAnAction": "Add an action",
"@addAnAction": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"createRule": "Create Rule",
"@createRule": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
@@ -4985,4 +4985,53 @@ class AppLocalizations {
name: 'createMyFirstRule',
);
}
String get createANewRule {
return Intl.message(
'Create a New Rule',
name: 'createANewRule',
);
}
String get ruleName {
return Intl.message(
'Rule Name',
name: 'ruleName',
);
}
String get condition {
return Intl.message(
'Condition',
name: 'condition',
);
}
String get addACondition {
return Intl.message(
'Add a condition',
name: 'addACondition',
);
}
String get actionsToPerform {
return Intl.message(
'Actions to Perform',
name: 'actionsToPerform',
);
}
String get addAnAction {
return Intl.message(
'Add an action',
name: 'addAnAction',
);
}
String get createRule {
return Intl.message(
'Create Rule',
name: 'createRule',
);
}
}