Browse Source

apply api post action nursery

master
daivph 5 years ago
parent
commit
634f0c3bbf
7 changed files with 359 additions and 160 deletions
  1. +5
    -0
      lib/custom_model/Media.dart
  2. +6
    -3
      lib/data/repository/repository.dart
  3. +22
    -0
      lib/presentation/custom_widgets/bloc/media_helper_bloc.dart
  4. +13
    -0
      lib/presentation/custom_widgets/bloc/media_helper_event.dart
  5. +28
    -0
      lib/presentation/custom_widgets/bloc/media_helper_state.dart
  6. +245
    -155
      lib/presentation/custom_widgets/widget_media_helper.dart
  7. +40
    -2
      lib/presentation/screens/actions/nursery/sc_edit_action_nursery.dart

+ 5
- 0
lib/custom_model/Media.dart View File

@@ -0,0 +1,5 @@
class Media {
String pathFile;
bool isVideo;
bool isServerFile = false;
}

+ 6
- 3
lib/data/repository/repository.dart View File

@@ -67,9 +67,12 @@ class Repository {
//Action
Future<void> createNursery(Function(dynamic) onSuccess,
Function(String) onError, String activityNursery,
{List<File> files}) async {
FormData formData =
new FormData.fromMap({"activityNursery": 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/createNursery", data: formData)

+ 22
- 0
lib/presentation/custom_widgets/bloc/media_helper_bloc.dart View File

@@ -0,0 +1,22 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/custom_model/Media.dart';
import 'package:meta/meta.dart';

part 'media_helper_event.dart';
part 'media_helper_state.dart';

class MediaHelperBloc extends Bloc<MediaHelperEvent, MediaHelperState> {
MediaHelperBloc() : super(MediaHelperInitial());

@override
Stream<MediaHelperState> mapEventToState(
MediaHelperEvent event,
) async* {
if (event is ChangeListMedia) {
yield MediaHelperSuccess(items: event.items);
}
}
}

+ 13
- 0
lib/presentation/custom_widgets/bloc/media_helper_event.dart View File

@@ -0,0 +1,13 @@
part of 'media_helper_bloc.dart';

abstract class MediaHelperEvent {
const MediaHelperEvent();

@override
List<Object> get props => [];
}

class ChangeListMedia extends MediaHelperEvent {
final List<Media> items;
ChangeListMedia({@required this.items});
}

+ 28
- 0
lib/presentation/custom_widgets/bloc/media_helper_state.dart View File

@@ -0,0 +1,28 @@
part of 'media_helper_bloc.dart';

abstract class MediaHelperState {
const MediaHelperState();

@override
List<Object> get props => [];
}

class MediaHelperInitial extends MediaHelperState {}

class MediaHelperFailure extends MediaHelperState {
final String errorString;
MediaHelperFailure({@required this.errorString});
}

class MediaHelperSuccess extends MediaHelperState {
final List<Media> items;

const MediaHelperSuccess({@required this.items});

MediaHelperSuccess copyWith({List<Media> items}) {
return MediaHelperSuccess(items: items ?? this.items);
}

@override
List<Object> get props => [items];
}

+ 245
- 155
lib/presentation/custom_widgets/widget_media_helper.dart View File

@@ -1,6 +1,8 @@
import 'dart:io';
import 'dart:async';

import 'package:farm_tpf/custom_model/Media.dart';
import 'package:farm_tpf/presentation/custom_widgets/bloc/media_helper_bloc.dart';
import 'package:farm_tpf/presentation/custom_widgets/hoz_list_view.dart';
import 'package:farm_tpf/presentation/custom_widgets/shimmer_image.dart';
import 'package:farm_tpf/utils/const_color.dart';
@@ -8,15 +10,21 @@ import 'package:farm_tpf/utils/const_string.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get/get.dart';
import 'package:get/state_manager.dart';
import 'package:image_picker/image_picker.dart';
import 'package:video_player/video_player.dart';

class WidgetMediaHelper extends StatefulWidget {
final Function(List<String> filePaths) onChangeFiles;
WidgetMediaHelper({@required this.onChangeFiles});
@override
_WidgetMediaHelperState createState() => _WidgetMediaHelperState();
}

class _WidgetMediaHelperState extends State<WidgetMediaHelper> {
final globalScaffoldKey = GlobalKey<ScaffoldState>();
PickedFile _imageFile;
dynamic _pickImageError;
bool isVideo = false;
@@ -25,97 +33,141 @@ class _WidgetMediaHelperState extends State<WidgetMediaHelper> {
String _retrieveDataError;

final ImagePicker _picker = ImagePicker();
List<ItemMediaVM> items = [];
List<Media> currentItems = [];
List<String> files = new List<String>();
var changeImageController = Get.put(ChangeImageController());
double imageWidth = 90;
double imageHeight = 90;

@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8),
child: Column(
children: <Widget>[
_actionButton(),
SizedBox(
height: 4.0,
),
_buildListPoster(),
defaultTargetPlatform == TargetPlatform.android
? FutureBuilder<void>(
future: retrieveLostData(),
builder:
(BuildContext context, AsyncSnapshot<void> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
case ConnectionState.done:
return isVideo ? _previewVideo() : _previewImage();
default:
if (snapshot.hasError) {
return Text(
'Pick image/video error: ${snapshot.error}}',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
},
)
: (isVideo ? _previewVideo() : _previewImage()),
],
));
void initState() {
super.initState();
changeImageController.initValue();
}

_buildListPoster() {
return WrapContentHozListView(
itemBuilder: (context, index) {
var item = items[index];
return _WidgetItemMedia(item);
},
separatorBuilder: (context, index) {
return SizedBox(width: 14);
},
list: items,
);
@override
Widget build(BuildContext context) {
return BlocProvider<MediaHelperBloc>(
create: (BuildContext contextA) =>
MediaHelperBloc()..add(ChangeListMedia(items: currentItems)),
child: BlocBuilder<MediaHelperBloc, MediaHelperState>(
builder: (contextB, state) {
if (state is MediaHelperFailure) {
return Container();
} else if (state is MediaHelperSuccess) {
return Container(
padding: EdgeInsets.all(8),
child: Column(
children: <Widget>[
SizedBox(
width: double.infinity,
height: 44,
child: FlatButton(
onPressed: () {
showDialog(
context: context,
barrierDismissible: true,
builder: (context) => Opacity(
child: multipleChoice(contextB),
opacity: 1,
));
},
color: COLOR_CONST.DEFAULT,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(7.0),
),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.image, color: Colors.white),
SizedBox(
width: 8.0,
),
Text(
button_add_media,
style: TextStyle(
fontWeight: FontWeight.bold,
color: COLOR_CONST.WHITE),
)
],
),
)),
),
SizedBox(
height: 4.0,
),
Container(
height: 150,
child: _buildListPoster(),
),
defaultTargetPlatform == TargetPlatform.android
? FutureBuilder<void>(
future: retrieveLostData(),
builder: (BuildContext context,
AsyncSnapshot<void> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
case ConnectionState.done:
return isVideo
? _previewVideo()
: _previewImage();
default:
if (snapshot.hasError) {
return Text(
'Pick image/video error: ${snapshot.error}}',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
},
)
: (isVideo ? _previewVideo() : _previewImage()),
],
));
}
return Container();
}));
}

Widget viewResult() {
FutureBuilder<void>(
future: retrieveLostData(),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
case ConnectionState.done:
return isVideo ? _previewVideo() : _previewImage();
default:
if (snapshot.hasError) {
return Text(
'Pick image/video error: ${snapshot.error}}',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
},
);
_buildListPoster() {
return BlocBuilder<MediaHelperBloc, MediaHelperState>(
builder: (context, state) {
if (state is MediaHelperSuccess) {
return WrapContentHozListView(
itemBuilder: (context, index) {
var item = state.items[index];
return _WidgetItemMedia(
item: item,
deleteImage: (item) {
files.remove(item.pathFile);
currentItems.remove(item);
widget.onChangeFiles(files);
BlocProvider.of<MediaHelperBloc>(context)
.add(ChangeListMedia(items: currentItems));
});
},
separatorBuilder: (context, index) {
return SizedBox(width: 14);
},
list: state.items,
);
}
return Container();
});
}

Widget multipleChoice() {
Widget multipleChoice(BuildContext context) {
return CupertinoAlertDialog(
title: Text(label_title_select_media),
actions: <Widget>[
@@ -159,40 +211,43 @@ class _WidgetMediaHelperState extends State<WidgetMediaHelper> {
}

Widget _actionButton() {
return SizedBox(
width: double.infinity,
height: 44,
child: FlatButton(
onPressed: () {
showDialog(
context: context,
barrierDismissible: true,
builder: (context) => Opacity(
child: multipleChoice(),
opacity: 1,
));
},
color: COLOR_CONST.DEFAULT,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(7.0),
),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.image, color: Colors.white),
SizedBox(
width: 8.0,
),
Text(
button_add_media,
style: TextStyle(
fontWeight: FontWeight.bold, color: COLOR_CONST.WHITE),
)
],
return BlocListener<MediaHelperBloc, MediaHelperState>(
listener: (context, state) {
SizedBox(
width: double.infinity,
height: 44,
child: FlatButton(
onPressed: () {
showDialog(
context: context,
barrierDismissible: true,
builder: (context) => Opacity(
child: Text(""),
opacity: 1,
));
},
color: COLOR_CONST.DEFAULT,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(7.0),
),
)),
);
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.image, color: Colors.white),
SizedBox(
width: 8.0,
),
Text(
button_add_media,
style: TextStyle(
fontWeight: FontWeight.bold, color: COLOR_CONST.WHITE),
)
],
),
)),
);
});
}

Future<void> _playVideo(PickedFile file) async {
@@ -203,11 +258,10 @@ class _WidgetMediaHelperState extends State<WidgetMediaHelper> {
await _controller.initialize();
await _controller.setLooping(true);
await _controller.play();
setState(() {});
}
}

void _onImageButtonPressed(ImageSource source, {BuildContext context}) async {
_onImageButtonPressed(ImageSource source, {BuildContext context}) async {
if (_controller != null) {
await _controller.setVolume(0.0);
}
@@ -221,20 +275,27 @@ class _WidgetMediaHelperState extends State<WidgetMediaHelper> {
try {
final pickedFile = await _picker.getImage(
source: source,
maxWidth: maxWidth,
maxHeight: maxHeight,
maxWidth: imageWidth,
maxHeight: imageHeight,
imageQuality: quality,
);
setState(() {
_imageFile = pickedFile;
});

Get.find<ChangeImageController>().updateFile(pickedFile);
Media newMedia = Media()
..isVideo = false
..isServerFile = false
..pathFile = pickedFile.path;
currentItems.add(newMedia);
files.add(pickedFile.path);
BlocProvider.of<MediaHelperBloc>(context)
..add(ChangeListMedia(items: currentItems));
widget.onChangeFiles(files);
} catch (e) {
setState(() {
_pickImageError = e;
});
Get.find<ChangeImageController>().updateFileError(e);
}
});
}
;
}

@override
@@ -278,30 +339,37 @@ class _WidgetMediaHelperState extends State<WidgetMediaHelper> {
}

Widget _previewImage() {
final Text retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_imageFile != null) {
var imageResult =
Image.file(File(_imageFile.path), width: 100, height: 100);
setState(() {
items.insert(0, ItemMediaVM(_imageFile.path, false, imageResult));
});
return Container(
child: Text("ok"),
);
} else if (_pickImageError != null) {
return Text(
'Pick image error: $_pickImageError',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
return Builder(builder: (context) {
final Text retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_imageFile != null) {
var imageResult =
Image.file(File(_imageFile.path), width: imageWidth, height: 100);
Media newMedia = Media()
..isVideo = false
..isServerFile = false
..pathFile = _imageFile.path;
currentItems.add(newMedia);
BlocProvider.of<MediaHelperBloc>(context)
.add(ChangeListMedia(items: currentItems));
//widget.onChangeFiles(files);
return Container(
child: Text("ok"),
);
} else if (_pickImageError != null) {
return Text(
'Pick image error: $_pickImageError',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
});
}

Future<void> retrieveLostData() async {
@@ -395,9 +463,10 @@ class AspectRatioVideoState extends State<AspectRatioVideo> {
}

class _WidgetItemMedia extends StatelessWidget {
final ItemMediaVM item;
ItemMediaCallback deleteImage;
final Media item;

_WidgetItemMedia(this.item);
_WidgetItemMedia({@required this.item, @required this.deleteImage});

BuildContext _context;

@@ -415,14 +484,14 @@ class _WidgetItemMedia extends StatelessWidget {
Positioned(
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: item.image == null
child: item.isServerFile
? ShimmerImage(
item.photo,
item.pathFile,
width: 93,
height: 124,
fit: BoxFit.cover,
)
: Image.file(File(item.photo), width: 100, height: 100),
: Image.file(File(item.pathFile), width: 100, height: 100),
)),
Positioned(
top: -5,
@@ -434,6 +503,7 @@ class _WidgetItemMedia extends StatelessWidget {
),
onPressed: () {
print("On tap delete media");
deleteImage(item);
}),
)
],
@@ -441,6 +511,8 @@ class _WidgetItemMedia extends StatelessWidget {
}
}

typedef ItemMediaCallback = void Function(Media item);

class ItemMediaVM {
String photo;
bool isVideo;
@@ -448,3 +520,21 @@ class ItemMediaVM {

ItemMediaVM(this.photo, this.isVideo, this.image);
}

class ChangeImageController extends GetxController {
PickedFile _imageFile;
dynamic _pickImageError;
void initValue() {
update();
}

void updateFile(PickedFile imageFile) {
_imageFile = imageFile;
update();
}

void updateFileError(dynamic pickImageError) {
_pickImageError = pickImageError;
update();
}
}

+ 40
- 2
lib/presentation/screens/actions/nursery/sc_edit_action_nursery.dart View File

@@ -53,11 +53,16 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
bool isResetForm = true;
final changeSupply = Get.put(ChangeSupply());
int selectedSupplyId = -1;
List<String> filePaths = List<String>();
var changeFileController = Get.put(ChangeFileController());

@override
void initState() {
super.initState();
changeSupply.initValue();
changeFileController.initValue();
filePaths.add(
"/Users/macbook/Library/Developer/CoreSimulator/Devices/CC52586C-39AA-489B-A74D-83107AA9F7C1/data/Containers/Data/Application/F377B9A4-939D-42B2-9628-350C4A0BFD50/tmp/image_picker_801FCF0F-577F-4AFA-AC58-1C716A1C561C-30707-000015F0E14256F8.jpg");
_nursery.nurseryDetail = new List<NurseryDetail>();
flutterToast = FlutterToast(context);
//UPDATE
@@ -80,13 +85,15 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
_validateInputs() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
_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);
}, activityNursery, filePaths: filePaths);
} else {
_autoValidate = true;
}
@@ -238,6 +245,7 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
}

Widget _btnAddWorker() {
//TODO :check flow error sua item -> xoa list -> bam nut them
return Builder(builder: (context) {
return BlocConsumer<StatusAddFormBloc, StatusAddFormState>(
listener: (context, state) {
@@ -526,7 +534,13 @@ class _EditActionNurseryState extends State<EditActionNurseryScreen> {
SizedBox(
height: 8.0,
),
WidgetMediaHelper()
WidgetMediaHelper(onChangeFiles: (filePaths) {
Get.find<ChangeFileController>()
.addAllFile(filePaths);
// setState(() {
// filePaths = filePaths;
// });
})
],
),
))))));
@@ -557,3 +571,27 @@ class ChangeSupply extends GetxController {
update();
}
}

class ChangeFileController extends GetxController {
List<String> files;
void initValue() {
files = [];
update();
}

void addAllFile(List<String> filePaths) {
files = [];
files = filePaths;
update();
}

void addFile(String filePath) {
files.add(filePath);
update();
}

void deleteFile(String filePath) {
files.remove(filePath);
update();
}
}

Loading…
Cancel
Save