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.

462 lines
19KB

  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/RequestActivity.dart';
  6. import 'package:farm_tpf/data/api/app_exception.dart';
  7. import 'package:farm_tpf/data/repository/repository.dart';
  8. import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart';
  9. import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
  10. import 'package:farm_tpf/presentation/custom_widgets/button_widget.dart';
  11. import 'package:farm_tpf/presentation/custom_widgets/dropdown_supply_widget.dart';
  12. import 'package:farm_tpf/presentation/custom_widgets/widget_action_field_date.dart';
  13. import 'package:farm_tpf/presentation/custom_widgets/widget_field_time_picker.dart';
  14. import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
  15. import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
  16. import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_area.dart';
  17. import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart';
  18. import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart';
  19. import 'package:farm_tpf/presentation/screens/actions/cubit/action_ui_cubit.dart';
  20. import 'package:farm_tpf/utils/const_string.dart';
  21. import 'package:farm_tpf/utils/pref.dart';
  22. import 'package:farm_tpf/utils/validators.dart';
  23. import 'package:flutter/material.dart';
  24. import 'package:flutter_bloc/flutter_bloc.dart';
  25. import 'package:get/get.dart';
  26. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  27. import 'package:farm_tpf/utils/formatter.dart';
  28. import 'dung/widget_dung_supply.dart';
  29. import 'nursery/widget_worker.dart';
  30. import 'plant/widget_plant_supply.dart';
  31. import 'spraying/widget_spraying_supply.dart';
  32. import 'state_management_helper/change_file_controller.dart';
  33. class ActionScreen extends StatefulWidget {
  34. final int cropId;
  35. final int idAction;
  36. final String activityType;
  37. final String title;
  38. ActionScreen(
  39. {@required this.cropId,
  40. @required this.idAction,
  41. @required this.title,
  42. @required this.activityType});
  43. @override
  44. _ActionScreenState createState() => _ActionScreenState();
  45. }
  46. class _ActionScreenState extends State<ActionScreen> {
  47. final _scaffoldKey = GlobalKey<ScaffoldState>();
  48. var _formKey = GlobalKey<FormState>();
  49. var pref = LocalPref();
  50. final _executeByController = TextEditingController();
  51. DateTime executeTime = DateTime.now();
  52. List<String> filePaths = <String>[];
  53. var changeFileController = Get.put(ChangeFileController());
  54. Map<String, TextEditingController> textFieldControllers = {};
  55. Map<String, String> valueObjects = {};
  56. var _requestActivity = RequestActivity();
  57. final _repository = Repository();
  58. var _actionUIForm = ActionUIForm();
  59. var _nurseryDetails = <TbNurseryDetailsDTO>[];
  60. var _supplyUsings = <SuppliesUsing>[];
  61. Future<Null> getSharedPrefs() async {
  62. var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME);
  63. _executeByController.text = currentFullName ?? "";
  64. }
  65. @override
  66. void initState() {
  67. super.initState();
  68. getSharedPrefs();
  69. changeFileController.initValue();
  70. }
  71. _validateInputs() async {
  72. if (_formKey.currentState.validate()) {
  73. _formKey.currentState.save();
  74. try {
  75. LoadingDialog.showLoadingDialog(context);
  76. filePaths = Get.find<ChangeFileController>().newFiles;
  77. //Create request general model
  78. _requestActivity
  79. ..tbActivityTypeId = widget.idAction
  80. ..tbCropId = widget.cropId;
  81. if (_actionUIForm.activityExtendTypeDTOList.isNotEmpty) {
  82. _requestActivity
  83. ..externalTable = _actionUIForm
  84. ?.activityExtendTypeDTOList?.first?.externalTable ??
  85. '';
  86. }
  87. filePaths = Get.find<ChangeFileController>().newFiles;
  88. textFieldControllers.forEach((key, value) {
  89. print(textFieldControllers[key].text);
  90. valueObjects[key] = textFieldControllers[key].text;
  91. });
  92. //tbObjectUpdateDTOList
  93. var _objectPrameters = <TbObjectUpdateDTO>[];
  94. valueObjects.forEach((key, value) {
  95. var objectUpdate = TbObjectUpdateDTO()
  96. ..tbObjectParameterId = int.tryParse(key)
  97. ..index = value;
  98. _objectPrameters.add(objectUpdate);
  99. });
  100. _requestActivity.tbObjectUpdateDTOList = _objectPrameters;
  101. //CHECK NURSERY
  102. if (widget.activityType == 'ACTIVE_TYPE_NURSERY') {
  103. _requestActivity.tbNurseryDetailsDTOList = _nurseryDetails;
  104. } else if (widget.activityType == 'ACTIVE_TYPE_PLANTING') {
  105. var _listSupplyUsingDetail = <TbSuppliesUsingDetailsDTOs>[];
  106. _supplyUsings.forEach((element) {
  107. var usingSupplyDetail = TbSuppliesUsingDetailsDTOs()
  108. ..tbSuppliesInWarehouseId = element.tbSuppliesInWarehouseId
  109. ..dosage = element.dosage
  110. ..quantity = element.quantity;
  111. _listSupplyUsingDetail.add(usingSupplyDetail);
  112. });
  113. _requestActivity.tbSuppliesUsingDetailsDTOs = _listSupplyUsingDetail;
  114. }
  115. //convert data to json
  116. var activityCommonData =
  117. jsonEncode(_requestActivity.toJson()).toString();
  118. print(activityCommonData);
  119. _repository.createActionCommon((data) {
  120. LoadingDialog.hideLoadingDialog(context);
  121. Get.back(result: 'ok');
  122. Utils.showSnackBarSuccess(message: label_add_success);
  123. }, (error) {
  124. LoadingDialog.hideLoadingDialog(context);
  125. Utils.showSnackBarError(message: AppException.handleError(error));
  126. },
  127. activityType: widget.activityType,
  128. activityData: activityCommonData,
  129. filePaths: filePaths);
  130. //ADD NEW
  131. //Update
  132. } catch (e) {
  133. LoadingDialog.hideLoadingDialog(context);
  134. print(e.toString());
  135. }
  136. } else {
  137. //
  138. }
  139. }
  140. Widget _btnExecuteTimePicker() {
  141. return WidgetFieldDateTimePicker(
  142. initDateTime: executeTime,
  143. onUpdateDateTime: (selectedDate) {
  144. _requestActivity.executeDate =
  145. selectedDate.convertLocalDateTimeToStringUtcDateTime();
  146. });
  147. }
  148. Widget _executeByField() {
  149. return TextFormField(
  150. keyboardType: TextInputType.text,
  151. decoration: InputDecoration(labelText: "Người thực hiện"),
  152. enabled: false,
  153. controller: _executeByController,
  154. onSaved: (newValue) {},
  155. );
  156. }
  157. //
  158. // GENERATE DYNAMIC FORM
  159. //
  160. Widget generateTextField(List<ActionUIField> fields) {
  161. return Wrap(
  162. children: [
  163. ListView.separated(
  164. shrinkWrap: true,
  165. physics: NeverScrollableScrollPhysics(),
  166. itemCount: fields.length,
  167. separatorBuilder: (context, index) {
  168. return SizedBox(
  169. height: 8,
  170. );
  171. },
  172. itemBuilder: (context, index) {
  173. var field = fields[index];
  174. if (field.tbControlTypeName == 'text') {
  175. return TextFormField(
  176. keyboardType: TextInputType.text,
  177. decoration: InputDecoration(labelText: field.description),
  178. controller: textFieldControllers[field.id.toString()],
  179. onSaved: (newValue) {},
  180. validator: field.isMandatory
  181. ? (String value) {
  182. return Validators.validateNotNullOrEmpty(
  183. value, 'Vui lòng nhập ${field.description}');
  184. }
  185. : null,
  186. );
  187. } else if (field.tbControlTypeName == 'number') {
  188. return WidgetTextFormFieldNumber(
  189. hintValue: field.description,
  190. textController: textFieldControllers[field.id.toString()],
  191. onSaved: (newValue) {},
  192. validator: field.isMandatory
  193. ? (String value) {
  194. return Validators.validNumberOrEmpty(
  195. value, 'Vui lòng nhập ${field.description}');
  196. }
  197. : null,
  198. );
  199. } else if (field.tbControlTypeName == 'textarea') {
  200. return TextFieldAreaWidget(
  201. hint: field.description,
  202. controller: textFieldControllers[field.id.toString()],
  203. onSaved: (newValue) {});
  204. } else if (field.tbControlTypeName == 'dropdown' ||
  205. field.tbControlTypeName == 'radiobutton') {
  206. return DropdownSupplyWidget(
  207. titleName: field.description ?? '',
  208. tbSupply: field.tbActivityExtendTypeExternalTable ?? '',
  209. tag: field.name,
  210. value: field.description,
  211. hint:
  212. '${field.description} ${field.isMandatory ? '*' : ''}',
  213. condition: field.tbActivityExtendTypeCondition,
  214. invalidMessage: '',
  215. onPressed: (commonData) {
  216. valueObjects[field.id.toString()] =
  217. commonData.id.toString();
  218. });
  219. } else if (field.tbControlTypeName == 'date') {
  220. return FieldDateWidget(
  221. tag: field.name,
  222. value: field.description,
  223. hint:
  224. '${field.description} ${field.isMandatory ? '*' : ''}',
  225. invalidMessage: '',
  226. onPressed: (selectedDate) {
  227. valueObjects[field.id.toString()] = selectedDate
  228. .convertLocalDateTimeToStringUtcDateTime();
  229. });
  230. } else {
  231. return Container();
  232. }
  233. })
  234. ],
  235. );
  236. }
  237. //
  238. // GENERATE SUPPLY
  239. //
  240. Widget generateSupply(String activityType) {
  241. switch (activityType) {
  242. case 'ACTIVE_TYPE_NURSERY':
  243. return WidgetWorker(onChangeWorkers: (nurseryDetails) {
  244. _nurseryDetails = nurseryDetails;
  245. });
  246. break;
  247. case 'ACTIVE_TYPE_PLANTING':
  248. return Column(
  249. children: [
  250. Container(
  251. width: double.infinity,
  252. height: 16,
  253. color: Colors.grey[200],
  254. ),
  255. WidgetPlantSupply(
  256. currentItems: [],
  257. onChangeSupplies: (value) {
  258. _supplyUsings = value;
  259. }),
  260. ],
  261. );
  262. break;
  263. case 'ACTIVE_TYPE_FERTILIZE':
  264. return Column(
  265. children: [
  266. Container(
  267. width: double.infinity,
  268. height: 16,
  269. color: Colors.grey[200],
  270. ),
  271. WidgetDungSupply(currentItems: [], onChangeSupplies: (value) {}),
  272. ],
  273. );
  274. break;
  275. case 'ACTIVE_TYPE_SPRAYING_PESTICIDES':
  276. return Column(
  277. children: [
  278. Container(
  279. width: double.infinity,
  280. height: 16,
  281. color: Colors.grey[200],
  282. ),
  283. WidgetSprayingSupply(
  284. currentItems: [], onChangeSupplies: (value) {}),
  285. ],
  286. );
  287. break;
  288. default:
  289. return Container();
  290. break;
  291. }
  292. }
  293. @override
  294. Widget build(BuildContext context) => KeyboardDismisser(
  295. gestures: [
  296. GestureType.onTap,
  297. GestureType.onPanUpdateDownDirection,
  298. ],
  299. child: Scaffold(
  300. backgroundColor: Colors.white,
  301. key: _scaffoldKey,
  302. appBar: AppBarWidget(
  303. isBack: true,
  304. action: InkWell(
  305. child: Text(
  306. 'Lưu',
  307. style: TextStyle(
  308. color: Colors.red, fontWeight: FontWeight.normal),
  309. ),
  310. onTap: () {
  311. FocusScopeNode currentFocus = FocusScope.of(context);
  312. if (!currentFocus.hasPrimaryFocus) {
  313. currentFocus.unfocus();
  314. }
  315. _validateInputs();
  316. },
  317. ),
  318. ),
  319. body: KeyboardDismisser(
  320. child: MultiBlocProvider(
  321. providers: [
  322. BlocProvider<ActionUiCubit>(
  323. create: (context) =>
  324. ActionUiCubit(repository: Repository())
  325. ..getActionUIForm(widget.idAction)),
  326. BlocProvider<MediaHelperBloc>(
  327. create: (context) =>
  328. MediaHelperBloc()..add(ChangeListMedia(items: [])),
  329. )
  330. ],
  331. child: Form(
  332. key: _formKey,
  333. child: SafeArea(
  334. child: SingleChildScrollView(
  335. child: BlocBuilder<ActionUiCubit, ActionUiState>(
  336. builder: (context, state) {
  337. if (state is ActionUiLoading) {
  338. print('loading...');
  339. return Center(child: CircularProgressIndicator());
  340. } else if (state is ActionUiSuccess) {
  341. _actionUIForm = state.item as ActionUIForm;
  342. _actionUIForm.objectParameterDTOList
  343. .forEach((element) {
  344. //generate controller
  345. if (element.tbControlTypeName == 'text' ||
  346. element.tbControlTypeName == 'number' ||
  347. element.tbControlTypeName == 'textarea') {
  348. var textEditingController =
  349. new TextEditingController();
  350. textFieldControllers.putIfAbsent(
  351. element.id.toString(),
  352. () => textEditingController);
  353. }
  354. // generate value each parameter
  355. valueObjects.putIfAbsent(
  356. element.id.toString(), () => '');
  357. });
  358. return Column(
  359. children: [
  360. Padding(
  361. padding: const EdgeInsets.all(8.0),
  362. child: Column(
  363. children: <Widget>[
  364. Container(
  365. width: double.infinity,
  366. child: Text(
  367. "Ngày thực hiện *",
  368. style: TextStyle(
  369. color: Colors.black54,
  370. fontSize: 13.0),
  371. ),
  372. ),
  373. _btnExecuteTimePicker(),
  374. SizedBox(
  375. height: 8.0,
  376. ),
  377. generateTextField(_actionUIForm
  378. .objectParameterDTOList),
  379. _executeByField(),
  380. SizedBox(
  381. height: 8.0,
  382. ),
  383. ],
  384. ),
  385. ),
  386. generateSupply(widget.activityType),
  387. Container(
  388. width: double.infinity,
  389. height: 16,
  390. color: Colors.grey[200],
  391. ),
  392. BlocBuilder<MediaHelperBloc,
  393. MediaHelperState>(
  394. builder: (context, state) {
  395. if (state is MediaHelperSuccess) {
  396. return WidgetMediaPicker(
  397. currentItems: state.items,
  398. onChangeFiles: (newPathFiles,
  399. deletePathFiles) async {
  400. Get.find<ChangeFileController>()
  401. .change(newPathFiles,
  402. deletePathFiles);
  403. });
  404. } else {
  405. return Center(
  406. child: CircularProgressIndicator());
  407. }
  408. }),
  409. Padding(
  410. padding: const EdgeInsets.all(8.0),
  411. child: ButtonWidget(
  412. title: 'CẬP NHẬT',
  413. onPressed: () {
  414. FocusScopeNode currentFocus =
  415. FocusScope.of(context);
  416. if (!currentFocus.hasPrimaryFocus) {
  417. currentFocus.unfocus();
  418. }
  419. _validateInputs();
  420. }),
  421. ),
  422. ],
  423. );
  424. } else if (state is ActionUiFailure) {
  425. print('error');
  426. return Text(state.errorString);
  427. // LoadingDialog.hideLoadingDialog(context);
  428. }
  429. },
  430. ),
  431. ),
  432. )),
  433. ))));
  434. @override
  435. void dispose() {
  436. _executeByController.dispose();
  437. textFieldControllers.forEach((key, value) {
  438. textFieldControllers[key].dispose();
  439. });
  440. super.dispose();
  441. }
  442. }