Browse Source

show plot detail

master
daivph 5 years ago
parent
commit
ba93672b77
13 changed files with 322 additions and 51 deletions
  1. +6
    -0
      lib/data/api/rest_client.dart
  2. +20
    -0
      lib/data/api/rest_client.g.dart
  3. +5
    -0
      lib/data/repository/repository.dart
  4. +1
    -1
      lib/models/Crop.g.dart
  5. +1
    -1
      lib/models/HistoryAction.g.dart
  6. +2
    -1
      lib/presentation/screens/plot/sc_plot.dart
  7. +68
    -0
      lib/presentation/screens/plot_detail/bloc/plot_detail_bloc.dart
  8. +18
    -0
      lib/presentation/screens/plot_detail/bloc/plot_detail_event.dart
  9. +35
    -0
      lib/presentation/screens/plot_detail/bloc/plot_detail_state.dart
  10. +109
    -6
      lib/presentation/screens/plot_detail/sc_plot_action.dart
  11. +8
    -1
      lib/presentation/screens/plot_detail/sc_plot_detail.dart
  12. +46
    -39
      pubspec.lock
  13. +3
    -2
      pubspec.yaml

+ 6
- 0
lib/data/api/rest_client.dart View File

{@Path() int page = 0, @Path() int size = 20, @Path() String query = ""}); {@Path() int page = 0, @Path() int size = 20, @Path() String query = ""});
@GET("/api/listActivityTypesOther") @GET("/api/listActivityTypesOther")
Future<List<ActionType>> getActionTypes(); Future<List<ActionType>> getActionTypes();

//Crop
@GET(
"/api/tb-crops-detail/{cropId}?page={page}&size={size}&sort=executeDate,DESC")
Future<Crop> getCropDetail(@Path() int cropId,
{@Path() int page = 0, @Path() int size = 20});
} }

+ 20
- 0
lib/data/api/rest_client.g.dart View File

.toList(); .toList();
return value; return value;
} }

@override
getCropDetail(cropId, {page = 0, size = 20}) async {
ArgumentError.checkNotNull(cropId, 'cropId');
const _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
queryParameters.removeWhere((k, v) => v == null);
final _data = <String, dynamic>{};
final Response<Map<String, dynamic>> _result = await _dio.request(
'/api/tb-crops-detail/$cropId?page=$page&size=$size&sort=executeDate,DESC',
queryParameters: queryParameters,
options: RequestOptions(
method: 'GET',
headers: <String, dynamic>{},
extra: _extra,
baseUrl: baseUrl),
data: _data);
final value = Crop.fromJson(_result.data);
return value;
}
} }

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

return client.getActionTypes(); return client.getActionTypes();
} }


Future<Crop> getPlotDetail(int cropId, {int page, int size}) {
final client = RestClient(dio);
return client.getCropDetail(cropId, page: page, size: size);
}

Future<List<Plot>> getPlots({int page, int size, String searchString}) { Future<List<Plot>> getPlots({int page, int size, String searchString}) {
final client = RestClient(dio); final client = RestClient(dio);
return client.getPlots(page: page, size: size, query: searchString); return client.getPlots(page: page, size: size, query: searchString);

+ 1
- 1
lib/models/Crop.g.dart View File

'seedIncubationTime': instance.seedIncubationTime, 'seedIncubationTime': instance.seedIncubationTime,
'numberPlants': instance.numberPlants, 'numberPlants': instance.numberPlants,
'numberCurrentPlants': instance.numberCurrentPlants, 'numberCurrentPlants': instance.numberCurrentPlants,
'endOfFarmingDate': instance.endOfFarmingDate
'endOfFarmingDate': instance.endOfFarmingDate,
}; };

+ 1
- 1
lib/models/HistoryAction.g.dart View File

'executeDate': instance.executeDate, 'executeDate': instance.executeDate,
'description': instance.description, 'description': instance.description,
'activityTypeId': instance.activityTypeId, 'activityTypeId': instance.activityTypeId,
'activityTypeName': instance.activityTypeName
'activityTypeName': instance.activityTypeName,
}; };

+ 2
- 1
lib/presentation/screens/plot/sc_plot.dart View File

Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (BuildContext context) => PlotDetailScreen()));
builder: (BuildContext context) =>
PlotDetailScreen(cropId: item.id)));
}); });
} }
} }

+ 68
- 0
lib/presentation/screens/plot_detail/bloc/plot_detail_bloc.dart View File

import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/data/api/app_exception.dart';
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:meta/meta.dart';

part 'plot_detail_event.dart';
part 'plot_detail_state.dart';

class PlotDetailBloc extends Bloc<PlotDetailEvent, PlotDetailState> {
final Repository repository;
PlotDetailBloc({@required this.repository}) : super(PlotDetailInitial());
static int pageSize = 20;

@override
Stream<PlotDetailState> mapEventToState(
PlotDetailEvent event,
) async* {
if (event is DataFetched &&
!(state is PlotDetailSuccess &&
(state as PlotDetailSuccess).hasReachedMax)) {
try {
if (state is PlotDetailInitial) {
yield PlotDetailLoading();
final response = await repository.getPlotDetail(event.cropId,
page: 0, size: pageSize);
yield PlotDetailSuccess(
items: response.activities,
page: 0,
hasReachedMax:
response.activities.length < pageSize ? true : false);
}
if (state is PlotDetailSuccess) {
final currentState = state as PlotDetailSuccess;
int page = currentState.page + 1;
yield PlotDetailLoading();
final response = await repository.getPlotDetail(event.cropId,
page: page, size: pageSize);
yield response.activities.isEmpty
? currentState.copyWith(hasReachedMax: true)
: PlotDetailSuccess(
items: currentState.items + response.activities,
page: currentState.page + 1,
hasReachedMax: false);
}
} catch (e) {
var errorString = AppException.handleError(e);
yield PlotDetailFailure(errorString: errorString);
}
}
if (event is OnRefresh) {
try {
yield PlotDetailLoading();
final response = await repository.getPlotDetail(event.cropId,
page: 0, size: pageSize);
yield PlotDetailSuccess(
items: response.activities,
page: 0,
hasReachedMax:
response.activities.length < pageSize ? true : false);
} catch (e) {
yield PlotDetailFailure(errorString: AppException.handleError(e));
}
}
}
}

+ 18
- 0
lib/presentation/screens/plot_detail/bloc/plot_detail_event.dart View File

part of 'plot_detail_bloc.dart';

abstract class PlotDetailEvent extends Equatable {
const PlotDetailEvent();

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

class DataFetched extends PlotDetailEvent {
final int cropId;
DataFetched(this.cropId);
}

class OnRefresh extends PlotDetailEvent {
final int cropId;
OnRefresh(this.cropId);
}

+ 35
- 0
lib/presentation/screens/plot_detail/bloc/plot_detail_state.dart View File

part of 'plot_detail_bloc.dart';

abstract class PlotDetailState extends Equatable {
const PlotDetailState();

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

class PlotDetailInitial extends PlotDetailState {}

class PlotDetailLoading extends PlotDetailState {}

class PlotDetailFailure extends PlotDetailState {
final String errorString;
PlotDetailFailure({@required this.errorString});
}

class PlotDetailSuccess<T> extends PlotDetailState {
final List<T> items;
final int page;
final bool hasReachedMax;

const PlotDetailSuccess({this.items, this.page, this.hasReachedMax});

PlotDetailSuccess copyWith({List<T> items, int page, bool hasReachedMax}) {
return PlotDetailSuccess(
items: items ?? this.items,
page: page ?? this.page,
hasReachedMax: hasReachedMax ?? this.hasReachedMax);
}

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

+ 109
- 6
lib/presentation/screens/plot_detail/sc_plot_action.dart View File

import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/models/index.dart';
import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.dart';
import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
import 'package:farm_tpf/presentation/screens/actions/other/sc_edit_action_other.dart'; import 'package:farm_tpf/presentation/screens/actions/other/sc_edit_action_other.dart';
import 'package:farm_tpf/presentation/screens/plot/sc_plot.dart'; import 'package:farm_tpf/presentation/screens/plot/sc_plot.dart';
import 'package:farm_tpf/presentation/screens/plot_detail/bloc/plot_detail_bloc.dart';
import 'package:farm_tpf/utils/const_color.dart'; import 'package:farm_tpf/utils/const_color.dart';
import 'package:farm_tpf/utils/const_string.dart'; import 'package:farm_tpf/utils/const_string.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:farm_tpf/utils/formatter.dart';


class PlotActionScreen extends StatefulWidget { class PlotActionScreen extends StatefulWidget {
final int cropId;
PlotActionScreen({@required this.cropId});
@override @override
_PlotActionScreenState createState() => _PlotActionScreenState(); _PlotActionScreenState createState() => _PlotActionScreenState();
} }
)) ))
])) ]))
], ],
body: RefreshIndicator(
backgroundColor: Colors.white,
onRefresh: () async {},
child: ListView.builder(
itemBuilder: (context, index) => ListTile(title: Text("Text $index")),
itemCount: 20,
body: BlocProvider(
create: (context) => PlotDetailBloc(repository: Repository())
..add(DataFetched(widget.cropId)),
child: HoldInfinityWidget(
cropId: widget.cropId,
), ),
), ),
); );
} }
} }


class HoldInfinityWidget extends StatelessWidget {
final int cropId;
HoldInfinityWidget({@required this.cropId});
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(key: _scaffoldKey, body: InfinityView(cropId: cropId));
}
}

class InfinityView extends StatefulWidget {
final int cropId;
InfinityView({@required this.cropId});
@override
_InfinityViewState createState() => _InfinityViewState();
}

class _InfinityViewState extends State<InfinityView> {
final _scrollController = ScrollController();
final _scrollThreshold = 250.0;
PlotDetailBloc _plotDetailBloc;

@override
void initState() {
_scrollController.addListener(() {
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.position.pixels;
if (maxScroll - currentScroll < _scrollThreshold) {
_plotDetailBloc.add(DataFetched(widget.cropId));
}
});
_plotDetailBloc = BlocProvider.of<PlotDetailBloc>(context);
super.initState();
}

@override
Widget build(BuildContext context) {
return BlocBuilder<PlotDetailBloc, PlotDetailState>(
builder: (context, state) {
if (state is PlotDetailFailure) {
return Center(child: Text(state.errorString));
}
if (state is PlotDetailSuccess) {
if (state.items.isEmpty) {
return Center(child: Text(label_list_empty));
}
return RefreshIndicator(
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return index >= state.items.length
? BottomLoader()
: ItemInfinityWidget(item: state.items[index]);
},
itemCount: state.hasReachedMax
? state.items.length
: state.items.length + 1,
controller: _scrollController,
),
onRefresh: () async {
_plotDetailBloc.add(OnRefresh(widget.cropId));
});
}
return Center(
child: LoadingListPage(),
);
},
);
}

@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
}

class ItemInfinityWidget extends StatelessWidget {
final HistoryAction item;

const ItemInfinityWidget({Key key, @required this.item}) : super(key: key);

@override
Widget build(BuildContext context) {
return GestureDetector(
child: Card(
child: ListTile(
title: Text(item.activityTypeName),
subtitle: Text(item.executeDate.format_DDMMYY_HHmm()),
),
),
onTap: () {});
}
}

class ActionType { class ActionType {
Widget addScreen; Widget addScreen;
Widget listScreen; Widget listScreen;

+ 8
- 1
lib/presentation/screens/plot_detail/sc_plot_detail.dart View File

import 'package:flutter/material.dart'; import 'package:flutter/material.dart';


class PlotDetailScreen extends StatefulWidget { class PlotDetailScreen extends StatefulWidget {
final int cropId;
PlotDetailScreen({@required this.cropId});
@override @override
_PlotDetailScreenState createState() => _PlotDetailScreenState(); _PlotDetailScreenState createState() => _PlotDetailScreenState();
} }
child: new Scaffold( child: new Scaffold(
backgroundColor: COLOR_CONST.ITEM_BG, backgroundColor: COLOR_CONST.ITEM_BG,
body: TabBarView( body: TabBarView(
children: [PlotParameterScreen(), PlotActionScreen()],
children: [
PlotParameterScreen(),
PlotActionScreen(
cropId: widget.cropId,
)
],
), ),
bottomNavigationBar: new TabBar( bottomNavigationBar: new TabBar(
tabs: [ tabs: [

+ 46
- 39
pubspec.lock View File

# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
analyzer:
_fe_analyzer_shared:
dependency: transitive dependency: transitive
description:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.0"
analyzer:
dependency: "direct main"
description: description:
name: analyzer name: analyzer
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.36.4"
version: "0.39.14"
archive: archive:
dependency: transitive dependency: transitive
description: description:
name: build name: build
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.6"
version: "1.3.0"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.1+1"
version: "0.4.2"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.1"
version: "1.3.11"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.9"
version: "1.10.0"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.1"
version: "5.2.0"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.2" version: "1.0.2"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
code_builder: code_builder:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.9"
version: "1.3.6"
dio: dio:
dependency: "direct main" dependency: "direct main"
description: description:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.0" version: "0.3.0"
front_end:
dependency: transitive
description:
name: front_end
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.19"
get: get:
dependency: "direct main" dependency: "direct main"
description: description:
name: json_annotation name: json_annotation
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.3.0"
json_model:
dependency: "direct dev"
description:
name: json_model
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.2"
version: "3.0.1"
json_serializable: json_serializable:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: json_serializable name: json_serializable
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.3.0"
kernel:
dependency: transitive
description:
name: kernel
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.19"
version: "3.4.1"
keyboard_dismisser: keyboard_dismisser:
dependency: "direct main" dependency: "direct main"
description: description:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.3" version: "0.4.3"
package_resolver:
dependency: transitive
description:
name: package_resolver
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.10"
path: path:
dependency: transitive dependency: transitive
description: description:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.3" version: "2.1.3"
retrofit:
dependency: transitive
description:
name: retrofit
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.4"
retrofit_generator:
dependency: "direct dev"
description:
name: retrofit_generator
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.7+6"
rxdart: rxdart:
dependency: "direct main" dependency: "direct main"
description: description:
name: source_gen name: source_gen
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.4+4"
version: "0.9.6"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.1+2" version: "0.1.1+2"
tuple:
dependency: transitive
description:
name: tuple
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:

+ 3
- 2
pubspec.yaml View File

get: ^3.8.0 get: ^3.8.0
intl: ^0.16.1 intl: ^0.16.1
flutter_datetime_picker: ^1.3.8 flutter_datetime_picker: ^1.3.8
analyzer: ^0.39.14


dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
#flutter packages pub run build_runner build --delete-conflicting-outputs #flutter packages pub run build_runner build --delete-conflicting-outputs
# retrofit_generator: ^1.3.7
retrofit_generator: ^1.3.7
# flutter packages pub run json_model # flutter packages pub run json_model
json_model: ^0.0.2
# json_model: ^0.0.2
build_runner: any build_runner: any
json_serializable: any json_serializable: any

Loading…
Cancel
Save