| { | { | ||||
| "id": 1578, | |||||
| "times": 20, | |||||
| "activityExecuteDate": "2020-08-20T11:53:20Z", | |||||
| "isExceedLimit": false | |||||
| "id": 1, | |||||
| "qrCode": "QRLO01", | |||||
| "code": "LO01", | |||||
| "areaM2": 1000.0, | |||||
| "type": 0, | |||||
| "startDate": "2020-08-20T02:34:18Z", | |||||
| "endDate": "2020-08-20T02:34:18Z", | |||||
| "status": "STATUS_ARE_ACTIVE", | |||||
| "description": "", | |||||
| "ageDayStartAt": 3, | |||||
| "tbSuppliesId": 1, | |||||
| "suppliesName": "Rau muống", | |||||
| "tbGuidelineId": 2, | |||||
| "netHouseId": 26, | |||||
| "netHouseName": "T01", | |||||
| "areaId": 3, | |||||
| "area": "Khu C" | |||||
| } | } |
| @JsonSerializable() | @JsonSerializable() | ||||
| class Plot { | class Plot { | ||||
| Plot(); | |||||
| Plot(); | |||||
| num id; | |||||
| num times; | |||||
| String activityExecuteDate; | |||||
| bool isExceedLimit; | |||||
| factory Plot.fromJson(Map<String, dynamic> json) => _$PlotFromJson(json); | |||||
| Map<String, dynamic> toJson() => _$PlotToJson(this); | |||||
| num id; | |||||
| String qrCode; | |||||
| String code; | |||||
| num areaM2; | |||||
| num type; | |||||
| String startDate; | |||||
| String endDate; | |||||
| String status; | |||||
| String description; | |||||
| num ageDayStartAt; | |||||
| num tbSuppliesId; | |||||
| String suppliesName; | |||||
| num tbGuidelineId; | |||||
| num netHouseId; | |||||
| String netHouseName; | |||||
| num areaId; | |||||
| String area; | |||||
| factory Plot.fromJson(Map<String,dynamic> json) => _$PlotFromJson(json); | |||||
| Map<String, dynamic> toJson() => _$PlotToJson(this); | |||||
| } | } |
| Plot _$PlotFromJson(Map<String, dynamic> json) { | Plot _$PlotFromJson(Map<String, dynamic> json) { | ||||
| return Plot() | return Plot() | ||||
| ..id = json['id'] as num | ..id = json['id'] as num | ||||
| ..times = json['times'] as num | |||||
| ..activityExecuteDate = json['activityExecuteDate'] as String | |||||
| ..isExceedLimit = json['isExceedLimit'] as bool; | |||||
| ..qrCode = json['qrCode'] as String | |||||
| ..code = json['code'] as String | |||||
| ..areaM2 = json['areaM2'] as num | |||||
| ..type = json['type'] as num | |||||
| ..startDate = json['startDate'] as String | |||||
| ..endDate = json['endDate'] as String | |||||
| ..status = json['status'] as String | |||||
| ..description = json['description'] as String | |||||
| ..ageDayStartAt = json['ageDayStartAt'] as num | |||||
| ..tbSuppliesId = json['tbSuppliesId'] as num | |||||
| ..suppliesName = json['suppliesName'] as String | |||||
| ..tbGuidelineId = json['tbGuidelineId'] as num | |||||
| ..netHouseId = json['netHouseId'] as num | |||||
| ..netHouseName = json['netHouseName'] as String | |||||
| ..areaId = json['areaId'] as num | |||||
| ..area = json['area'] as String; | |||||
| } | } | ||||
| Map<String, dynamic> _$PlotToJson(Plot instance) => <String, dynamic>{ | Map<String, dynamic> _$PlotToJson(Plot instance) => <String, dynamic>{ | ||||
| 'id': instance.id, | 'id': instance.id, | ||||
| 'times': instance.times, | |||||
| 'activityExecuteDate': instance.activityExecuteDate, | |||||
| 'isExceedLimit': instance.isExceedLimit, | |||||
| 'qrCode': instance.qrCode, | |||||
| 'code': instance.code, | |||||
| 'areaM2': instance.areaM2, | |||||
| 'type': instance.type, | |||||
| 'startDate': instance.startDate, | |||||
| 'endDate': instance.endDate, | |||||
| 'status': instance.status, | |||||
| 'description': instance.description, | |||||
| 'ageDayStartAt': instance.ageDayStartAt, | |||||
| 'tbSuppliesId': instance.tbSuppliesId, | |||||
| 'suppliesName': instance.suppliesName, | |||||
| 'tbGuidelineId': instance.tbGuidelineId, | |||||
| 'netHouseId': instance.netHouseId, | |||||
| 'netHouseName': instance.netHouseName, | |||||
| 'areaId': instance.areaId, | |||||
| 'area': instance.area | |||||
| }; | }; |
| export 'Plot.dart'; | |||||
| export 'ResourceHelper.dart'; | |||||
| export 'Supply.dart' ; | |||||
| export 'Plot.dart' ; | |||||
| export 'ResourceHelper.dart' ; |
| import 'package:farm_tpf/models/Plot.dart'; | import 'package:farm_tpf/models/Plot.dart'; | ||||
| import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.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/custom_widgets/loading_list_page.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/plot/widget_search.dart'; | |||||
| import 'package:farm_tpf/utils/const_color.dart'; | |||||
| import 'package:farm_tpf/utils/const_enum.dart'; | |||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||
| import 'package:farm_tpf/utils/const_string.dart'; | import 'package:farm_tpf/utils/const_string.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:farm_tpf/utils/formatter.dart'; | |||||
| import 'bloc/plot_bloc.dart'; | import 'bloc/plot_bloc.dart'; | ||||
| if (state.items.isEmpty) { | if (state.items.isEmpty) { | ||||
| return Center(child: Text(label_list_empty)); | return Center(child: Text(label_list_empty)); | ||||
| } | } | ||||
| return RefreshIndicator( | |||||
| child: ListView.builder( | |||||
| 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 { | |||||
| _plotBloc.add(OnRefresh()); | |||||
| }); | |||||
| return Column( | |||||
| children: <Widget>[ | |||||
| WidgetSearch(), | |||||
| Expanded( | |||||
| child: RefreshIndicator( | |||||
| child: ListView.builder( | |||||
| 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 { | |||||
| _plotBloc.add(OnRefresh()); | |||||
| })) | |||||
| ], | |||||
| ); | |||||
| } | } | ||||
| return Center( | return Center( | ||||
| child: LoadingListPage(), | child: LoadingListPage(), | ||||
| Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||||
| return GestureDetector( | return GestureDetector( | ||||
| child: Card( | child: Card( | ||||
| color: item.id % 3 == 0 ? Colors.white : Colors.greenAccent[100], | |||||
| child: Container( | |||||
| padding: EdgeInsets.all(8.0), | |||||
| child: Column( | |||||
| crossAxisAlignment: CrossAxisAlignment.start, | |||||
| children: <Widget>[ | |||||
| Text("Ngày giờ: " + item.activityExecuteDate.toString()), | |||||
| SizedBox( | |||||
| height: 8.0, | |||||
| ), | |||||
| Text("Thời gian: " + item.id.toString() + " giây"), | |||||
| ], | |||||
| color: item.status == "STATUS_ARE_ACTIVE" | |||||
| ? Colors.white | |||||
| : COLOR_CONST.DEFAULT, | |||||
| child: ListTile( | |||||
| title: Text( | |||||
| item.code.toString() + " - " + item.suppliesName.toString(), | |||||
| style: TextStyle( | |||||
| color: item.status == "STATUS_ARE_ACTIVE" | |||||
| ? COLOR_CONST.DEFAULT | |||||
| : Colors.white), | |||||
| ), | ), | ||||
| subtitle: Text(item.startDate.format_DDMMYY_HHmm().toString(), | |||||
| style: TextStyle( | |||||
| color: item.status == "STATUS_ARE_ACTIVE" | |||||
| ? COLOR_CONST.DEFAULT | |||||
| : Colors.white)), | |||||
| trailing: Text( | |||||
| item.areaM2.formatNumtoStringDecimal().toString() + " m\u00B2", | |||||
| style: TextStyle( | |||||
| color: item.status == "STATUS_ARE_ACTIVE" | |||||
| ? COLOR_CONST.DEFAULT | |||||
| : Colors.white)), | |||||
| ), | ), | ||||
| ), | ), | ||||
| onTap: () {}); | onTap: () {}); |
| import 'package:farm_tpf/utils/const_color.dart'; | |||||
| import 'package:flutter/material.dart'; | |||||
| class WidgetSearch extends StatefulWidget { | |||||
| @override | |||||
| _WidgetSearchState createState() => _WidgetSearchState(); | |||||
| } | |||||
| class _WidgetSearchState extends State<WidgetSearch> { | |||||
| BuildContext _blocContext; | |||||
| TextEditingController _searchController = TextEditingController(); | |||||
| @override | |||||
| void initState() { | |||||
| super.initState(); | |||||
| _searchController.addListener(() { | |||||
| final keyword = _searchController.text; | |||||
| if (keyword.isNotEmpty) { | |||||
| //search when text change | |||||
| } | |||||
| }); | |||||
| } | |||||
| Widget getSearchBarUI() { | |||||
| _searchController.text = ""; | |||||
| return Padding( | |||||
| padding: const EdgeInsets.only(left: 8, right: 8, top: 4, bottom: 0), | |||||
| child: Row( | |||||
| children: <Widget>[ | |||||
| Expanded( | |||||
| child: Padding( | |||||
| padding: const EdgeInsets.only(right: 8, top: 8, bottom: 0), | |||||
| child: Container( | |||||
| decoration: BoxDecoration( | |||||
| color: Colors.white, | |||||
| borderRadius: const BorderRadius.all( | |||||
| Radius.circular(38.0), | |||||
| ), | |||||
| boxShadow: <BoxShadow>[ | |||||
| BoxShadow( | |||||
| color: Colors.grey.withOpacity(0.2), | |||||
| offset: const Offset(0, 2), | |||||
| blurRadius: 8.0), | |||||
| ], | |||||
| ), | |||||
| child: Padding( | |||||
| padding: const EdgeInsets.only( | |||||
| left: 16, right: 16, top: 4, bottom: 4), | |||||
| child: TextField( | |||||
| textInputAction: TextInputAction.done, | |||||
| controller: _searchController, | |||||
| onChanged: (String txt) {}, | |||||
| cursorColor: COLOR_CONST.GRAY1, | |||||
| decoration: InputDecoration( | |||||
| border: InputBorder.none, | |||||
| hintText: 'Tìm kiếm ...', | |||||
| ), | |||||
| onSubmitted: (value) { | |||||
| FocusScope.of(context).requestFocus(FocusNode()); | |||||
| }, | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| ); | |||||
| } | |||||
| @override | |||||
| Widget build(BuildContext context) { | |||||
| _blocContext = context; | |||||
| return Container(child: getSearchBarUI()); | |||||
| } | |||||
| @override | |||||
| void dispose() { | |||||
| _searchController.dispose(); | |||||
| super.dispose(); | |||||
| } | |||||
| } |
| import 'package:farm_tpf/presentation/screens/control_device/sc_control_device.dart'; | import 'package:farm_tpf/presentation/screens/control_device/sc_control_device.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/home/home.dart'; | import 'package:farm_tpf/presentation/screens/home/home.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/plot/sc_plot.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/profile/sc_update_profile.dart'; | import 'package:farm_tpf/presentation/screens/profile/sc_update_profile.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/scan_barcode/sc_scan_barcode.dart'; | import 'package:farm_tpf/presentation/screens/scan_barcode/sc_scan_barcode.dart'; | ||||
| import 'package:farm_tpf/utils/const_color.dart'; | import 'package:farm_tpf/utils/const_color.dart'; | ||||
| drawerIndex = drawerIndexdata; | drawerIndex = drawerIndexdata; | ||||
| if (drawerIndex == DrawerIndex.Home) { | if (drawerIndex == DrawerIndex.Home) { | ||||
| setState(() { | setState(() { | ||||
| screenView = HomePage(); | |||||
| screenView = PlotListScreen(); | |||||
| }); | }); | ||||
| } else if (drawerIndex == DrawerIndex.ControlDevice) { | } else if (drawerIndex == DrawerIndex.ControlDevice) { | ||||
| setState(() { | setState(() { |
| import 'package:intl/intl.dart'; | import 'package:intl/intl.dart'; | ||||
| extension ddMM_HHmm on String { | |||||
| //"2020-08-13T02:11:32Z" => 13/08 02:11 | |||||
| // convert utc to local timezone | |||||
| String format_DDMM_HHmm() { | |||||
| try { | |||||
| final str = this.toString(); | |||||
| var dateFromString = | |||||
| DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(str, true).toLocal(); | |||||
| return DateFormat("dd/MM HH:mm").format(dateFromString); | |||||
| } catch (_) { | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| String format_DDMMYY_HHmm() { | |||||
| try { | |||||
| final str = this.toString(); | |||||
| var dateFromString = | |||||
| DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(str, true).toLocal(); | |||||
| return DateFormat("dd/MM/yyyy HH:mm").format(dateFromString); | |||||
| } catch (_) { | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| } | |||||
| extension numToString on num { | |||||
| String formatNumtoStringDecimal() { | |||||
| try { | |||||
| var numWithLocalSeparator = new NumberFormat.decimalPattern("vi_VN"); | |||||
| final str = numWithLocalSeparator.format(this); | |||||
| return str; | |||||
| } catch (_) { | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| } | |||||
| extension HHmm on Duration { | extension HHmm on Duration { | ||||
| String formatHHmm() { | String formatHHmm() { | ||||
| //1:34:00.000000 | //1:34:00.000000 | ||||
| extension FormatNumber on int { | extension FormatNumber on int { | ||||
| String formatDecimalThousand() { | String formatDecimalThousand() { | ||||
| //1403 -> 1,403 | //1403 -> 1,403 | ||||
| var f = new NumberFormat.decimalPattern("en_US"); | |||||
| var f = new NumberFormat.decimalPattern("vi_VN"); | |||||
| return f.format(this); | |||||
| } | |||||
| } | |||||
| extension FormatNumberToDecimal on double { | |||||
| String formatDecimalThousand() { | |||||
| var f = new NumberFormat.decimalPattern("vi_VN"); | |||||
| return f.format(this); | return f.format(this); | ||||
| } | } | ||||
| } | } | ||||
| extension DoubleParsing on String { | extension DoubleParsing on String { | ||||
| double parseDoubleThousand() { | double parseDoubleThousand() { | ||||
| var newValue = this.replaceAll(",", ""); | |||||
| //TODO: CHECK again | |||||
| if (newValue.endsWith(".0")) { | |||||
| newValue = newValue.substring(0, newValue.length - 2); | |||||
| } | |||||
| return double.tryParse(newValue); | |||||
| var newValue = this.replaceAll(".", ""); | |||||
| var changeToServerFormat = newValue.replaceAll(",", "."); | |||||
| return double.tryParse(changeToServerFormat); | |||||
| } | } | ||||
| } | } | ||||
| extension IntParsing on String { | extension IntParsing on String { | ||||
| int parseIntThousand() { | int parseIntThousand() { | ||||
| var newValue = this.replaceAll(",", ""); | |||||
| if (newValue.endsWith(".0")) { | |||||
| newValue = newValue.substring(0, newValue.length - 2); | |||||
| } | |||||
| return int.tryParse(newValue); | |||||
| var newValue = this.replaceAll(".", ""); | |||||
| var changeToServerFormat = newValue.replaceAll(",", "."); | |||||
| return int.tryParse(changeToServerFormat); | |||||
| } | } | ||||
| } | } |
| name: json_serializable | name: json_serializable | ||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "3.4.0" | |||||
| version: "3.4.1" | |||||
| keyboard_dismisser: | keyboard_dismisser: | ||||
| dependency: "direct main" | dependency: "direct main" | ||||
| description: | description: | ||||
| name: retrofit_generator | name: retrofit_generator | ||||
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "1.3.7+5" | |||||
| version: "1.3.7+6" | |||||
| rxdart: | rxdart: | ||||
| dependency: "direct main" | dependency: "direct main" | ||||
| description: | description: |