You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

697 lines
28KB

  1. import 'dart:convert';
  2. import 'package:farm_tpf/custom_model/SuppliesUsing.dart';
  3. import 'package:farm_tpf/custom_model/action_form/ActionUIField.dart';
  4. import 'package:farm_tpf/custom_model/action_form/ActionUIForm.dart';
  5. import 'package:farm_tpf/custom_model/action_form/CommonData.dart';
  6. import 'package:farm_tpf/custom_model/action_form/RequestActivity.dart';
  7. import 'package:farm_tpf/data/api/app_exception.dart';
  8. import 'package:farm_tpf/data/repository/repository.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart';
  10. import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
  11. import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart';
  12. import 'package:farm_tpf/presentation/custom_widgets/dropdown_supply_widget.dart';
  13. import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
  14. import 'package:farm_tpf/presentation/custom_widgets/widget_action_field_date.dart';
  15. import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart';
  16. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  17. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  18. import 'package:farm_tpf/presentation/custom_widgets/widget_radio_button.dart';
  19. import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_area.dart';
  20. import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart';
  21. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  22. import 'package:farm_tpf/presentation/screens/actions/cubit/action_ui_cubit.dart';
  23. import 'package:farm_tpf/utils/const_string.dart';
  24. import 'package:farm_tpf/utils/pref.dart';
  25. import 'package:farm_tpf/utils/validators.dart';
  26. import 'package:flutter/material.dart';
  27. import 'package:flutter/scheduler.dart';
  28. import 'package:flutter_bloc/flutter_bloc.dart';
  29. import 'package:get/get.dart';
  30. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  31. import 'package:farm_tpf/utils/formatter.dart';
  32. import '../../../utils/local_storage.dart';
  33. import 'controller/ChangeFieldInForm.dart';
  34. import 'controller/ChangeSupplyUsing.dart';
  35. import 'controller/ChangeWorker.dart';
  36. import 'dung/widget_dung_supply.dart';
  37. import 'nursery/widget_worker.dart';
  38. import 'plant/widget_plant_supply.dart';
  39. import 'spraying/widget_spraying_supply.dart';
  40. import 'state_management_helper/change_dropdown_controller.dart';
  41. import 'state_management_helper/change_file_controller.dart';
  42. import 'util_action.dart';
  43. class ActionScreen extends StatefulWidget {
  44. final bool isEdit;
  45. final int cropId;
  46. final int idAction;
  47. final String activityType;
  48. final String title;
  49. final int activityId;
  50. ActionScreen({
  51. required this.isEdit,
  52. required this.cropId,
  53. required this.idAction,
  54. required this.title,
  55. required this.activityType,
  56. required this.activityId,
  57. });
  58. @override
  59. _ActionScreenState createState() => _ActionScreenState();
  60. }
  61. class _ActionScreenState extends State<ActionScreen> {
  62. var _formKey = GlobalKey<FormState>();
  63. var pref = LocalPref();
  64. final _executeByController = TextEditingController();
  65. DateTime executeTime = DateTime.now();
  66. List<String> filePaths = <String>[];
  67. var controller = Get.put(ChangeDropdownController());
  68. var changeFileController = Get.put(ChangeFileController());
  69. Map<String, TextEditingController> textFieldControllers = {};
  70. Map<String, String> valueObjects = {};
  71. var _requestActivity = RequestActivity();
  72. final _repository = Repository();
  73. var _actionUIForm = ActionUIForm();
  74. var _nurseryDetails = <TbNurseryDetailsDTO>[];
  75. var _supplyUsings = <SuppliesUsing>[];
  76. var _previousGroupFieldName = '';
  77. var isValidated = false;
  78. Future<Null> getSharedPrefs() async {
  79. // var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  80. var currentFullName = LocalStorage.getString(LocalStorageKey.full_name);
  81. _executeByController.text = currentFullName ?? "";
  82. }
  83. @override
  84. void initState() {
  85. super.initState();
  86. getSharedPrefs();
  87. changeFileController.initValue();
  88. }
  89. _submitForm() async {
  90. switch (widget.activityType) {
  91. case 'ACTIVE_TYPE_NURSERY':
  92. if (Get.find<ChangeFieldFormSupply>().isChanged ?? false) {
  93. Utils.showDialog(
  94. title: 'Thông tin người thực hiện chưa cập nhật',
  95. message: 'Bạn có muốn cập nhật',
  96. textConfirm: 'Tiếp tục',
  97. textCancel: 'Xem lại',
  98. onConfirm: () {
  99. Get.back();
  100. _validateInputs();
  101. });
  102. } else {
  103. _validateInputs();
  104. }
  105. break;
  106. // case 'ACTIVE_TYPE_PLANTING':
  107. case 'ACTIVE_TYPE_FERTILIZE':
  108. case 'ACTIVE_TYPE_SPRAYING_PESTICIDES':
  109. if (Get.find<ChangeFieldFormSupply>().isChanged ?? false) {
  110. Utils.showDialogConfirmSupply(onConfirm: () {
  111. Get.back();
  112. _validateInputs();
  113. });
  114. } else {
  115. _validateInputs();
  116. }
  117. break;
  118. default:
  119. _validateInputs();
  120. break;
  121. }
  122. }
  123. _validateInputs() async {
  124. if (_formKey.currentState!.validate()) {
  125. _formKey.currentState!.save();
  126. try {
  127. LoadingDialog.showLoadingDialog(context);
  128. filePaths = Get.find<ChangeFileController>().newFiles ?? [];
  129. //Create request general model
  130. _requestActivity
  131. ..tbActivityTypeId = widget.idAction
  132. ..tbCropId = widget.cropId;
  133. if ((_actionUIForm.activityExtendTypeDTOList ?? []).isNotEmpty) {
  134. _requestActivity..externalTable = _actionUIForm?.activityExtendTypeDTOList?.first?.externalTable ?? '';
  135. }
  136. filePaths = Get.find<ChangeFileController>().newFiles ?? [];
  137. textFieldControllers.forEach((key, value) {
  138. valueObjects[key] = textFieldControllers[key]?.text ?? '';
  139. });
  140. //tbObjectUpdateDTOList
  141. var _objectPrameters = <TbObjectUpdateDTO>[];
  142. if (widget.isEdit) {
  143. // Edit
  144. if (_requestActivity.tbObjectUpdateDTOList != null) {
  145. _requestActivity.tbObjectUpdateDTOList?.forEach((element) {
  146. print(valueObjects[element.tbObjectParameterId.toString()]);
  147. var updateValue = '';
  148. if (Validators.stringNotNullOrEmpty(valueObjects[element.tbObjectParameterId.toString()] ?? '')) {
  149. updateValue = valueObjects[element.tbObjectParameterId.toString()] ?? '';
  150. } else {
  151. updateValue = element.index ?? '';
  152. }
  153. var objectUpdate = TbObjectUpdateDTO()
  154. ..id = element.id
  155. ..tbObjectParameterId = element.tbObjectParameterId
  156. ..index = updateValue;
  157. _objectPrameters.add(objectUpdate);
  158. });
  159. _requestActivity.tbObjectUpdateDTOList = _objectPrameters;
  160. }
  161. } else {
  162. //Add new
  163. valueObjects.forEach((key, value) {
  164. var objectUpdate = TbObjectUpdateDTO()
  165. ..tbObjectParameterId = int.tryParse(key)
  166. ..index = value;
  167. _objectPrameters.add(objectUpdate);
  168. });
  169. _requestActivity.tbObjectUpdateDTOList = _objectPrameters;
  170. }
  171. //CHECK NURSERY
  172. if (widget.activityType == 'ACTIVE_TYPE_NURSERY') {
  173. _requestActivity.tbNurseryDetailsDTOList = _nurseryDetails;
  174. } else if (
  175. // widget.activityType == 'ACTIVE_TYPE_PLANTING' ||
  176. widget.activityType == 'ACTIVE_TYPE_FERTILIZE' ||
  177. widget.activityType == 'ACTIVE_TYPE_SPRAYING_PESTICIDES') {
  178. _requestActivity.tbSuppliesUsingDetailsDTOs = _supplyUsings;
  179. }
  180. //delete images
  181. _requestActivity.deletedImages = Get.find<ChangeFileController>().deleteFiles;
  182. //convert data to json
  183. var activityCommonData = jsonEncode(_requestActivity.toJson()).toString();
  184. print(activityCommonData);
  185. if (widget.activityId < 0) {
  186. //ADD New
  187. _repository.createActionCommon((data) {
  188. LoadingDialog.hideLoadingDialog(context);
  189. Get.back(result: 'ok');
  190. Utils.showSnackBarSuccess(message: label_add_success);
  191. }, (error) {
  192. LoadingDialog.hideLoadingDialog(context);
  193. Utils.showSnackBarError(message: AppException.handleError(error));
  194. }, activityType: widget.activityType, activityData: activityCommonData, filePaths: filePaths);
  195. } else {
  196. //UPDATE
  197. _repository.updateActionCommon((data) {
  198. LoadingDialog.hideLoadingDialog(context);
  199. Get.back(result: 'ok');
  200. Utils.showSnackBarSuccess(message: label_update_success);
  201. }, (error) {
  202. LoadingDialog.hideLoadingDialog(context);
  203. Utils.showSnackBarError(message: AppException.handleError(error));
  204. }, activityType: widget.activityType, activityData: activityCommonData, filePaths: filePaths);
  205. }
  206. //ADD NEW
  207. //Update
  208. } catch (e) {
  209. LoadingDialog.hideLoadingDialog(context);
  210. print(e.toString());
  211. }
  212. } else {
  213. //
  214. setState(() {
  215. isValidated = true;
  216. });
  217. }
  218. }
  219. Widget _btnExecuteTimePicker() {
  220. return WidgetFieldDateTimePicker(
  221. initDateTime: executeTime,
  222. onUpdateDateTime: (selectedDate) {
  223. _requestActivity.executeDate = selectedDate.convertLocalDateTimeToStringUtcDateTime();
  224. });
  225. }
  226. Widget _executeByField() {
  227. return TextFormField(
  228. keyboardType: TextInputType.text,
  229. decoration: InputDecoration(labelText: "Người thực hiện"),
  230. enabled: false,
  231. controller: _executeByController,
  232. onSaved: (newValue) {},
  233. );
  234. }
  235. //
  236. // GENERATE DYNAMIC FORM
  237. //
  238. Widget groupName(String name) {
  239. if (_previousGroupFieldName == name || !Validators.stringNotNullOrEmpty(name)) {
  240. return SizedBox();
  241. } else {
  242. _previousGroupFieldName = name ?? '';
  243. return Container(
  244. child: Row(
  245. children: [
  246. Container(
  247. width: 24,
  248. height: 0.5,
  249. color: Colors.green,
  250. ),
  251. Text(' ${name ?? ''} '),
  252. Expanded(
  253. child: Container(
  254. width: 5,
  255. height: 0.5,
  256. color: Colors.green,
  257. ),
  258. ),
  259. ],
  260. ),
  261. );
  262. }
  263. }
  264. Widget generateField(List<ActionUIField> fields) {
  265. return Wrap(
  266. children: [
  267. ListView.separated(
  268. shrinkWrap: true,
  269. physics: NeverScrollableScrollPhysics(),
  270. itemCount: fields.length,
  271. separatorBuilder: (context, index) {
  272. return SizedBox(
  273. height: 8,
  274. );
  275. },
  276. itemBuilder: (context, index) {
  277. var field = fields[index];
  278. if (field.tbControlTypeName == 'text') {
  279. return Column(
  280. children: [
  281. groupName(field.groupName ?? ''),
  282. TextFormField(
  283. keyboardType: TextInputType.text,
  284. decoration: InputDecoration(
  285. labelText: ((field.isMandatory ?? false) ?? false) ? '${field.description} *' : '${field.description}',
  286. hintText: field.description),
  287. controller: textFieldControllers[field.id.toString()],
  288. onSaved: (newValue) {},
  289. validator: ((field.isMandatory ?? false) ?? false)
  290. ? (String? value) {
  291. return Validators.validateNotNullOrEmpty(
  292. value ?? '',
  293. 'Vui lòng nhập ${field.description}',
  294. );
  295. }
  296. : null,
  297. ),
  298. ],
  299. );
  300. } else if (field.tbControlTypeName == 'number') {
  301. return Column(
  302. children: [
  303. groupName(field.groupName ?? ''),
  304. WidgetTextFormFieldNumber(
  305. hintValue: field.description ?? '',
  306. labelText: ((field.isMandatory ?? false) ?? false) ? '${field.description} *' : '${field.description}',
  307. textController: textFieldControllers[field.id.toString()] ?? TextEditingController(),
  308. onSaved: (newValue) {},
  309. validator: ((field.isMandatory ?? false) ?? false)
  310. ? (String? value) {
  311. return Validators.validNumberOrEmpty(
  312. value ?? '',
  313. 'Vui lòng nhập ${field.description}',
  314. );
  315. }
  316. : null,
  317. ),
  318. ],
  319. );
  320. } else if (field.tbControlTypeName == 'textarea') {
  321. return Column(
  322. children: [
  323. groupName(field.groupName ?? ''),
  324. TextFieldAreaWidget(
  325. hint: field.description ?? '',
  326. labelText: (field.isMandatory ?? false) ? '${field.description} *' : '${field.description}',
  327. controller: textFieldControllers[field.id.toString()] ?? TextEditingController(),
  328. onSaved: (newValue) {},
  329. validator: (field.isMandatory ?? false)
  330. ? (String? value) {
  331. return Validators.validateNotNullOrEmpty(
  332. value ?? '',
  333. 'Vui lòng nhập ${field.description}',
  334. );
  335. }
  336. : null,
  337. ),
  338. ],
  339. );
  340. } else if (field.tbControlTypeName == 'dropdown') {
  341. return Column(
  342. children: [
  343. groupName(field.groupName ?? ''),
  344. DropdownSupplyWidget(
  345. titleName: field.description ?? '',
  346. tbSupply: field.tbActivityExtendTypeExternalTable ?? '',
  347. tag: field.name ?? '',
  348. value: field.description,
  349. hint: '${field.description} ${(field.isMandatory ?? false) ? '*' : ''}',
  350. condition: field.tbActivityExtendTypeCondition ?? '',
  351. invalidMessage: '',
  352. onPressed: (commonData) {
  353. valueObjects[field.id.toString()] = commonData.id.toString();
  354. },
  355. ),
  356. ],
  357. );
  358. } else if (field.tbControlTypeName == 'radiobutton') {
  359. return Column(
  360. children: [
  361. groupName(field.groupName ?? ''),
  362. RadioButtonWidget(
  363. tag: field.name ?? '',
  364. condition: field.tbActivityExtendTypeCondition ?? '',
  365. supply: field.tbActivityExtendTypeExternalTable ?? '',
  366. onPressed: (commonData) {
  367. valueObjects[field.id.toString()] = commonData.id.toString();
  368. },
  369. ),
  370. ],
  371. );
  372. } else if (field.tbControlTypeName == 'date') {
  373. return Column(
  374. children: [
  375. groupName(field.groupName ?? ''),
  376. FieldDateWidget(
  377. tag: field.name ?? '',
  378. isValidated: isValidated,
  379. value: field.description,
  380. hint: '${field.description} ${(field.isMandatory ?? false) ? '*' : ''}',
  381. onPressed: (selectedDate) {
  382. valueObjects[field.id.toString()] = selectedDate.convertLocalDateTimeToStringUtcDateTime();
  383. },
  384. validator: (field.isMandatory ?? false)
  385. ? (String? value) {
  386. return Validators.validateNotNullOrEmpty(value ?? '', 'Vui lòng nhập ${field.description}');
  387. }
  388. : null,
  389. ),
  390. ],
  391. );
  392. } else {
  393. return Container();
  394. }
  395. })
  396. ],
  397. );
  398. }
  399. //
  400. // GENERATE SUPPLY
  401. //
  402. Widget generateSupply(String activityType) {
  403. switch (activityType) {
  404. case 'ACTIVE_TYPE_NURSERY':
  405. return WidgetWorker(onChangeWorkers: (nurseryDetails) {
  406. _nurseryDetails = nurseryDetails;
  407. });
  408. break;
  409. // case 'ACTIVE_TYPE_PLANTING':
  410. // return Column(
  411. // children: [
  412. // Container(
  413. // width: double.infinity,
  414. // height: 16,
  415. // color: Colors.grey[200],
  416. // ),
  417. // WidgetPlantSupply(
  418. // currentItems: [],
  419. // onChangeSupplies: (value) {
  420. // _supplyUsings = value;
  421. // }),
  422. // ],
  423. // );
  424. // break;
  425. case 'ACTIVE_TYPE_FERTILIZE':
  426. return Column(
  427. children: [
  428. Container(
  429. width: double.infinity,
  430. height: 16,
  431. color: Colors.grey[200],
  432. ),
  433. WidgetDungSupply(
  434. currentItems: [],
  435. onChangeSupplies: (value) {
  436. _supplyUsings = value;
  437. }),
  438. ],
  439. );
  440. break;
  441. case 'ACTIVE_TYPE_SPRAYING_PESTICIDES':
  442. return Column(
  443. children: [
  444. Container(
  445. width: double.infinity,
  446. height: 16,
  447. color: Colors.grey[200],
  448. ),
  449. WidgetSprayingSupply(
  450. currentItems: [],
  451. onChangeSupplies: (value) {
  452. _supplyUsings = value;
  453. }),
  454. ],
  455. );
  456. break;
  457. default:
  458. return Container();
  459. break;
  460. }
  461. }
  462. void showDataWhenEdit(BuildContext context) {
  463. //Show media
  464. try {
  465. if (Validators.stringNotNullOrEmpty(_requestActivity.media ?? '')) {
  466. BlocProvider.of<MediaHelperBloc>(context).add(
  467. ChangeListMedia(
  468. items: UtilAction.convertFilePathToMedia(
  469. _requestActivity.media ?? '',
  470. ),
  471. ),
  472. );
  473. }
  474. } catch (e) {
  475. print(e);
  476. }
  477. SchedulerBinding.instance.addPostFrameCallback((_) {
  478. if (
  479. // widget.activityType == 'ACTIVE_TYPE_PLANTING' ||
  480. widget.activityType == 'ACTIVE_TYPE_FERTILIZE' ||
  481. widget.activityType == 'ACTIVE_TYPE_SPRAYING_PESTICIDES') {
  482. //list supply
  483. Get.find<ChangeSupplyUsing>().changeInitList(_requestActivity.tbSuppliesUsingDetailsDTOs ?? []);
  484. } else if (widget.activityType == 'ACTIVE_TYPE_NURSERY') {
  485. //list nursery
  486. Get.find<ChangeWorker>().changeInitList(_requestActivity.tbNurseryDetailsDTOList ?? []);
  487. }
  488. });
  489. //Show value textfield
  490. if (_requestActivity.tbObjectUpdateDTOList != null) {
  491. print(textFieldControllers.keys.toList());
  492. _requestActivity.tbObjectUpdateDTOList?.forEach((element) {
  493. if (element.tbObjectParameterDTO?.tbControlTypeName == 'text' || element.tbObjectParameterDTO?.tbControlTypeName == 'textarea') {
  494. SchedulerBinding.instance.addPostFrameCallback((_) {
  495. textFieldControllers[element.tbObjectParameterId.toString()]?.text = element.index ?? '';
  496. });
  497. } else if (element.tbObjectParameterDTO?.tbControlTypeName == 'number') {
  498. SchedulerBinding.instance.addPostFrameCallback((_) {
  499. textFieldControllers[element.tbObjectParameterId.toString()]?.text = element.index?.formatStringToStringDecimal() ?? '';
  500. });
  501. } else {
  502. SchedulerBinding.instance.addPostFrameCallback((_) {
  503. if (element.tbObjectParameterDTO?.tbControlTypeName == 'dropdown' ||
  504. element.tbObjectParameterDTO?.tbControlTypeName?.toLowerCase() == 'radiobutton') {
  505. var dropdownValueName = '';
  506. if ((element.tbObjectParameterDTO?.tbActivityExtendTypeDropDownDTOList ?? []).isNotEmpty ||
  507. element.tbObjectParameterDTO?.tbActivityExtendTypeDropDownDTOList != null) {
  508. element.tbObjectParameterDTO?.tbActivityExtendTypeDropDownDTOList?.forEach((dropdownData) {
  509. if (dropdownData.id == int.tryParse(element.index ?? '-1')) {
  510. dropdownValueName = dropdownData.name ?? '';
  511. }
  512. });
  513. }
  514. var commonData = CommonData()
  515. ..id = int.tryParse(element.index ?? '-1')
  516. ..name = dropdownValueName;
  517. Get.find<ChangeDropdownController>(tag: element.tbObjectParameterDTO?.name).change(commonData);
  518. } else if (element.tbObjectParameterDTO?.tbControlTypeName == 'date') {
  519. Get.find<ChangeDateTimePicker>(tag: element.tbObjectParameterDTO?.name).change(
  520. element.index?.convertStringServerDateTimeToLocalDateTime() ?? DateTime.now(),
  521. );
  522. }
  523. });
  524. }
  525. });
  526. } else {
  527. //
  528. }
  529. }
  530. @override
  531. Widget build(BuildContext context) => KeyboardDismisser(
  532. gestures: [
  533. GestureType.onTap,
  534. GestureType.onPanUpdateDownDirection,
  535. ],
  536. child: Scaffold(
  537. backgroundColor: Colors.white,
  538. appBar: AppBarWidget(
  539. isBack: true,
  540. action: InkWell(
  541. child: Text(
  542. 'Lưu',
  543. style: TextStyle(color: Colors.red, fontWeight: FontWeight.normal),
  544. ),
  545. onTap: () {
  546. FocusScopeNode currentFocus = FocusScope.of(context);
  547. if (!currentFocus.hasPrimaryFocus) {
  548. currentFocus.unfocus();
  549. }
  550. _submitForm();
  551. },
  552. ),
  553. ),
  554. body: MultiBlocProvider(
  555. providers: [
  556. BlocProvider<ActionUiCubit>(
  557. create: (context) => ActionUiCubit(repository: Repository())
  558. ..getActionUIForm(
  559. actionId: widget.idAction, actionType: widget.activityType, isEdit: widget.isEdit, activityId: widget.activityId)),
  560. BlocProvider<MediaHelperBloc>(
  561. create: (context) => MediaHelperBloc()..add(ChangeListMedia(items: [])),
  562. )
  563. ],
  564. child: Form(
  565. key: _formKey,
  566. child: SafeArea(
  567. child: BlocBuilder<ActionUiCubit, ActionUiState>(
  568. builder: (context, state) {
  569. if (state is ActionUiLoading) {
  570. print('loading...');
  571. return Center(
  572. child: LoadingListPage(),
  573. );
  574. } else if (state is ActionUiSuccess) {
  575. _actionUIForm = state.actionUIForm ?? ActionUIForm();
  576. _requestActivity = state.activityDetail ?? RequestActivity();
  577. //CREATE UI
  578. _actionUIForm.objectParameterDTOList?.forEach((element) {
  579. //generate controller
  580. if (element.tbControlTypeName == 'text' ||
  581. element.tbControlTypeName == 'number' ||
  582. element.tbControlTypeName == 'textarea') {
  583. var textEditingController = new TextEditingController();
  584. textFieldControllers.putIfAbsent(element.id.toString(), () => textEditingController);
  585. }
  586. // generate value each parameter
  587. valueObjects.putIfAbsent(element.id.toString(), () => '');
  588. });
  589. //SHOW EDIT DATA
  590. if (widget.isEdit) {
  591. showDataWhenEdit(context);
  592. }
  593. return SingleChildScrollView(
  594. child: Column(
  595. children: [
  596. Padding(
  597. padding: const EdgeInsets.all(8.0),
  598. child: Column(
  599. children: <Widget>[
  600. Container(
  601. width: double.infinity,
  602. child: Text(
  603. "Ngày thực hiện *",
  604. style: TextStyle(color: Colors.black54, fontSize: 13.0),
  605. ),
  606. ),
  607. _btnExecuteTimePicker(),
  608. SizedBox(
  609. height: 8.0,
  610. ),
  611. generateField(_actionUIForm.objectParameterDTOList ?? []),
  612. _executeByField(),
  613. SizedBox(
  614. height: 8.0,
  615. ),
  616. ],
  617. ),
  618. ),
  619. generateSupply(widget.activityType),
  620. Container(
  621. width: double.infinity,
  622. height: 16,
  623. color: Colors.grey[200],
  624. ),
  625. BlocBuilder<MediaHelperBloc, MediaHelperState>(builder: (context, state) {
  626. if (state is MediaHelperSuccess) {
  627. return WidgetMediaPicker(
  628. currentItems: state.items,
  629. onChangeFiles: (newPathFiles, deletePathFiles) async {
  630. Get.find<ChangeFileController>().change(newPathFiles, deletePathFiles);
  631. });
  632. } else {
  633. return Center(child: CircularProgressIndicator());
  634. }
  635. }),
  636. Padding(
  637. padding: const EdgeInsets.all(8.0),
  638. child: ButtonWidget(
  639. title: 'CẬP NHẬT',
  640. onPressed: () {
  641. FocusScopeNode currentFocus = FocusScope.of(context);
  642. if (!currentFocus.hasPrimaryFocus) {
  643. currentFocus.unfocus();
  644. }
  645. _submitForm();
  646. }),
  647. ),
  648. ],
  649. ),
  650. );
  651. } else if (state is ActionUiFailure) {
  652. return Center(child: Text(state.errorString));
  653. }
  654. return Container();
  655. },
  656. ),
  657. )),
  658. )));
  659. @override
  660. void dispose() {
  661. _executeByController.dispose();
  662. textFieldControllers.forEach((key, value) {
  663. textFieldControllers[key]?.dispose();
  664. });
  665. super.dispose();
  666. }
  667. }