|
@@ -0,0 +1,364 @@
|
|
|
+import 'dart:typed_data';
|
|
|
+import 'dart:ui';
|
|
|
+import 'package:cs_resources/generated/assets.dart';
|
|
|
+import 'package:domain/entity/response/labour_request_index_entity.dart';
|
|
|
+import 'package:flutter/cupertino.dart';
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+import 'package:flutter/widgets.dart';
|
|
|
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|
|
+import 'package:get/get.dart';
|
|
|
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
|
|
|
+import 'package:shared/utils/date_time_utils.dart';
|
|
|
+import 'package:shared/utils/screen_util.dart';
|
|
|
+import 'package:shared/utils/util.dart';
|
|
|
+import 'package:widgets/ext/ex_widget.dart';
|
|
|
+import 'package:cs_resources/constants/color_constants.dart';
|
|
|
+import 'package:widgets/my_button.dart';
|
|
|
+import 'package:widgets/my_load_image.dart';
|
|
|
+import 'package:widgets/my_text_field.dart';
|
|
|
+import 'package:widgets/my_text_view.dart';
|
|
|
+import 'package:widgets/picker/date_picker_util.dart';
|
|
|
+import 'package:widgets/picker/option_pick_util.dart';
|
|
|
+import 'package:widgets/widget_export.dart';
|
|
|
+
|
|
|
+/*
|
|
|
+ * 电子考勤统计的筛选
|
|
|
+ */
|
|
|
+class AttendanceReportFilter extends StatefulWidget {
|
|
|
+ void Function(DateTime? selectedStartDate, DateTime? selectedEndDate, String? selectedDepartmentId, String? staffName)? onFilterAction;
|
|
|
+ LabourRequestIndexEntity optionResult;
|
|
|
+ DateTime? selectedStartDate;
|
|
|
+ DateTime? selectedEndDate;
|
|
|
+ String? selectedDepartmentId;
|
|
|
+ String? staffName;
|
|
|
+
|
|
|
+ AttendanceReportFilter({
|
|
|
+ required this.optionResult,
|
|
|
+ required this.selectedStartDate,
|
|
|
+ required this.selectedEndDate,
|
|
|
+ required this.selectedDepartmentId,
|
|
|
+ required this.staffName,
|
|
|
+ this.onFilterAction,
|
|
|
+ });
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<AttendanceReportFilter> createState() => _LabourReviewFilterState();
|
|
|
+}
|
|
|
+
|
|
|
+class _LabourReviewFilterState extends State<AttendanceReportFilter> {
|
|
|
+ DateTime? selectedStartDate;
|
|
|
+ DateTime? selectedEndDate;
|
|
|
+ String? selectedStatusId;
|
|
|
+ String? selectedDepartmentId;
|
|
|
+ String? staffName;
|
|
|
+ late TextEditingController textController;
|
|
|
+ late FocusNode textFocusNode;
|
|
|
+
|
|
|
+ @override
|
|
|
+ void initState() {
|
|
|
+ super.initState();
|
|
|
+ this.selectedStartDate = widget.selectedStartDate;
|
|
|
+ this.selectedEndDate = widget.selectedEndDate;
|
|
|
+ this.selectedDepartmentId = widget.selectedDepartmentId;
|
|
|
+ this.staffName = widget.staffName;
|
|
|
+ textController = TextEditingController();
|
|
|
+ textFocusNode = FocusNode();
|
|
|
+ if (Utils.isNotEmpty(staffName)) {
|
|
|
+ textController.text = staffName!;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ SizedBox(
|
|
|
+ height: kToolbarHeight + ScreenUtil.getStatusBarH(context) + 1,
|
|
|
+ ),
|
|
|
+ Container(
|
|
|
+ padding: const EdgeInsets.only(left: 15, right: 15, top: 17.5, bottom: 20),
|
|
|
+ width: double.infinity,
|
|
|
+ decoration: const BoxDecoration(
|
|
|
+ color: Colors.white,
|
|
|
+ ),
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ //标题
|
|
|
+ MyTextView(
|
|
|
+ "Staff Name".tr,
|
|
|
+ fontSize: 14,
|
|
|
+ isFontMedium: true,
|
|
|
+ textColor: ColorConstants.black33,
|
|
|
+ ),
|
|
|
+
|
|
|
+ //输入标题搜索
|
|
|
+ IgnoreKeyboardDismiss(
|
|
|
+ child: MyTextField(
|
|
|
+ "staff",
|
|
|
+ staffName == null ? "" : staffName!,
|
|
|
+ hintText: "Enter...".tr,
|
|
|
+ hintStyle: const TextStyle(
|
|
|
+ color: ColorConstants.gray88,
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
+ ),
|
|
|
+ controller: textController,
|
|
|
+ focusNode: textFocusNode,
|
|
|
+ margin: const EdgeInsets.only(left: 0, right: 0, top: 8),
|
|
|
+ showDivider: false,
|
|
|
+ fillBackgroundColor: ColorConstants.grayECECEC,
|
|
|
+ fillCornerRadius: 5,
|
|
|
+ padding: const EdgeInsets.only(left: 16, right: 16, top: 0, bottom: 0),
|
|
|
+ height: 40,
|
|
|
+ style: const TextStyle(
|
|
|
+ color: ColorConstants.black33,
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
+ ),
|
|
|
+ inputType: TextInputType.text,
|
|
|
+ textInputAction: TextInputAction.done,
|
|
|
+ enabled: true,
|
|
|
+ onSubmit: (key, value) {},
|
|
|
+ cursorColor: ColorConstants.black33,
|
|
|
+ showLeftIcon: false,
|
|
|
+ showRightIcon: false,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+
|
|
|
+ //部门
|
|
|
+ MyTextView(
|
|
|
+ "Outlet".tr,
|
|
|
+ fontSize: 14,
|
|
|
+ marginTop: 11,
|
|
|
+ isFontMedium: true,
|
|
|
+ textColor: ColorConstants.black33,
|
|
|
+ ),
|
|
|
+
|
|
|
+ //选择部门
|
|
|
+ Container(
|
|
|
+ padding: const EdgeInsets.only(left: 16, right: 10),
|
|
|
+ margin: const EdgeInsets.only(top: 10),
|
|
|
+ height: 45,
|
|
|
+ decoration: const BoxDecoration(
|
|
|
+ color: ColorConstants.grayECECEC,
|
|
|
+ borderRadius: BorderRadius.all(Radius.circular(5)),
|
|
|
+ ),
|
|
|
+ child: Row(
|
|
|
+ mainAxisSize: MainAxisSize.max,
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ MyTextView(
|
|
|
+ selectedDepartmentId == null || selectedDepartmentId == "0"
|
|
|
+ ? ""
|
|
|
+ : widget.optionResult.departmentList!.firstWhere((element) => element.value.toString() == selectedDepartmentId).txt!,
|
|
|
+ hint: "Choose Outlet".tr,
|
|
|
+ textHintColor: ColorConstants.textBlackHint,
|
|
|
+ fontSize: 14,
|
|
|
+ isFontMedium: true,
|
|
|
+ textColor: ColorConstants.black33,
|
|
|
+ ).expanded(),
|
|
|
+ const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ).onTap(() {
|
|
|
+ pickerOutlet();
|
|
|
+ }),
|
|
|
+
|
|
|
+ //开始时间
|
|
|
+ MyTextView(
|
|
|
+ "Start Date".tr,
|
|
|
+ fontSize: 14,
|
|
|
+ isFontMedium: true,
|
|
|
+ marginTop: 11,
|
|
|
+ textColor: ColorConstants.black33,
|
|
|
+ ),
|
|
|
+
|
|
|
+ //选择时间
|
|
|
+ Container(
|
|
|
+ padding: const EdgeInsets.only(left: 16, right: 10),
|
|
|
+ margin: const EdgeInsets.only(top: 10),
|
|
|
+ height: 45,
|
|
|
+ decoration: const BoxDecoration(
|
|
|
+ color: ColorConstants.grayECECEC,
|
|
|
+ borderRadius: BorderRadius.all(Radius.circular(5)),
|
|
|
+ ),
|
|
|
+ child: Row(
|
|
|
+ mainAxisSize: MainAxisSize.max,
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ MyTextView(
|
|
|
+ selectedStartDate == null ? "" : DateTimeUtils.formatDate(selectedStartDate, format: "yyyy-MM-dd"),
|
|
|
+ fontSize: 14,
|
|
|
+ hint: "Choose Start Date".tr,
|
|
|
+ textHintColor: ColorConstants.textBlackHint,
|
|
|
+ isFontMedium: true,
|
|
|
+ textColor: ColorConstants.black33,
|
|
|
+ ).expanded(),
|
|
|
+ const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ).onTap(() {
|
|
|
+ pickerStartDate();
|
|
|
+ }),
|
|
|
+
|
|
|
+ //结束日期
|
|
|
+ MyTextView(
|
|
|
+ "End Date".tr,
|
|
|
+ fontSize: 14,
|
|
|
+ marginTop: 11,
|
|
|
+ isFontMedium: true,
|
|
|
+ textColor: ColorConstants.black33,
|
|
|
+ ),
|
|
|
+
|
|
|
+ //选择结束日期
|
|
|
+ Container(
|
|
|
+ padding: const EdgeInsets.only(left: 16, right: 10),
|
|
|
+ margin: const EdgeInsets.only(top: 10),
|
|
|
+ height: 45,
|
|
|
+ decoration: const BoxDecoration(
|
|
|
+ color: ColorConstants.grayECECEC,
|
|
|
+ borderRadius: BorderRadius.all(Radius.circular(5)),
|
|
|
+ ),
|
|
|
+ child: Row(
|
|
|
+ mainAxisSize: MainAxisSize.max,
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ MyTextView(
|
|
|
+ selectedEndDate == null ? "" : DateTimeUtils.formatDate(selectedEndDate, format: "yyyy-MM-dd"),
|
|
|
+ fontSize: 14,
|
|
|
+ hint: "Choose End Date".tr,
|
|
|
+ textHintColor: ColorConstants.textBlackHint,
|
|
|
+ isFontMedium: true,
|
|
|
+ textColor: ColorConstants.black33,
|
|
|
+ ).expanded(),
|
|
|
+ const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ).onTap(() {
|
|
|
+ pickerEndDate();
|
|
|
+ }),
|
|
|
+
|
|
|
+ //按钮组
|
|
|
+ Row(
|
|
|
+ children: [
|
|
|
+ MyButton(
|
|
|
+ onPressed: () {
|
|
|
+ //只是Reset当前的弹窗筛选选项
|
|
|
+ widget.selectedStartDate = null;
|
|
|
+ widget.selectedEndDate = null;
|
|
|
+ widget.selectedDepartmentId = null;
|
|
|
+ widget.staffName = null;
|
|
|
+
|
|
|
+ setState(() {
|
|
|
+ selectedStartDate = null;
|
|
|
+ selectedEndDate = null;
|
|
|
+ selectedStatusId = null;
|
|
|
+ selectedDepartmentId = null;
|
|
|
+ staffName = null;
|
|
|
+ textController.text = "";
|
|
|
+ });
|
|
|
+ },
|
|
|
+ text: "Reset".tr,
|
|
|
+ textColor: ColorConstants.white,
|
|
|
+ backgroundColor: hexToColor("#FFBB1B"),
|
|
|
+ radius: 17.25,
|
|
|
+ minWidth: 60,
|
|
|
+ minHeight: 36,
|
|
|
+ ).expanded(),
|
|
|
+ const SizedBox(width: 15),
|
|
|
+ MyButton(
|
|
|
+ onPressed: () {
|
|
|
+ onCancel();
|
|
|
+ //取消软键盘
|
|
|
+ textFocusNode.unfocus();
|
|
|
+ //确定的时候取输入框的值
|
|
|
+ staffName = textController.text;
|
|
|
+ widget.onFilterAction?.call(selectedStartDate, selectedEndDate, selectedDepartmentId, staffName);
|
|
|
+ },
|
|
|
+ text: "Filter".tr,
|
|
|
+ textColor: ColorConstants.white,
|
|
|
+ backgroundColor: hexToColor("#0AC074"),
|
|
|
+ radius: 17.25,
|
|
|
+ minWidth: 60,
|
|
|
+ minHeight: 36,
|
|
|
+ ).expanded(),
|
|
|
+ ],
|
|
|
+ ).marginOnly(top: 20),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Center(child: const MyAssetImage(Assets.baseServiceDialogDeleteIcon, width: 26.5, height: 26.5).marginOnly(top: 35)).onTap(() {
|
|
|
+ onCancel();
|
|
|
+ }),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ //取消弹框
|
|
|
+ void onCancel() async {
|
|
|
+ SmartDialog.dismiss();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 筛选开始日期
|
|
|
+ void pickerStartDate() {
|
|
|
+ FocusScope.of(context).unfocus();
|
|
|
+
|
|
|
+ DatePickerUtil.showCupertinoDatePicker(
|
|
|
+ selectedDateTime: selectedStartDate,
|
|
|
+ onDateTimeChanged: (date) {
|
|
|
+ setState(() {
|
|
|
+ selectedStartDate = date;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ title: "Start Date".tr,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 筛选结束日期
|
|
|
+ void pickerEndDate() {
|
|
|
+ FocusScope.of(context).unfocus();
|
|
|
+
|
|
|
+ DatePickerUtil.showCupertinoDatePicker(
|
|
|
+ selectedDateTime: selectedEndDate ?? selectedStartDate,
|
|
|
+ onDateTimeChanged: (date) {
|
|
|
+ setState(() {
|
|
|
+ selectedEndDate = date;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ title: "End Date".tr,
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 筛选部门
|
|
|
+ void pickerOutlet() {
|
|
|
+ FocusScope.of(context).unfocus();
|
|
|
+
|
|
|
+ int selectedDepartmentIndex;
|
|
|
+ if (selectedDepartmentId == null) {
|
|
|
+ selectedDepartmentIndex = 0;
|
|
|
+ } else {
|
|
|
+ selectedDepartmentIndex = widget.optionResult.departmentList!.indexWhere((department) => department.value.toString() == selectedDepartmentId);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (selectedDepartmentIndex < 0) {
|
|
|
+ selectedDepartmentIndex = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ OptionPickerUtil.showCupertinoOptionPicker(
|
|
|
+ items: widget.optionResult.departmentList!.map((e) => e.txt!).toList(growable: false),
|
|
|
+ initialSelectIndex: selectedDepartmentIndex,
|
|
|
+ onPickerChanged: (_, index) {
|
|
|
+ setState(() {
|
|
|
+ selectedDepartmentId = widget.optionResult.departmentList![index].value!.toString();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+}
|