TF-3956 Adjust UI for vacation section in setting on web
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class ArrowDownIconBorderButtonWidget extends StatelessWidget {
|
||||
final ImagePaths imagePaths;
|
||||
final String? icon;
|
||||
final IconData? iconData;
|
||||
final Color? iconColor;
|
||||
final Color? backgroundColor;
|
||||
final String? tooltipMessage;
|
||||
final double? height;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
const ArrowDownIconBorderButtonWidget({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
this.icon,
|
||||
this.iconData,
|
||||
this.iconColor,
|
||||
this.backgroundColor,
|
||||
this.tooltipMessage,
|
||||
this.height,
|
||||
this.padding,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (icon == null && iconData == null) return const SizedBox.shrink();
|
||||
|
||||
Widget buttonIcon = Container(
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
border: Border.all(
|
||||
color: AppColor.m3Neutral90,
|
||||
),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
height: height,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (iconData != null)
|
||||
Icon(iconData, color: iconColor)
|
||||
else if (icon != null)
|
||||
SvgPicture.asset(
|
||||
icon!,
|
||||
colorFilter: iconColor.asFilter(),
|
||||
),
|
||||
SvgPicture.asset(imagePaths.icStyleArrowDown),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (onTap != null) {
|
||||
buttonIcon = Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
child: buttonIcon,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (tooltipMessage != null) {
|
||||
buttonIcon = Tooltip(
|
||||
message: tooltipMessage,
|
||||
child: buttonIcon,
|
||||
);
|
||||
}
|
||||
|
||||
if (padding != null) {
|
||||
buttonIcon = Padding(padding: padding!, child: buttonIcon);
|
||||
}
|
||||
|
||||
return buttonIcon;
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/utils/style_utils.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart';
|
||||
|
||||
typedef OnTapActionCallback<T> = Function(T? value);
|
||||
|
||||
class BorderButtonField<T> extends StatelessWidget {
|
||||
|
||||
final T? value;
|
||||
final OnTapActionCallback? tapActionCallback;
|
||||
final Widget? icon;
|
||||
final TextStyle? textStyle;
|
||||
final MouseCursor? mouseCursor;
|
||||
final String? hintText;
|
||||
final bool isEmpty;
|
||||
final Color? backgroundColor;
|
||||
final String? label;
|
||||
|
||||
const BorderButtonField({
|
||||
super.key,
|
||||
this.label,
|
||||
this.value,
|
||||
this.tapActionCallback,
|
||||
this.icon,
|
||||
this.textStyle,
|
||||
this.mouseCursor,
|
||||
this.hintText,
|
||||
this.isEmpty = false,
|
||||
this.backgroundColor,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final buttonField = InkWell(
|
||||
onTap: () => tapActionCallback?.call(value),
|
||||
mouseCursor: mouseCursor,
|
||||
child: Container(
|
||||
height: 44,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: _getBorderColor(),
|
||||
width: 0.5),
|
||||
color: backgroundColor ?? Colors.white),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(children: [
|
||||
Expanded(child: Text(
|
||||
_getName(context, value),
|
||||
style: _getTextStyle(value),
|
||||
maxLines: 1,
|
||||
softWrap: CommonTextStyle.defaultSoftWrap,
|
||||
overflow: CommonTextStyle.defaultTextOverFlow,
|
||||
)),
|
||||
if (icon != null) icon!
|
||||
]),
|
||||
),
|
||||
);
|
||||
if (label != null) {
|
||||
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Text(label!, style: ThemeUtils.defaultTextStyleInterFont.copyWith(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColor.colorContentEmail)),
|
||||
const SizedBox(height: 8),
|
||||
buttonField
|
||||
]);
|
||||
} else {
|
||||
return buttonField;
|
||||
}
|
||||
}
|
||||
|
||||
TextStyle? _getTextStyle(T? value) {
|
||||
if (hintText != null && value == null) {
|
||||
return ThemeUtils.defaultTextStyleInterFont.copyWith(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColor.colorHintInputCreateMailbox);
|
||||
}
|
||||
return textStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Colors.black);
|
||||
}
|
||||
|
||||
String _getName(BuildContext context, T? value) {
|
||||
if (value is DateTime) {
|
||||
return value.formatDate(locale: Localizations.localeOf(context).toLanguageTag());
|
||||
}
|
||||
if (value is TimeOfDay) {
|
||||
return value.formatTime(context);
|
||||
}
|
||||
return hintText ?? '';
|
||||
}
|
||||
|
||||
Color _getBorderColor() {
|
||||
if (!isEmpty) {
|
||||
return AppColor.colorInputBorderCreateMailbox;
|
||||
}
|
||||
return AppColor.colorInputBorderErrorVerifyName;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ typedef OnTextChange = void Function(String text);
|
||||
class DefaultInputFieldWidget extends StatelessWidget {
|
||||
final TextEditingController textEditingController;
|
||||
final String? hintText;
|
||||
final FocusNode? focusNode;
|
||||
final OnTextChange? onTextChange;
|
||||
final OnTextSubmitted? onTextSubmitted;
|
||||
|
||||
@@ -16,6 +17,7 @@ class DefaultInputFieldWidget extends StatelessWidget {
|
||||
super.key,
|
||||
required this.textEditingController,
|
||||
this.hintText,
|
||||
this.focusNode,
|
||||
this.onTextChange,
|
||||
this.onTextSubmitted,
|
||||
});
|
||||
@@ -29,6 +31,7 @@ class DefaultInputFieldWidget extends StatelessWidget {
|
||||
textStyle: ThemeUtils.textStyleBodyBody3(
|
||||
color: AppColor.m3SurfaceBackground,
|
||||
),
|
||||
focusNode: focusNode,
|
||||
onTextSubmitted: onTextSubmitted,
|
||||
onTextChange: onTextChange,
|
||||
decoration: InputDecoration(
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart';
|
||||
|
||||
typedef OnSelectValueAction<T> = Function(T? value);
|
||||
|
||||
class LabelBorderButtonField<T> extends StatelessWidget {
|
||||
final T? value;
|
||||
final bool isEmpty;
|
||||
final bool arrangeHorizontally;
|
||||
final String label;
|
||||
final String? hintText;
|
||||
final double? horizontalSpacing;
|
||||
final double? minWidth;
|
||||
final OnSelectValueAction onSelectValueAction;
|
||||
|
||||
const LabelBorderButtonField({
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.label,
|
||||
required this.onSelectValueAction,
|
||||
this.isEmpty = false,
|
||||
this.arrangeHorizontally = true,
|
||||
this.hintText,
|
||||
this.minWidth,
|
||||
this.horizontalSpacing,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget buttonField = Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: () => onSelectValueAction(value),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: Container(
|
||||
height: 40,
|
||||
constraints: BoxConstraints(minWidth: minWidth ?? 106),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
border: Border.all(color: _getBorderColor(), width: 1),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
_getName(context, value),
|
||||
style: _getTextStyle(value),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (arrangeHorizontally) {
|
||||
buttonField = Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 83),
|
||||
child: Text(
|
||||
'$label:',
|
||||
style: ThemeUtils.textStyleBodyBody3(color: Colors.black),
|
||||
),
|
||||
),
|
||||
SizedBox(width: horizontalSpacing ?? 12),
|
||||
buttonField,
|
||||
],
|
||||
);
|
||||
} else {
|
||||
buttonField = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'$label:',
|
||||
style: ThemeUtils.textStyleBodyBody3(color: Colors.black),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
buttonField,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return buttonField;
|
||||
}
|
||||
|
||||
TextStyle? _getTextStyle(T? value) {
|
||||
if (hintText != null && value == null) {
|
||||
return ThemeUtils.textStyleBodyBody3(color: AppColor.steelGray400);
|
||||
} else {
|
||||
return ThemeUtils.textStyleBodyBody3(color: Colors.black);
|
||||
}
|
||||
}
|
||||
|
||||
String _getName(BuildContext context, T? value) {
|
||||
if (value is DateTime) {
|
||||
return value.formatDate(
|
||||
pattern: 'dd/MM/yyyy',
|
||||
locale: Localizations.localeOf(context).toLanguageTag(),
|
||||
);
|
||||
}
|
||||
if (value is TimeOfDay) {
|
||||
return value.formatTime(context);
|
||||
}
|
||||
return hintText ?? '';
|
||||
}
|
||||
|
||||
Color _getBorderColor() =>
|
||||
isEmpty ? AppColor.redFF3347 : AppColor.m3Neutral90;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
|
||||
|
||||
class LabelInputFieldBuilder extends StatelessWidget {
|
||||
final String label;
|
||||
final TextEditingController textEditingController;
|
||||
final String? errorText;
|
||||
final String? hintText;
|
||||
final FocusNode? focusNode;
|
||||
final bool arrangeHorizontally;
|
||||
final OnTextChange? onTextChange;
|
||||
|
||||
const LabelInputFieldBuilder({
|
||||
super.key,
|
||||
required this.label,
|
||||
required this.textEditingController,
|
||||
this.arrangeHorizontally = true,
|
||||
this.hintText,
|
||||
this.errorText,
|
||||
this.focusNode,
|
||||
this.onTextChange,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget bodyWidget = ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 565),
|
||||
child: DefaultInputFieldWidget(
|
||||
textEditingController: textEditingController,
|
||||
hintText: hintText,
|
||||
focusNode: focusNode,
|
||||
onTextChange: onTextChange,
|
||||
),
|
||||
);
|
||||
|
||||
if (arrangeHorizontally) {
|
||||
bodyWidget = Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 83),
|
||||
child: Text(
|
||||
'$label:',
|
||||
style: ThemeUtils.textStyleBodyBody3(color: Colors.black),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Flexible(child: bodyWidget),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
bodyWidget = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'$label:',
|
||||
style: ThemeUtils.textStyleBodyBody3(color: Colors.black),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
bodyWidget,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return bodyWidget;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class SwitchLabelButtonWidget extends StatelessWidget {
|
||||
final ImagePaths imagePaths;
|
||||
final bool isActive;
|
||||
final String label;
|
||||
final VoidCallback onSwitchAction;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
|
||||
const SwitchLabelButtonWidget({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
required this.isActive,
|
||||
required this.label,
|
||||
required this.onSwitchAction,
|
||||
this.padding,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bodyWidget = Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: onSwitchAction,
|
||||
child: SvgPicture.asset(
|
||||
isActive ? imagePaths.icSwitchOn : imagePaths.icSwitchOff,
|
||||
fit: BoxFit.fill,
|
||||
width: 52,
|
||||
height: 32,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Text(
|
||||
label,
|
||||
style: ThemeUtils.textStyleBodyBody2(color: Colors.black),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
if (padding != null) {
|
||||
return Padding(padding: padding!, child: bodyWidget);
|
||||
} else {
|
||||
return bodyWidget;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
|
||||
import 'package:core/core.dart';
|
||||
import 'package:core/utils/direction_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/text_input_decoration_builder.dart';
|
||||
|
||||
typedef OnChangeInputAction = Function(String value);
|
||||
|
||||
class TextInputFieldBuilder extends StatelessWidget {
|
||||
|
||||
final String? label;
|
||||
final String? error;
|
||||
final String? hint;
|
||||
final TextEditingController? editingController;
|
||||
final FocusNode? focusNode;
|
||||
final TextInputType? inputType;
|
||||
final bool isMandatory;
|
||||
final int? minLines;
|
||||
final int? maxLines;
|
||||
final Color? backgroundColor;
|
||||
final OnChangeInputAction? onChangeInputAction;
|
||||
|
||||
const TextInputFieldBuilder({
|
||||
Key? key,
|
||||
this.label,
|
||||
this.hint,
|
||||
this.error,
|
||||
this.isMandatory = false,
|
||||
this.editingController,
|
||||
this.focusNode,
|
||||
this.inputType,
|
||||
this.minLines,
|
||||
this.maxLines,
|
||||
this.backgroundColor,
|
||||
this.onChangeInputAction,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
if (label != null)
|
||||
...[
|
||||
Text(isMandatory ? '${label!}*' : label!,
|
||||
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColor.colorContentEmail)),
|
||||
const SizedBox(height: 8)
|
||||
],
|
||||
TextFieldBuilder(
|
||||
onTextChange: onChangeInputAction,
|
||||
textInputAction: TextInputAction.next,
|
||||
controller: editingController,
|
||||
focusNode: focusNode,
|
||||
textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith(color: Colors.black, fontSize: 16),
|
||||
keyboardType: inputType ?? TextInputType.text,
|
||||
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||
minLines: minLines,
|
||||
maxLines: maxLines,
|
||||
decoration: (TextInputDecorationBuilder()
|
||||
..setContentPadding(EdgeInsets.symmetric(vertical: PlatformInfo.isWeb ? 16 : 12, horizontal: 12))
|
||||
..setHintText(hint)
|
||||
..setFillColor(backgroundColor)
|
||||
..setErrorText(error))
|
||||
.build(),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user