Browse Source

action crop status

master
daivph 5 years ago
parent
commit
1771f56795
8 changed files with 431 additions and 95 deletions
  1. +24
    -16
      lib/custom_model/CropStatus.dart
  2. +59
    -0
      lib/custom_model/RequestGeneralModel.dart
  3. +7
    -7
      lib/data/api/dio_provider.dart
  4. +290
    -71
      lib/presentation/screens/actions/crop_status/sc_edit_action_crop_status.dart
  5. +23
    -0
      lib/presentation/screens/actions/util_action.dart
  6. +11
    -1
      lib/presentation/screens/plot_detail/sc_plot_action.dart
  7. +6
    -0
      lib/utils/const_common.dart
  8. +11
    -0
      lib/utils/formatter.dart

+ 24
- 16
lib/custom_model/CropStatus.dart View File

@@ -1,60 +1,68 @@
class CropStatus {
int id;
int cropId;
int activityId;
String executeDate;
num cropRate;
num numberOfTreeToGrow;
num hightOfTree;
num numberOfLeaf;
num leafSize;
String cropRate;
String numberOfTreeToGrow;
String heightOfTree;
String numberOfLeaf;
String leafSize;
String leafColor;
String abilityProduceBuds;
num bodySize;
String note;
String internodeLength;
String description;
String media;

CropStatus(
{this.id,
this.cropId,
this.activityId,
this.executeDate,
this.cropRate,
this.numberOfTreeToGrow,
this.hightOfTree,
this.heightOfTree,
this.numberOfLeaf,
this.leafSize,
this.leafColor,
this.abilityProduceBuds,
this.bodySize,
this.note});
this.internodeLength,
this.description,
this.media});

CropStatus.fromJson(Map<String, dynamic> json) {
id = json['id'];
cropId = json['cropId'];
activityId = json['activityId'];
executeDate = json['executeDate'];
cropRate = json['cropRate'];
numberOfTreeToGrow = json['numberOfTreeToGrow'];
hightOfTree = json['hightOfTree'];
heightOfTree = json['heightOfTree'];
numberOfLeaf = json['numberOfLeaf'];
leafSize = json['leafSize'];
leafColor = json['leafColor'];
abilityProduceBuds = json['abilityProduceBuds'];
bodySize = json['bodySize'];
note = json['note'];
internodeLength = json['internodeLength'];
description = json['description'];
media = json['media'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['cropId'] = this.cropId;
data['activityId'] = this.activityId;
data['executeDate'] = this.executeDate;
data['cropRate'] = this.cropRate;
data['numberOfTreeToGrow'] = this.numberOfTreeToGrow;
data['hightOfTree'] = this.hightOfTree;
data['heightOfTree'] = this.heightOfTree;
data['numberOfLeaf'] = this.numberOfLeaf;
data['leafSize'] = this.leafSize;
data['leafColor'] = this.leafColor;
data['abilityProduceBuds'] = this.abilityProduceBuds;
data['bodySize'] = this.bodySize;
data['note'] = this.note;
data['internodeLength'] = this.internodeLength;
data['description'] = this.description;
data['media'] = this.media;
return data;
}
}

+ 59
- 0
lib/custom_model/RequestGeneralModel.dart View File

@@ -0,0 +1,59 @@
class RequestGeneralModel {
int cropId;
int activityId;
String executeDate;
String description;
List<ObjectUpdateDetail> objectUpdateDetail;

RequestGeneralModel(
{this.cropId,
this.activityId,
this.executeDate,
this.description,
this.objectUpdateDetail});

RequestGeneralModel.fromJson(Map<String, dynamic> json) {
cropId = json['cropId'];
activityId = json['activityId'];
executeDate = json['executeDate'];
description = json['description'];
if (json['objectUpdateDetail'] != null) {
objectUpdateDetail = new List<ObjectUpdateDetail>();
json['objectUpdateDetail'].forEach((v) {
objectUpdateDetail.add(new ObjectUpdateDetail.fromJson(v));
});
}
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['cropId'] = this.cropId;
data['activityId'] = this.activityId;
data['executeDate'] = this.executeDate;
data['description'] = this.description;
if (this.objectUpdateDetail != null) {
data['objectUpdateDetail'] =
this.objectUpdateDetail.map((v) => v.toJson()).toList();
}
return data;
}
}

class ObjectUpdateDetail {
String name;
String index;

ObjectUpdateDetail({this.name, this.index});

ObjectUpdateDetail.fromJson(Map<String, dynamic> json) {
name = json['name'];
index = json['index'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['index'] = this.index;
return data;
}
}

+ 7
- 7
lib/data/api/dio_provider.dart View File

@@ -21,11 +21,11 @@ class HttpLogInterceptor extends InterceptorsWrapper {
var token = await pref.getString(DATA_CONST.TOKEN_KEY);
options.headers["Authorization"] = "Bearer $token";
options.receiveTimeout = 20000;
// log("onRequest: ${options.uri}\n"
// "data=${options.data}\n"
// "method=${options.method}\n"
// "headers=${options.headers}\n"
// "queryParameters=${options.queryParameters}");
log("onRequest: ${options.uri}\n"
"data=${options.data}\n"
"method=${options.method}\n"
"headers=${options.headers}\n"
"queryParameters=${options.queryParameters}");
return options;
}

@@ -37,8 +37,8 @@ class HttpLogInterceptor extends InterceptorsWrapper {

@override
Future onError(DioError err) {
// log("onError: $err\n"
// "Response: ${err.response}");
log("onError: $err\n"
"Response: ${err.response}");
return super.onError(err);
}
}

+ 290
- 71
lib/presentation/screens/actions/crop_status/sc_edit_action_crop_status.dart View File

@@ -1,18 +1,36 @@
import 'dart:convert';

import 'package:farm_tpf/custom_model/CropStatus.dart';
import 'package:farm_tpf/custom_model/RequestGeneralModel.dart';
import 'package:farm_tpf/data/api/app_exception.dart';
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
import 'package:farm_tpf/presentation/custom_widgets/widget_media_picker.dart';
import 'package:farm_tpf/presentation/screens/actions/bloc/action_detail_bloc.dart';
import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_file_controller.dart';
import 'package:farm_tpf/presentation/screens/actions/util_action.dart';
import 'package:farm_tpf/utils/const_common.dart';
import 'package:farm_tpf/utils/const_string.dart';
import 'package:farm_tpf/utils/const_style.dart';
import 'package:farm_tpf/utils/pref.dart';
import 'package:farm_tpf/utils/validators.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:pattern_formatter/pattern_formatter.dart';
import 'package:farm_tpf/utils/formatter.dart';

class EditActionCropStatusScreen extends StatefulWidget {
final int cropId;
final bool isEdit;
final int activityId;
EditActionCropStatusScreen(
{@required this.cropId, this.isEdit = false, this.activityId});
@override
_EditActionCropStatusScreenState createState() =>
_EditActionCropStatusScreenState();
@@ -26,24 +44,25 @@ class _EditActionCropStatusScreenState
bool _autoValidate = false;
CropStatus _cropStatus = CropStatus();
var pref = LocalPref();
FlutterToast flutterToast;
TextEditingController _cropRateController = TextEditingController();
TextEditingController _numTreeController = TextEditingController();
TextEditingController _hightOfTreeController = TextEditingController();
TextEditingController _heightOfTreeController = TextEditingController();
TextEditingController _numberOfLeafController = TextEditingController();
TextEditingController _leafSizeController = TextEditingController();
TextEditingController _leafColorController = TextEditingController();
TextEditingController _abilityProduceBudsController = TextEditingController();
TextEditingController _bodySizeController = TextEditingController();
TextEditingController _internodeLengthController = TextEditingController();
TextEditingController _descriptionController = TextEditingController();

String executeTimeView;
DateTime executeTime = DateTime.now();
List<String> filePaths = List<String>();
var changeFileController = Get.put(ChangeFileController());

@override
void initState() {
super.initState();
flutterToast = FlutterToast(context);
changeFileController.initValue();
//UPDATE
if (_cropStatus != null) {
try {
@@ -57,6 +76,107 @@ class _EditActionCropStatusScreenState
_cropStatus.executeDate = "$parsedExecuteDate";
}
executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
_cropStatus.cropId = widget.cropId;
}

_validateInputs() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
LoadingDialog.showLoadingDialog(context);
filePaths = Get.find<ChangeFileController>().files;
//Create request general model
try {
RequestGeneralModel generalModel = RequestGeneralModel()
..cropId = _cropStatus.cropId
..activityId = _cropStatus.activityId
..description = _cropStatus.description
..executeDate = _cropStatus.executeDate;
var generalDetail = List<ObjectUpdateDetail>();
generalDetail.add(ObjectUpdateDetail()
..name = "TY_LE_CAY_TRONG"
..index = _cropStatus.cropRate);
generalDetail.add(ObjectUpdateDetail()
..name = "SO_LUONG_LEN_CAY"
..index = _cropStatus.numberOfTreeToGrow);
generalDetail.add(ObjectUpdateDetail()
..name = "CHIEU_CAO_CAY"
..index = _cropStatus.heightOfTree);
generalDetail.add(ObjectUpdateDetail()
..name = "SO_LA"
..index = _cropStatus.numberOfLeaf);
generalDetail.add(ObjectUpdateDetail()
..name = "KICH_THUOC_LA"
..index = _cropStatus.leafSize);
generalDetail.add(ObjectUpdateDetail()
..name = "MAU_LA"
..index = _cropStatus.leafColor);
generalDetail.add(ObjectUpdateDetail()
..name = "DAI_DOT_THAN"
..index = _cropStatus.internodeLength);
generalDetail.add(ObjectUpdateDetail()
..name = "KHA_NANG_SINH_CHOI"
..index = _cropStatus.abilityProduceBuds);
generalModel.objectUpdateDetail = generalDetail;
var activityCropStatus = jsonEncode(generalModel.toJson()).toString();
// var activityCropStatus = jsonEncode(_cropStatus.toJson()).toString();
//ADD NEW
if (_cropStatus.activityId == null) {
_repository.createAction((value) {
LoadingDialog.hideLoadingDialog(context);
Get.back(result: value);
Get.snackbar(label_add_success, "Hoạt động thực trạng cây trồng",
snackPosition: SnackPosition.BOTTOM);
}, (error) {
LoadingDialog.hideLoadingDialog(context);
_scaffoldKey.currentState.showSnackBar(SnackBar(
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(child: Text(AppException.handleError(error))),
Icon(Icons.error),
],
),
backgroundColor: Colors.red,
duration: Duration(seconds: 3),
));
},
apiAddAction: ConstCommon.apiAddCropStatus,
paramActivity: ConstCommon.paramsActionCropStatus,
activityAction: activityCropStatus,
filePaths: filePaths);
} else {
//UPDATE
_repository.updateAction((value) {
LoadingDialog.hideLoadingDialog(context);
Get.back(result: value);
Get.snackbar(label_update_success, "Hoạt động thực trạng cây trồng",
snackPosition: SnackPosition.BOTTOM);
}, (error) {
LoadingDialog.hideLoadingDialog(context);
_scaffoldKey.currentState.showSnackBar(SnackBar(
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(child: Text(AppException.handleError(error))),
Icon(Icons.error),
],
),
backgroundColor: Colors.red,
duration: Duration(seconds: 3),
));
},
apiUpdateAction: ConstCommon.apiUpdateCropStatus,
paramActivity: ConstCommon.paramsActionCropStatus,
activityAction: activityCropStatus,
filePaths: filePaths);
}
} catch (e) {
LoadingDialog.hideLoadingDialog(context);
print(e.toString());
}
} else {
_autoValidate = true;
}
}

Widget _btnExecuteTimePicker() {
@@ -108,7 +228,7 @@ class _EditActionCropStatusScreenState
return Validators.validNumber(value, "Tỉ lệ lên cây");
},
onSaved: (newValue) {
_cropStatus.cropRate = newValue.parseDoubleThousand();
_cropStatus.cropRate = newValue;
},
);
}
@@ -126,7 +246,7 @@ class _EditActionCropStatusScreenState
return Validators.validNumber(value, "Số lượng lên cây");
},
onSaved: (newValue) {
_cropStatus.numberOfTreeToGrow = newValue.parseDoubleThousand();
_cropStatus.numberOfTreeToGrow = newValue;
},
);
}
@@ -139,12 +259,12 @@ class _EditActionCropStatusScreenState
formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
],
decoration: InputDecoration(labelText: "Chiều cao cây"),
controller: _hightOfTreeController,
controller: _heightOfTreeController,
validator: (String value) {
return Validators.validNumber(value, "Chiều cao cây");
},
onSaved: (newValue) {
_cropStatus.hightOfTree = newValue.parseDoubleThousand();
_cropStatus.heightOfTree = newValue;
},
);
}
@@ -162,7 +282,7 @@ class _EditActionCropStatusScreenState
return Validators.validNumber(value, "Số lá");
},
onSaved: (newValue) {
_cropStatus.numberOfLeaf = newValue.parseDoubleThousand();
_cropStatus.numberOfLeaf = newValue;
},
);
}
@@ -180,7 +300,7 @@ class _EditActionCropStatusScreenState
return Validators.validNumber(value, "Kích thước lá");
},
onSaved: (newValue) {
_cropStatus.leafSize = newValue.parseDoubleThousand();
_cropStatus.leafSize = newValue;
},
);
}
@@ -196,7 +316,7 @@ class _EditActionCropStatusScreenState
);
}

Widget _bodySizeField() {
Widget _internodeLengthField() {
return TextFormField(
keyboardType: TextInputType.numberWithOptions(decimal: true),
inputFormatters: [
@@ -204,12 +324,12 @@ class _EditActionCropStatusScreenState
formatter: NumberFormat("#,###.##", "es"), allowFraction: true)
],
decoration: InputDecoration(labelText: "Dài đốt thân"),
controller: _bodySizeController,
controller: _internodeLengthController,
validator: (String value) {
return Validators.validNumber(value, "Dài đốt thân");
},
onSaved: (newValue) {
_cropStatus.bodySize = newValue.parseDoubleThousand();
_cropStatus.internodeLength = newValue;
},
);
}
@@ -231,7 +351,7 @@ class _EditActionCropStatusScreenState
decoration: InputDecoration(labelText: "Ghi chú"),
controller: _descriptionController,
onSaved: (newValue) {
_cropStatus.note = newValue;
_cropStatus.description = newValue;
},
);
}
@@ -244,7 +364,13 @@ class _EditActionCropStatusScreenState
Icons.done,
color: Colors.black,
),
onPressed: () {},
onPressed: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
_validateInputs();
},
);
return <Widget>[iconButton];
}
@@ -264,71 +390,164 @@ class _EditActionCropStatusScreenState
title: Text(plot_action_crop_status),
actions: _actionAppBar()),
body: KeyboardDismisser(
child: Form(
key: _formKey,
autovalidate: _autoValidate,
child: SingleChildScrollView(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Container(
width: double.infinity,
child: Text(
"Ngày thực hiện",
style: TextStyle(
color: Colors.black54, fontSize: 13.0),
child: MultiBlocProvider(
providers: [
BlocProvider<ActionDetailBloc>(
create: (context) =>
ActionDetailBloc(repository: Repository())
..add(FetchData(
isNeedFetchData: widget.isEdit,
apiActivity: ConstCommon.apiDetailCropStatus,
activityId: widget.activityId))),
BlocProvider<MediaHelperBloc>(
create: (context) =>
MediaHelperBloc()..add(ChangeListMedia(items: [])),
)
],
child: Form(
key: _formKey,
autovalidate: _autoValidate,
child: SingleChildScrollView(
padding: EdgeInsets.all(8.0),
child: BlocConsumer<ActionDetailBloc, ActionDetailState>(
listener: (context, state) async {
if (state is ActionDetailFailure) {
print("fail");
LoadingDialog.hideLoadingDialog(context);
} else if (state is ActionDetailSuccess) {
LoadingDialog.hideLoadingDialog(context);
print("success");
print(state.item);
_cropStatus = CropStatus.fromJson(state.item);
_cropStatus.activityId = widget.activityId;
_cropRateController.text = _cropStatus.cropRate
.formatStringToStringDecimal();
_numTreeController.text = _cropStatus
.numberOfTreeToGrow
.formatStringToStringDecimal();
_heightOfTreeController.text = _cropStatus
.heightOfTree
.formatStringToStringDecimal();
_numberOfLeafController.text = _cropStatus
.numberOfLeaf
.formatStringToStringDecimal();
_leafSizeController.text = _cropStatus.leafSize
.formatStringToStringDecimal();
_leafColorController.text =
_cropStatus.leafColor ?? "";
_abilityProduceBudsController.text =
_cropStatus.abilityProduceBuds ?? "";
_internodeLengthController.text = _cropStatus
.internodeLength
.formatStringToStringDecimal();
_descriptionController.text =
_cropStatus.description ?? "";

try {
executeTime =
DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
.parse(_cropStatus.executeDate);
} catch (_) {}
executeTimeView = DateFormat("dd/MM/yyyy HH:mm")
.format(executeTime);
//Show media
if (_cropStatus.media != null) {
await UtilAction.cacheFiles(_cropStatus.media)
.then((value) {
print("then: ${value.length}");
BlocProvider.of<MediaHelperBloc>(context)
.add(ChangeListMedia(items: value));
}).whenComplete(() {
print("completed");
});
}
} else if (state is ActionDetailInitial) {
print("init");
} else if (state is ActionDetailLoading) {
print("loading");
LoadingDialog.showLoadingDialog(context);
}
},
builder: (context, state) {
return Column(
children: <Widget>[
Container(
width: double.infinity,
child: Text(
"Ngày thực hiện",
style: TextStyle(
color: Colors.black54, fontSize: 13.0),
),
),
_btnExecuteTimePicker(),
SizedBox(
height: 8.0,
),
_cropRateField(),
SizedBox(
height: 8.0,
),
_numTreeField(),
SizedBox(
height: 8.0,
),
_hightOfTreeField(),
SizedBox(
height: 8.0,
),
_numberOfLeafField(),
SizedBox(
height: 8.0,
),
_leafSizeField(),
SizedBox(
height: 8.0,
),
_leafColorField(),
SizedBox(
height: 8.0,
),
_internodeLengthField(),
SizedBox(
height: 8.0,
),
_abilityProduceBudsField(),
SizedBox(
height: 8.0,
),
),
_btnExecuteTimePicker(),
SizedBox(
height: 8.0,
),
_cropRateField(),
SizedBox(
height: 8.0,
),
_numTreeField(),
SizedBox(
height: 8.0,
),
_hightOfTreeField(),
SizedBox(
height: 8.0,
),
_numberOfLeafField(),
SizedBox(
height: 8.0,
),
_leafSizeField(),
SizedBox(
height: 8.0,
),
_leafColorField(),
SizedBox(
height: 8.0,
),
_bodySizeField(),
SizedBox(
height: 8.0,
),
_abilityProduceBudsField(),
SizedBox(
height: 8.0,
),
_desciptionField()
],
),
)))));
_desciptionField(),
BlocBuilder<MediaHelperBloc, MediaHelperState>(
builder: (context, state) {
if (state is MediaHelperSuccess) {
print("length: " +
state.items.length.toString());
return WidgetMediaPicker(
currentItems: state.items,
onChangeFiles: (filePaths) async {
Get.find<ChangeFileController>()
.addAllFile(filePaths);
});
} else {
return Center(
child: CircularProgressIndicator());
}
}),
],
);
},
),
)),
))));
@override
void dispose() {
_cropRateController.dispose();
_numTreeController.dispose();
_hightOfTreeController.dispose();
_heightOfTreeController.dispose();
_numberOfLeafController.dispose();
_leafSizeController.dispose();
_leafColorController.dispose();
_abilityProduceBudsController.dispose();
_bodySizeController.dispose();
_internodeLengthController.dispose();
_descriptionController.dispose();
super.dispose();
}

+ 23
- 0
lib/presentation/screens/actions/util_action.dart View File

@@ -0,0 +1,23 @@
import 'package:farm_tpf/custom_model/Media.dart';
import 'package:farm_tpf/utils/const_common.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:mime/mime.dart';

class UtilAction {
static Future<List<Media>> cacheFiles(String existedMedias) async {
var medias = List<Media>();
var mediaPaths = existedMedias.split(";");
for (int i = 0; i < mediaPaths.length; i++) {
var tempFile = await DefaultCacheManager()
.getSingleFile(ConstCommon.baseImageUrl + mediaPaths[i]);
print(tempFile.path);
var isVideo = lookupMimeType(tempFile.path) == "video/mp4";
print("file type: " + lookupMimeType(tempFile.path));
Media media = Media()
..pathFile = tempFile.path
..isVideo = isVideo;
medias.add(media);
}
return medias;
}
}

+ 11
- 1
lib/presentation/screens/plot_detail/sc_plot_action.dart View File

@@ -52,7 +52,11 @@ class _PlotActionScreenState extends State<PlotActionScreen> {
)));
actions.add(ActionType(plot_action_plant, null, EditActionPlantScreen()));
actions.add(ActionType(
plot_action_crop_status, null, EditActionCropStatusScreen()));
plot_action_crop_status,
null,
EditActionCropStatusScreen(
cropId: widget.cropId,
)));
actions.add(ActionType(
plot_action_environment_update, null, EditActionEnvironmentUpdate()));
actions.add(ActionType(plot_action_dung, null, EditActionDungScreen()));
@@ -362,6 +366,12 @@ class ItemInfinityWidget extends StatelessWidget {
}
}
});
} else if (item.activityTypeName == "ACTIVE_TYPE_STATUS_CROP") {
Get.to(EditActionCropStatusScreen(
cropId: item.cropId,
activityId: item.id,
isEdit: true,
));
}
});
}

+ 6
- 0
lib/utils/const_common.dart View File

@@ -5,10 +5,16 @@ class ConstCommon {
static const String baseImageUrl = "http://s3.tpf.aztrace.vn/upload/";

static const String apiDetailNursery = "api/activity-nursery";
static const String apiDetailCropStatus = "api/activity-crop-status";

//nursery
static const String paramsActionNursery = "activityNursery";
static const String apiUpdateNursery = "api/updateNursery";
static const String apiAddNursery = "api/createNursery";
//crop_status
static const String paramsActionCropStatus = "activityCrop";
static const String apiUpdateCropStatus = "api/updateStatusCrop";
static const String apiAddCropStatus = "api/createStatusCrop";

static const String supplyTypeSeed = "GIONG";
static const String supplyTypeDung = "PHANBON";

+ 11
- 0
lib/utils/formatter.dart View File

@@ -27,6 +27,17 @@ extension ddMM_HHmm on String {
return "";
}
}

String formatStringToStringDecimal() {
try {
var numOfString = double.tryParse(this.toString());
var numWithLocalSeparator = new NumberFormat.decimalPattern("vi_VN");
final str = numWithLocalSeparator.format(numOfString);
return str;
} catch (_) {
return "";
}
}
}

extension numToString on num {

Loading…
Cancel
Save