Browse Source

update action nursery

master
daivph 5 years ago
parent
commit
e5274ae021
9 changed files with 234 additions and 45 deletions
  1. +12
    -0
      ios/Podfile.lock
  2. +8
    -8
      lib/data/api/dio_provider.dart
  3. +21
    -0
      lib/data/repository/repository.dart
  4. +11
    -3
      lib/presentation/custom_widgets/widget_media_picker.dart
  5. +125
    -30
      lib/presentation/screens/actions/nursery/sc_edit_action_nursery.dart
  6. +17
    -3
      lib/presentation/screens/plot_detail/sc_plot_action.dart
  7. +1
    -0
      lib/utils/const_common.dart
  8. +36
    -1
      pubspec.lock
  9. +3
    -0
      pubspec.yaml

+ 12
- 0
ios/Podfile.lock View File

@@ -85,6 +85,9 @@ PODS:
- Protobuf (>= 3.9.2, ~> 3.9)
- FLAnimatedImage (1.0.12)
- Flutter (1.0.0)
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- GoogleDataTransport (7.3.0):
- nanopb (~> 1.30906.0)
- GoogleUtilities/AppDelegateSwizzler (6.7.2):
@@ -126,6 +129,9 @@ PODS:
- SDWebImage/Core (~> 5.6)
- shared_preferences (0.0.1):
- Flutter
- sqflite (0.0.1):
- Flutter
- FMDB (~> 2.7.2)
- SwiftProtobuf (1.12.0)
- thumbnails (0.0.1):
- Flutter
@@ -143,6 +149,7 @@ DEPENDENCIES:
- package_info (from `.symlinks/plugins/package_info/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- thumbnails (from `.symlinks/plugins/thumbnails/ios`)
- video_player (from `.symlinks/plugins/video_player/ios`)

@@ -159,6 +166,7 @@ SPEC REPOS:
- FirebaseInstanceID
- FirebaseMessaging
- FLAnimatedImage
- FMDB
- GoogleDataTransport
- GoogleUtilities
- MTBBarcodeScanner
@@ -190,6 +198,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/path_provider/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
thumbnails:
:path: ".symlinks/plugins/thumbnails/ios"
video_player:
@@ -213,6 +223,7 @@ SPEC CHECKSUMS:
FirebaseMessaging: 29543feb343b09546ab3aa04d008ee8595b43c44
FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
GoogleDataTransport: e85fb700c9b027079ce182c3d08e12e0f9618bb4
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09
@@ -225,6 +236,7 @@ SPEC CHECKSUMS:
SDWebImage: a990c053fff71e388a10f3357edb0be17929c9c5
SDWebImageFLPlugin: 6c2295fb1242d44467c6c87dc5db6b0a13228fd8
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0
SwiftProtobuf: 4ef85479c18ca85b5482b343df9c319c62bda699
thumbnails: bb4f4e9bb4b51c8ae4e6ad9a2fa81373f9b634ad
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e

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

@@ -21,24 +21,24 @@ 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;
}

@override
Future onResponse(Response response) {
// log("onResponse: $response");
log("onResponse: $response");
return super.onResponse(response);
}

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

+ 21
- 0
lib/data/repository/repository.dart View File

@@ -92,6 +92,27 @@ class Repository {
}
}

Future<void> updateNursery(Function(dynamic) onSuccess,
Function(String) onError, String activityNursery,
{List<String> filePaths}) async {
var formData = FormData();
filePaths.forEach((f) {
formData.files.add(MapEntry("images", MultipartFile.fromFileSync(f)));
});
formData.fields.add(MapEntry("activityNursery", activityNursery));
try {
await dio
.post("${ConstCommon.baseUrl}/api/updateNursery", data: formData)
.then((value) {
onSuccess(value);
}).catchError((onError) {
onError(AppException.handleError(onError));
});
} catch (e) {
onError(AppException.handleError(e));
}
}

//Device
Future<List<Device>> getDevices() {
final client = RestClient(dio);

+ 11
- 3
lib/presentation/custom_widgets/widget_media_picker.dart View File

@@ -16,8 +16,9 @@ import 'bloc/media_helper_bloc.dart';
import 'hoz_list_view.dart';

class WidgetMediaPicker extends StatefulWidget {
final List<Media> currentItems;
final Function(List<String> filePaths) onChangeFiles;
WidgetMediaPicker({@required this.onChangeFiles});
WidgetMediaPicker({this.currentItems, @required this.onChangeFiles});
@override
_WidgetMediaPickerState createState() => _WidgetMediaPickerState();
}
@@ -41,6 +42,7 @@ class _WidgetMediaPickerState extends State<WidgetMediaPicker> {
if (state is MediaHelperFailure) {
return Container();
} else if (state is MediaHelperSuccess) {
currentItems = widget.currentItems ?? [];
return Container(
padding: EdgeInsets.all(8),
child: Column(
@@ -203,9 +205,15 @@ class _WidgetMediaPickerState extends State<WidgetMediaPicker> {
return BlocBuilder<MediaHelperBloc, MediaHelperState>(
builder: (context, state) {
if (state is MediaHelperSuccess) {
print("build list items length: " + state.items.length.toString());
print("" + currentItems.length.toString());
files = [];
currentItems.forEach((element) {
files.add(element.pathFile);
});
return WrapContentHozListView(
itemBuilder: (context, index) {
var item = state.items[index];
var item = currentItems[index];
return _WidgetItemMedia(
item: item,
deleteImage: (item) {
@@ -219,7 +227,7 @@ class _WidgetMediaPickerState extends State<WidgetMediaPicker> {
separatorBuilder: (context, index) {
return SizedBox(width: 4);
},
list: state.items,
list: currentItems,
);
}
return Container();

+ 125
- 30
lib/presentation/screens/actions/nursery/sc_edit_action_nursery.dart View File

@@ -1,9 +1,12 @@
import 'dart:convert';

import 'package:farm_tpf/custom_model/Media.dart';
import 'package:farm_tpf/custom_model/Nursery.dart';
import 'package:farm_tpf/custom_model/NurseryDetail.dart';
import 'package:farm_tpf/data/api/app_exception.dart';
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/models/index.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';
@@ -18,16 +21,23 @@ 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_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import 'package:get/state_manager.dart';
import 'package:intl/intl.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:mime/mime.dart';
import 'package:pattern_formatter/pattern_formatter.dart';
import 'package:farm_tpf/utils/formatter.dart';

class EditActionNurseryScreen extends StatefulWidget {
final int cropId;
final bool isEdit;
final int activityId;
EditActionNurseryScreen(
{@required this.cropId, this.isEdit = false, this.activityId});
@override
_EditActionNurseryState createState() => _EditActionNurseryState();
}
@@ -66,7 +76,7 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
_nursery.nurseryDetail = new List<NurseryDetail>();
flutterToast = FlutterToast(context);
//UPDATE
if (_nursery.cropId != null) {
if (_nursery.id != null) {
try {
executeTime =
DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(_nursery.executeDate);
@@ -76,24 +86,61 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
var parsedExecuteDate =
DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(executeTime);
_nursery.executeDate = "$parsedExecuteDate";
//TODO: update cropid
_nursery.cropId = 1;
}
executeTimeView = DateFormat("dd/MM/yyyy HH:mm").format(executeTime);
_nursery.cropId = widget.cropId;
}

_validateInputs() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
LoadingDialog.showLoadingDialog(context);
_nursery.nurseryDetail = currentNurseryDetail;
filePaths = Get.find<ChangeFileController>().files;
var activityNursery = jsonEncode(_nursery.toJson()).toString();
_repository.createNursery((value) {
print("post ok");
}, (error) {
print("--------------------------------");
print(error);
}, activityNursery, filePaths: filePaths);
//ADD NEW
if (_nursery.activityId == null) {
_repository.createNursery((value) {
LoadingDialog.hideLoadingDialog(context);
Get.back();
Get.snackbar(label_add_success, "Hoạt động ươm",
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),
));
}, activityNursery, filePaths: filePaths);
} else {
//UPDATE
_repository.updateNursery((value) {
LoadingDialog.hideLoadingDialog(context);
Get.back();
Get.snackbar(label_add_success, "Hoạt động ươm",
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),
));
}, activityNursery, filePaths: filePaths);
}
} else {
_autoValidate = true;
}
@@ -278,17 +325,13 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
keyboardType: TextInputType.text,
controller: _workerNameController,
decoration: InputDecoration(labelText: "Tên công nhân"),
onSaved: (newValue) {
_nursery.description = newValue;
},
onSaved: (newValue) {},
),
TextFormField(
keyboardType: TextInputType.text,
controller: _trayNumberController,
decoration: InputDecoration(labelText: "Ươm khây số"),
onSaved: (newValue) {
_nursery.description = newValue;
},
onSaved: (newValue) {},
),
Align(
alignment: Alignment.centerRight,
@@ -479,10 +522,15 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
create: (context) => StatusAddFormBloc(),
),
BlocProvider<ActionDetailBloc>(
create: (context) => ActionDetailBloc(
repository: Repository())
..add(
FetchData(isNeedFetchData: true, activityId: 1)))
create: (context) =>
ActionDetailBloc(repository: Repository())
..add(FetchData(
isNeedFetchData: widget.isEdit,
activityId: widget.activityId))),
BlocProvider<MediaHelperBloc>(
create: (context) =>
MediaHelperBloc()..add(ChangeListMedia(items: [])),
)
],
child: Form(
key: _formKey,
@@ -491,16 +539,34 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
padding: EdgeInsets.all(8.0),
child: BlocConsumer<ActionDetailBloc,
ActionDetailState>(
listener: (context, state) {
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);
_nursery = Nursery.fromJson(state.item);
_quantityController.text =
"sfdf ${_nursery.id}";
_seedLengthController.text =
_nursery.seedLength.toString();
//Show media
if (_nursery.media.isNotEmpty) {
await cacheFiles(_nursery.media)
.then((value) {
print("then: ${value.length}");
BlocProvider.of<MediaHelperBloc>(context)
.add(ChangeListMedia(items: value));
}).whenComplete(() {
print("completed");
});
}
//Show worker
if (_nursery.nurseryDetail.length > 0) {
BlocProvider.of<ExpansionListBloc>(context)
.add(AddNew(
items: _nursery.nurseryDetail));
}
} else if (state is ActionDetailInitial) {
print("init");
} else if (state is ActionDetailLoading) {
@@ -561,14 +627,23 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
SizedBox(
height: 8.0,
),
WidgetMediaPicker(
onChangeFiles: (filePaths) {
Get.find<ChangeFileController>()
.addAllFile(filePaths);
// setState(() {
// filePaths = filePaths;
// });
})
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());
}
}),
],
);
},
@@ -583,6 +658,26 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
_descriptionController.dispose();
super.dispose();
}

Future<List<Media>> cacheFiles(String existedMedias) async {
var medias = List<Media>();
var mediaPathsLocal = List<String>();
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);
mediaPathsLocal.add(tempFile.path);
}
Get.find<ChangeFileController>().addAllFile(filePaths);
return medias;
}
}

class ChangeSupply extends GetxController {

+ 17
- 3
lib/presentation/screens/plot_detail/sc_plot_action.dart View File

@@ -20,6 +20,7 @@ import 'package:farm_tpf/utils/const_string.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:farm_tpf/utils/formatter.dart';
import 'package:get/get.dart';

class PlotActionScreen extends StatefulWidget {
int cropId;
@@ -41,8 +42,12 @@ class _PlotActionScreenState extends State<PlotActionScreen> {
}

_initActionButtons() {
actions
.add(ActionType(plot_action_nursery, null, EditActionNurseryScreen()));
actions.add(ActionType(
plot_action_nursery,
null,
EditActionNurseryScreen(
cropId: widget.cropId,
)));
actions.add(ActionType(plot_action_plant, null, EditActionPlantScreen()));
actions.add(ActionType(
plot_action_crop_status, null, EditActionCropStatusScreen()));
@@ -282,9 +287,18 @@ class ItemInfinityWidget extends StatelessWidget {
child: ListTile(
title: Text(item.activityTypeDescription ?? ''),
subtitle: Text(item.executeDate.format_DDMMYY_HHmm()),
trailing: Text(item.id.toString()),
),
),
onTap: () {});
onTap: () {
if (item.activityTypeName == "ACTIVE_TYPE_NURSERY") {
Get.to(EditActionNurseryScreen(
cropId: item.cropId,
activityId: item.id,
isEdit: true,
));
}
});
}
}


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

@@ -2,6 +2,7 @@ class ConstCommon {
static int kExpiredTime = 12 * 60 * 60 * 1000; //24h
static int kFileSize = 1000000; //1M = 1000.000 bytes
static const String baseUrl = "http://tpf.aztrace.vn";
static const String baseImageUrl = "http://s3.tpf.aztrace.vn/upload/";

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

+ 36
- 1
pubspec.lock View File

@@ -293,6 +293,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.5"
flutter_cache_manager:
dependency: "direct main"
description:
name: flutter_cache_manager
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.2"
flutter_datetime_picker:
dependency: "direct main"
description:
@@ -467,7 +474,7 @@ packages:
source: hosted
version: "1.1.8"
mime:
dependency: transitive
dependency: "direct main"
description:
name: mime
url: "https://pub.dartlang.org"
@@ -723,6 +730,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
sqflite:
dependency: transitive
description:
name: sqflite
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1+1"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2+1"
stack_trace:
dependency: transitive
description:
@@ -751,6 +772,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
synchronized:
dependency: transitive
description:
name: synchronized
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0+2"
term_glyph:
dependency: transitive
description:
@@ -793,6 +821,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.2"
vector_math:
dependency: transitive
description:

+ 3
- 0
pubspec.yaml View File

@@ -51,6 +51,9 @@ dependencies:
path_provider: ^1.6.14
file_picker: ^2.0.0
thumbnails: ^1.0.1
flutter_cache_manager: ^1.4.2

mime: ^0.9.7

dev_dependencies:
flutter_test:

Loading…
Cancel
Save