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.

459 lines
18KB

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