| @@ -376,7 +376,7 @@ | |||
| CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; | |||
| CODE_SIGN_IDENTITY = "Apple Development"; | |||
| CODE_SIGN_STYLE = Automatic; | |||
| CURRENT_PROJECT_VERSION = 36; | |||
| CURRENT_PROJECT_VERSION = 37; | |||
| DEVELOPMENT_TEAM = C3DTD2JH94; | |||
| ENABLE_BITCODE = NO; | |||
| FRAMEWORK_SEARCH_PATHS = ( | |||
| @@ -393,7 +393,7 @@ | |||
| "$(inherited)", | |||
| "$(PROJECT_DIR)/Flutter", | |||
| ); | |||
| MARKETING_VERSION = 1.1.16; | |||
| MARKETING_VERSION = 1.1.17; | |||
| PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo; | |||
| PRODUCT_NAME = "$(TARGET_NAME)"; | |||
| PROVISIONING_PROFILE_SPECIFIER = ""; | |||
| @@ -522,7 +522,7 @@ | |||
| CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; | |||
| CODE_SIGN_IDENTITY = "Apple Development"; | |||
| CODE_SIGN_STYLE = Automatic; | |||
| CURRENT_PROJECT_VERSION = 36; | |||
| CURRENT_PROJECT_VERSION = 37; | |||
| DEVELOPMENT_TEAM = C3DTD2JH94; | |||
| ENABLE_BITCODE = NO; | |||
| FRAMEWORK_SEARCH_PATHS = ( | |||
| @@ -539,7 +539,7 @@ | |||
| "$(inherited)", | |||
| "$(PROJECT_DIR)/Flutter", | |||
| ); | |||
| MARKETING_VERSION = 1.1.16; | |||
| MARKETING_VERSION = 1.1.17; | |||
| PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo; | |||
| PRODUCT_NAME = "$(TARGET_NAME)"; | |||
| PROVISIONING_PROFILE_SPECIFIER = ""; | |||
| @@ -560,7 +560,7 @@ | |||
| CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; | |||
| CODE_SIGN_IDENTITY = "Apple Development"; | |||
| CODE_SIGN_STYLE = Automatic; | |||
| CURRENT_PROJECT_VERSION = 36; | |||
| CURRENT_PROJECT_VERSION = 37; | |||
| DEVELOPMENT_TEAM = C3DTD2JH94; | |||
| ENABLE_BITCODE = NO; | |||
| FRAMEWORK_SEARCH_PATHS = ( | |||
| @@ -577,7 +577,7 @@ | |||
| "$(inherited)", | |||
| "$(PROJECT_DIR)/Flutter", | |||
| ); | |||
| MARKETING_VERSION = 1.1.16; | |||
| MARKETING_VERSION = 1.1.17; | |||
| PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo; | |||
| PRODUCT_NAME = "$(TARGET_NAME)"; | |||
| PROVISIONING_PROFILE_SPECIFIER = ""; | |||
| @@ -10,6 +10,8 @@ class CropPlot { | |||
| int? numberPlants; | |||
| int? numberCurrentPlants; | |||
| String? endOfFarmingDate; | |||
| int? numberRemovals; | |||
| List<ObjectParameterDataDTOS>? objectParameterDataDTOS; | |||
| CropPlot({ | |||
| this.tbCropDTO, | |||
| @@ -21,16 +23,26 @@ class CropPlot { | |||
| this.numberPlants, | |||
| this.numberCurrentPlants, | |||
| this.endOfFarmingDate, | |||
| this.numberRemovals, | |||
| this.objectParameterDataDTOS, | |||
| }); | |||
| CropPlot.fromJson(Map<String, dynamic> json) { | |||
| tbCropDTO = json['tbCropDTO'] != null ? new TbCropDTO.fromJson(json['tbCropDTO']) : null; | |||
| tbCropDTO = json['tbCropDTO'] != null | |||
| ? new TbCropDTO.fromJson(json['tbCropDTO']) | |||
| : null; | |||
| if (json['activities'] != null) { | |||
| activities = <Activities>[]; | |||
| json['activities'].forEach((v) { | |||
| activities?.add(new Activities.fromJson(v)); | |||
| }); | |||
| } | |||
| if (json['objectParameterDataDTOS'] != null) { | |||
| objectParameterDataDTOS = <ObjectParameterDataDTOS>[]; | |||
| json['objectParameterDataDTOS'].forEach((v) { | |||
| objectParameterDataDTOS?.add(new ObjectParameterDataDTOS.fromJson(v)); | |||
| }); | |||
| } | |||
| sowingDate = json['sowingDate']; | |||
| plantingDate = json['plantingDate']; | |||
| soakSeedsTime = json['soakSeedsTime']; | |||
| @@ -38,6 +50,7 @@ class CropPlot { | |||
| numberPlants = json['numberPlants']; | |||
| numberCurrentPlants = json['numberCurrentPlants']; | |||
| endOfFarmingDate = json['endOfFarmingDate']; | |||
| numberRemovals = json['numberRemovals']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| @@ -48,12 +61,36 @@ class CropPlot { | |||
| if (this.activities != null) { | |||
| data['activities'] = this.activities?.map((v) => v.toJson()).toList(); | |||
| } | |||
| if (this.objectParameterDataDTOS != null) { | |||
| data['objectParameterDataDTOS'] = | |||
| this.objectParameterDataDTOS?.map((v) => v.toJson()).toList(); | |||
| } | |||
| data['sowingDate'] = this.sowingDate; | |||
| data['soakSeedsTime'] = this.soakSeedsTime; | |||
| data['seedIncubationTime'] = this.seedIncubationTime; | |||
| data['numberPlants'] = this.numberPlants; | |||
| data['numberCurrentPlants'] = this.numberCurrentPlants; | |||
| data['endOfFarmingDate'] = this.endOfFarmingDate; | |||
| data['numberRemovals'] = this.numberRemovals; | |||
| return data; | |||
| } | |||
| } | |||
| class ObjectParameterDataDTOS { | |||
| String? name; | |||
| String? index; | |||
| ObjectParameterDataDTOS({this.name, this.index}); | |||
| ObjectParameterDataDTOS.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; | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| class ErrorCommon { | |||
| String? entityName; | |||
| String? errorKey; | |||
| int? status; | |||
| dynamic status; | |||
| ErrorCommon({ | |||
| this.entityName, | |||
| @@ -1,13 +1,19 @@ | |||
| import 'package:farm_tpf/custom_model/action_form/ActivityTypeDTO.dart'; | |||
| import 'ActionUIField.dart'; | |||
| import 'ActionUISupply.dart'; | |||
| class ActionUIForm { | |||
| ActivityTypeDTO? tbActivityTypeDTO; | |||
| List<ActionUIField>? objectParameterDTOList; | |||
| List<ActionUISupply>? activityExtendTypeDTOList; | |||
| ActionUIForm({this.objectParameterDTOList, this.activityExtendTypeDTOList}); | |||
| ActionUIForm.fromJson(Map<String, dynamic> json) { | |||
| if (json['tbActivityTypeDTO'] != null) { | |||
| tbActivityTypeDTO = new ActivityTypeDTO.fromJson(json['tbActivityTypeDTO']); | |||
| } | |||
| if (json['objectParameterDTOList'] != null) { | |||
| objectParameterDTOList = <ActionUIField>[]; | |||
| json['objectParameterDTOList'].forEach((v) { | |||
| @@ -24,6 +30,9 @@ class ActionUIForm { | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| if (this.tbActivityTypeDTO != null) { | |||
| data['tbActivityTypeDTO'] = this.tbActivityTypeDTO!.toJson(); | |||
| } | |||
| if (this.objectParameterDTOList != null) { | |||
| data['objectParameterDTOList'] = this.objectParameterDTOList?.map((v) => v.toJson()).toList(); | |||
| } | |||
| @@ -0,0 +1,72 @@ | |||
| class ActivityTypeDTO { | |||
| int? id; | |||
| String? name; | |||
| String? description; | |||
| bool? isCanDelete; | |||
| bool? isGuidelineUsing; | |||
| bool? isTriggerEvent; | |||
| int? position; | |||
| bool? isStart; | |||
| bool? isEnd; | |||
| String? supplyGroup; | |||
| String? guideType; | |||
| bool? isUseSupply; | |||
| String? urlSupply; | |||
| bool? isTraceability; | |||
| bool? afterHarvest; | |||
| ActivityTypeDTO( | |||
| {this.id, | |||
| this.name, | |||
| this.description, | |||
| this.isCanDelete, | |||
| this.isGuidelineUsing, | |||
| this.isTriggerEvent, | |||
| this.position, | |||
| this.isStart, | |||
| this.isEnd, | |||
| this.supplyGroup, | |||
| this.guideType, | |||
| this.isUseSupply, | |||
| this.urlSupply, | |||
| this.isTraceability, | |||
| this.afterHarvest}); | |||
| ActivityTypeDTO.fromJson(Map<String, dynamic> json) { | |||
| id = json['id']; | |||
| name = json['name']; | |||
| description = json['description']; | |||
| isCanDelete = json['isCanDelete']; | |||
| isGuidelineUsing = json['isGuidelineUsing']; | |||
| isTriggerEvent = json['isTriggerEvent']; | |||
| position = json['position']; | |||
| isStart = json['isStart']; | |||
| isEnd = json['isEnd']; | |||
| supplyGroup = json['supplyGroup']; | |||
| guideType = json['guideType']; | |||
| isUseSupply = json['isUseSupply']; | |||
| urlSupply = json['urlSupply']; | |||
| isTraceability = json['isTraceability']; | |||
| afterHarvest = json['afterHarvest']; | |||
| } | |||
| Map<String, dynamic> toJson() { | |||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
| data['id'] = this.id; | |||
| data['name'] = this.name; | |||
| data['description'] = this.description; | |||
| data['isCanDelete'] = this.isCanDelete; | |||
| data['isGuidelineUsing'] = this.isGuidelineUsing; | |||
| data['isTriggerEvent'] = this.isTriggerEvent; | |||
| data['position'] = this.position; | |||
| data['isStart'] = this.isStart; | |||
| data['isEnd'] = this.isEnd; | |||
| data['supplyGroup'] = this.supplyGroup; | |||
| data['guideType'] = this.guideType; | |||
| data['isUseSupply'] = this.isUseSupply; | |||
| data['urlSupply'] = this.urlSupply; | |||
| data['isTraceability'] = this.isTraceability; | |||
| data['afterHarvest'] = this.afterHarvest; | |||
| return data; | |||
| } | |||
| } | |||
| @@ -16,10 +16,22 @@ class AppException { | |||
| if (statusCode == 400) { | |||
| errorDescription = customMessageError ?? exception_dio_400; | |||
| try { | |||
| Map<String, dynamic> errorMap = jsonDecode(dioError.response?.data); | |||
| final rawData = dioError.response?.data; | |||
| Map<String, dynamic> errorMap; | |||
| if (rawData is String) { | |||
| errorMap = json.decode(rawData); | |||
| } else if (rawData is Map) { | |||
| errorMap = Map<String, dynamic>.from(rawData); | |||
| } else { | |||
| throw Exception("Unsupported error format"); | |||
| } | |||
| var errorCode = ErrorCommon.fromJson(errorMap).errorKey; | |||
| switch (errorCode) { | |||
| case '-1': | |||
| errorDescription = exception_dio_minus_1; | |||
| break; | |||
| case '1000': | |||
| errorDescription = exception_dio_1000; | |||
| break; | |||
| @@ -86,6 +98,9 @@ class AppException { | |||
| case '1021': | |||
| errorDescription = exception_dio_1021; | |||
| break; | |||
| case '9999': | |||
| errorDescription = exception_dio_9999; | |||
| break; | |||
| default: | |||
| errorDescription = customMessageError ?? exception_dio_400; | |||
| } | |||
| @@ -92,7 +92,7 @@ abstract class RestClient { | |||
| {@Path() int page = 0, @Path() int size = 20, @Path() String query = '', @DioOptions() Options? options}); | |||
| //Crop | |||
| @GET("/api/tb-crops-detail-for-app/{cropId}") | |||
| @GET("/api/v2/tb-crops-detail-for-app/{cropId}") | |||
| Future<CropPlot> getCropDetail(@Path() int cropId, {@Path() int page = 0, @Path() int size = 20}); | |||
| @GET("/api/tb-crops-scan-qrCode/{cropCode}") | |||
| @@ -107,9 +107,9 @@ abstract class RestClient { | |||
| @GET("/api/list-environment-updates-display/{cropId}?page={page}&size={size}") | |||
| Future<List<EnvironmentParameter>> getEnvironmentParameters(@Path() int cropId, {@Path() int page = 0, @Path() int size = 20}); | |||
| //NEW Activity implement | |||
| @GET('/api/display-object-param-dynamic-form/{idAction}') | |||
| @GET('/api/v2/display-object-param-dynamic-form/{idAction}') | |||
| Future<ActionUIForm> getActionUIForm(@Path() idAction, @DioOptions() Options? options); | |||
| @GET('/api/get-detail-common-activity/{actionType}/{activityId}') | |||
| Future<RequestActivity> getDetailActivityCommon(@Path() actionType, @Path() activityId); | |||
| @GET('/api/v2/get-detail-common-activity/{activityId}') | |||
| Future<RequestActivity> getDetailActivityCommon(@Path() activityId); | |||
| } | |||
| @@ -337,7 +337,7 @@ class _RestClient implements RestClient { | |||
| queryParameters.removeWhere((k, v) => v == null); | |||
| final _data = <String, dynamic>{}; | |||
| var _result = await _dio.request( | |||
| '/api/tb-crops-detail-for-app/$cropId', | |||
| '/api/v2/tb-crops-detail-for-app/$cropId', | |||
| queryParameters: queryParameters, | |||
| data: _data, | |||
| ); | |||
| @@ -440,20 +440,19 @@ class _RestClient implements RestClient { | |||
| newOptions.extra.addAll(_extra); | |||
| newOptions.headers.addAll(<String, dynamic>{}); | |||
| final _result = | |||
| await _dio.request<Map<String, dynamic>>('/api/display-object-param-dynamic-form/$idAction', queryParameters: queryParameters, data: _data); | |||
| await _dio.request<Map<String, dynamic>>('/api/v2/display-object-param-dynamic-form/$idAction', queryParameters: queryParameters, data: _data); | |||
| final value = ActionUIForm.fromJson(_result.data ?? Map<String, dynamic>()); | |||
| return value; | |||
| } | |||
| @override | |||
| getDetailActivityCommon(actionType, activityId) async { | |||
| ArgumentError.checkNotNull(actionType, 'actionType'); | |||
| getDetailActivityCommon(activityId) async { | |||
| ArgumentError.checkNotNull(activityId, 'activityId'); | |||
| const _extra = <String, dynamic>{}; | |||
| final queryParameters = <String, dynamic>{}; | |||
| queryParameters.removeWhere((k, v) => v == null); | |||
| final _data = <String, dynamic>{}; | |||
| final _result = await _dio.request<Map<String, dynamic>>('/api/get-detail-common-activity/$actionType/$activityId', | |||
| final _result = await _dio.request<Map<String, dynamic>>('/api/v2/get-detail-common-activity/$activityId', | |||
| queryParameters: queryParameters, data: _data); | |||
| final value = RequestActivity.fromJson(_result.data ?? Map<String, dynamic>()); | |||
| return value; | |||
| @@ -125,10 +125,19 @@ class Repository { | |||
| return value; | |||
| } | |||
| Future<List<Supply>> getSupplies(String type, {String query = ""}) async { | |||
| final client = RestClient(dio); | |||
| Future<List<Supply>> getSupplies(String urlSupply, {String query = ""}) async { | |||
| var op = buildConfigurableCacheOptions(forceRefresh: true, maxAge: Duration(days: ConstCommon.kMaxAgeCache)); | |||
| return client.getSupplies(type, query: query, options: op); | |||
| try { | |||
| final result = await dio.get("${ConstCommon.baseUrl}$urlSupply?q=$query", options: op); | |||
| final data = result.data; | |||
| if (data is List) { | |||
| return data.map((i) => Supply.fromJson(i as Map<String, dynamic>)).toList(); | |||
| } else { | |||
| return []; | |||
| } | |||
| } on DioError catch (e) { | |||
| return []; | |||
| } | |||
| } | |||
| Future<List<Device>> getDeviceForActivity() async { | |||
| @@ -260,7 +269,7 @@ class Repository { | |||
| } | |||
| Future<void> createActionCommon(Function(dynamic) onSuccess, Function(dynamic) onError, | |||
| {required String activityType, required String activityData, List<String>? filePaths}) async { | |||
| {required String activityData, List<String>? filePaths}) async { | |||
| var formData = FormData(); | |||
| if (filePaths != null) { | |||
| filePaths.forEach((f) { | |||
| @@ -270,7 +279,7 @@ class Repository { | |||
| formData.fields.add(MapEntry('tbCommonActivityDTO', activityData)); | |||
| try { | |||
| await dio.post("${ConstCommon.baseUrl}/api/create-common-activity/$activityType", data: formData).then((value) { | |||
| await dio.post("${ConstCommon.baseUrl}/api/create-common-activity", data: formData).then((value) { | |||
| onSuccess(value.data); | |||
| }); | |||
| } on DioError catch (e) { | |||
| @@ -279,7 +288,7 @@ class Repository { | |||
| } | |||
| Future<void> updateActionCommon(Function(dynamic) onSuccess, Function(dynamic) onError, | |||
| {required String activityType, required String activityData, List<String>? filePaths}) async { | |||
| {required String activityData, List<String>? filePaths}) async { | |||
| var formData = FormData(); | |||
| if (filePaths != null) { | |||
| filePaths.forEach((f) { | |||
| @@ -289,7 +298,7 @@ class Repository { | |||
| formData.fields.add(MapEntry('tbCommonActivityDTO', activityData)); | |||
| try { | |||
| await dio.post("${ConstCommon.baseUrl}/api/update-common-activity/$activityType", data: formData).then((value) { | |||
| await dio.post("${ConstCommon.baseUrl}/api/update-common-activity", data: formData).then((value) { | |||
| onSuccess(value.data); | |||
| }); | |||
| } on DioError catch (e) { | |||
| @@ -297,9 +306,9 @@ class Repository { | |||
| } | |||
| } | |||
| Future<RequestActivity> detailCommonAction({required int activityId, required String activityType}) async { | |||
| Future<RequestActivity> detailCommonAction({required int activityId}) async { | |||
| final client = RestClient(dio); | |||
| return client.getDetailActivityCommon(activityType, activityId); | |||
| return client.getDetailActivityCommon(activityId); | |||
| } | |||
| // Stamp | |||
| @@ -30,7 +30,7 @@ class LoadingDialog { | |||
| child: SizedBox( | |||
| width: 25, | |||
| height: 25, | |||
| child: Image.asset(AppAssets.logo)), | |||
| child: Image.asset(AppAssets.logoWithSlogan)), | |||
| ), | |||
| Container( | |||
| alignment: Alignment.center, | |||
| @@ -16,7 +16,6 @@ class ActionUiCubit extends Cubit<ActionUiState> { | |||
| Future<void> getActionUIForm({ | |||
| required bool isEdit, | |||
| required int actionId, | |||
| required String actionType, | |||
| required int activityId, | |||
| }) async { | |||
| try { | |||
| @@ -25,7 +24,7 @@ class ActionUiCubit extends Cubit<ActionUiState> { | |||
| var actionUIForm = await repository.getActionUIForm(idAction: actionId); | |||
| if (isEdit) { | |||
| try { | |||
| actionDetail = await repository.detailCommonAction(activityId: activityId, activityType: actionType); | |||
| actionDetail = await repository.detailCommonAction(activityId: activityId); | |||
| print(actionDetail); | |||
| } catch (e) { | |||
| print(e); | |||
| @@ -12,7 +12,6 @@ import 'package:farm_tpf/presentation/screens/actions/controller/ChangeUnit.dart | |||
| import 'package:farm_tpf/presentation/screens/actions/resource_device_activity/sc_device_activity.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/resources/sc_resource_helper.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/validators.dart'; | |||
| @@ -25,7 +24,8 @@ import '../util_action.dart'; | |||
| class WidgetDungSupply extends StatefulWidget { | |||
| final List<SuppliesUsing> currentItems; | |||
| final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; | |||
| WidgetDungSupply({required this.currentItems, required this.onChangeSupplies}); | |||
| final String urlSupply; | |||
| WidgetDungSupply({required this.currentItems, required this.onChangeSupplies, required this.urlSupply}); | |||
| @override | |||
| _WidgetDungSupplyState createState() => _WidgetDungSupplyState(); | |||
| } | |||
| @@ -160,7 +160,7 @@ class _WidgetDungSupplyState extends State<WidgetDungSupply> { | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => ResourceHelperScreen( | |||
| titleName: "Phân bón", | |||
| type: ConstCommon.supplyTypeDung, | |||
| urlSupply: widget.urlSupply, | |||
| selectedId: changeSelectedSupply.selectedSupplyId ?? -1, | |||
| currentItems: changeSupplyUsing.currentItems ?? [], | |||
| currentEditId: ((currentIndexEdit ?? 0) >= 0) | |||
| @@ -25,7 +25,9 @@ import '../util_action.dart'; | |||
| class WidgetHarvestProcessSupply extends StatefulWidget { | |||
| final List<SuppliesUsing>? currentItems; | |||
| final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; | |||
| final String urlSupply; | |||
| WidgetHarvestProcessSupply({ | |||
| required this.urlSupply, | |||
| this.currentItems, | |||
| required this.onChangeSupplies, | |||
| }); | |||
| @@ -163,7 +165,7 @@ class _WidgetHarvestProcessSupplyState extends State<WidgetHarvestProcessSupply> | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => ResourceHelperScreen( | |||
| titleName: "Hoá chất xử lý", | |||
| type: ConstCommon.supplyTypeAll, | |||
| urlSupply: widget.urlSupply, | |||
| selectedId: changeSelectedSupply.selectedSupplyId ?? -1, | |||
| currentItems: changeSupplyUsing.currentItems ?? [], | |||
| currentEditId: ((currentIndexEdit ?? -1) >= 0) | |||
| @@ -22,7 +22,8 @@ import 'package:farm_tpf/utils/formatter.dart'; | |||
| class WidgetPlantSupply extends StatefulWidget { | |||
| final List<SuppliesUsing>? currentItems; | |||
| final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; | |||
| WidgetPlantSupply({this.currentItems, required this.onChangeSupplies}); | |||
| final String urlSupply; | |||
| WidgetPlantSupply({required this.urlSupply, this.currentItems, required this.onChangeSupplies}); | |||
| @override | |||
| _WidgetPlantSupplyState createState() => _WidgetPlantSupplyState(); | |||
| } | |||
| @@ -147,7 +148,7 @@ class _WidgetPlantSupplyState extends State<WidgetPlantSupply> { | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => ResourceHelperScreen( | |||
| titleName: "Hoá chất xử lý", | |||
| type: ConstCommon.supplyTypeAll, | |||
| urlSupply: widget.urlSupply, | |||
| selectedId: changeSelectedSupply.selectedSupplyId ?? -1, | |||
| currentItems: changeSupplyUsing.currentItems ?? [], | |||
| currentEditId: ((currentIndexEdit ?? -1) >= 0) | |||
| @@ -21,6 +21,7 @@ import 'package:farm_tpf/presentation/custom_widgets/widget_text_field_area.dart | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/cubit/action_ui_cubit.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/supply_widget.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/pref.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| @@ -35,10 +36,7 @@ import '../../../utils/local_storage.dart'; | |||
| import 'controller/ChangeFieldInForm.dart'; | |||
| import 'controller/ChangeSupplyUsing.dart'; | |||
| import 'controller/ChangeWorker.dart'; | |||
| import 'dung/widget_dung_supply.dart'; | |||
| import 'nursery/widget_worker.dart'; | |||
| import 'plant/widget_plant_supply.dart'; | |||
| import 'spraying/widget_spraying_supply.dart'; | |||
| import 'state_management_helper/change_dropdown_controller.dart'; | |||
| import 'state_management_helper/change_file_controller.dart'; | |||
| import 'util_action.dart'; | |||
| @@ -47,16 +45,16 @@ class ActionScreen extends StatefulWidget { | |||
| final bool isEdit; | |||
| final int cropId; | |||
| final int idAction; | |||
| final String activityType; | |||
| final String title; | |||
| final int activityId; | |||
| final DateTime? executeDate; | |||
| ActionScreen({ | |||
| required this.isEdit, | |||
| required this.cropId, | |||
| required this.idAction, | |||
| required this.title, | |||
| required this.activityType, | |||
| required this.activityId, | |||
| this.executeDate, | |||
| }); | |||
| @override | |||
| @@ -94,40 +92,41 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| super.initState(); | |||
| getSharedPrefs(); | |||
| changeFileController.initValue(); | |||
| if (widget.executeDate != null) { | |||
| executeTime = widget.executeDate!; | |||
| } | |||
| } | |||
| _submitForm() async { | |||
| switch (widget.activityType) { | |||
| case 'ACTIVE_TYPE_NURSERY': | |||
| if (Get.find<ChangeFieldFormSupply>().isChanged ?? false) { | |||
| Utils.showDialog( | |||
| title: 'Thông tin người thực hiện chưa cập nhật', | |||
| message: 'Bạn có muốn cập nhật', | |||
| textConfirm: 'Tiếp tục', | |||
| textCancel: 'Xem lại', | |||
| onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| }); | |||
| } else { | |||
| _validateInputs(); | |||
| } | |||
| break; | |||
| // case 'ACTIVE_TYPE_PLANTING': | |||
| case 'ACTIVE_TYPE_FERTILIZE': | |||
| case 'ACTIVE_TYPE_SPRAYING_PESTICIDES': | |||
| if (Get.find<ChangeFieldFormSupply>().isChanged ?? false) { | |||
| Utils.showDialogConfirmSupply(onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| }); | |||
| } else { | |||
| final tbActivityType = _actionUIForm.tbActivityTypeDTO; | |||
| final isUseSupply = tbActivityType?.isUseSupply ?? false; | |||
| final isNursery = | |||
| tbActivityType?.isStart == true && tbActivityType?.position == 1; | |||
| if (isNursery) { | |||
| if (Get.find<ChangeFieldFormSupply>().isChanged ?? false) { | |||
| Utils.showDialog( | |||
| title: 'Thông tin người thực hiện chưa cập nhật', | |||
| message: 'Bạn có muốn cập nhật', | |||
| textConfirm: 'Tiếp tục', | |||
| textCancel: 'Xem lại', | |||
| onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| }); | |||
| } else { | |||
| _validateInputs(); | |||
| } | |||
| } else if (isUseSupply) { | |||
| if (Get.find<ChangeFieldFormSupply>().isChanged ?? false) { | |||
| Utils.showDialogConfirmSupply(onConfirm: () { | |||
| Get.back(); | |||
| _validateInputs(); | |||
| } | |||
| break; | |||
| default: | |||
| }); | |||
| } else { | |||
| _validateInputs(); | |||
| break; | |||
| } | |||
| } else { | |||
| _validateInputs(); | |||
| } | |||
| } | |||
| @@ -143,7 +142,10 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| ..tbActivityTypeId = widget.idAction | |||
| ..tbCropId = widget.cropId; | |||
| if ((_actionUIForm.activityExtendTypeDTOList ?? []).isNotEmpty) { | |||
| _requestActivity..externalTable = _actionUIForm?.activityExtendTypeDTOList?.first?.externalTable ?? ''; | |||
| _requestActivity | |||
| ..externalTable = _actionUIForm | |||
| ?.activityExtendTypeDTOList?.first?.externalTable ?? | |||
| ''; | |||
| } | |||
| filePaths = Get.find<ChangeFileController>().newFiles ?? []; | |||
| @@ -158,8 +160,10 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| _requestActivity.tbObjectUpdateDTOList?.forEach((element) { | |||
| print(valueObjects[element.tbObjectParameterId.toString()]); | |||
| var updateValue = ''; | |||
| if (Validators.stringNotNullOrEmpty(valueObjects[element.tbObjectParameterId.toString()] ?? '')) { | |||
| updateValue = valueObjects[element.tbObjectParameterId.toString()] ?? ''; | |||
| if (Validators.stringNotNullOrEmpty( | |||
| valueObjects[element.tbObjectParameterId.toString()] ?? '')) { | |||
| updateValue = | |||
| valueObjects[element.tbObjectParameterId.toString()] ?? ''; | |||
| } else { | |||
| updateValue = element.index ?? ''; | |||
| } | |||
| @@ -183,19 +187,24 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| _requestActivity.tbObjectUpdateDTOList = _objectPrameters; | |||
| } | |||
| final tbActivityType = _actionUIForm.tbActivityTypeDTO; | |||
| final isUseSupply = tbActivityType?.isUseSupply ?? false; | |||
| final isNursery = | |||
| tbActivityType?.isStart == true && tbActivityType?.position == 1; | |||
| //CHECK NURSERY | |||
| if (widget.activityType == 'ACTIVE_TYPE_NURSERY') { | |||
| if (isNursery) { | |||
| _requestActivity.tbNurseryDetailsDTOList = _nurseryDetails; | |||
| } else if ( | |||
| // widget.activityType == 'ACTIVE_TYPE_PLANTING' || | |||
| widget.activityType == 'ACTIVE_TYPE_FERTILIZE' || | |||
| widget.activityType == 'ACTIVE_TYPE_SPRAYING_PESTICIDES') { | |||
| isUseSupply) { | |||
| _requestActivity.tbSuppliesUsingDetailsDTOs = _supplyUsings; | |||
| } | |||
| //delete images | |||
| _requestActivity.deletedImages = Get.find<ChangeFileController>().deleteFiles; | |||
| _requestActivity.deletedImages = | |||
| Get.find<ChangeFileController>().deleteFiles; | |||
| //convert data to json | |||
| var activityCommonData = jsonEncode(_requestActivity.toJson()).toString(); | |||
| var activityCommonData = | |||
| jsonEncode(_requestActivity.toJson()).toString(); | |||
| print(activityCommonData); | |||
| if (widget.activityId < 0) { | |||
| @@ -207,7 +216,7 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, activityType: widget.activityType, activityData: activityCommonData, filePaths: filePaths); | |||
| }, activityData: activityCommonData, filePaths: filePaths); | |||
| } else { | |||
| //UPDATE | |||
| _repository.updateActionCommon((data) { | |||
| @@ -217,7 +226,7 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| }, (error) { | |||
| LoadingDialog.hideLoadingDialog(context); | |||
| Utils.showSnackBarError(message: AppException.handleError(error)); | |||
| }, activityType: widget.activityType, activityData: activityCommonData, filePaths: filePaths); | |||
| }, activityData: activityCommonData, filePaths: filePaths); | |||
| } | |||
| //ADD NEW | |||
| @@ -238,7 +247,8 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| return WidgetFieldDateTimePicker( | |||
| initDateTime: executeTime, | |||
| onUpdateDateTime: (selectedDate) { | |||
| _requestActivity.executeDate = selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| _requestActivity.executeDate = | |||
| selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| }); | |||
| } | |||
| @@ -256,7 +266,8 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| // GENERATE DYNAMIC FORM | |||
| // | |||
| Widget groupName(String name) { | |||
| if (_previousGroupFieldName == name || !Validators.stringNotNullOrEmpty(name)) { | |||
| if (_previousGroupFieldName == name || | |||
| !Validators.stringNotNullOrEmpty(name)) { | |||
| return SizedBox(); | |||
| } else { | |||
| _previousGroupFieldName = name ?? ''; | |||
| @@ -303,15 +314,17 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| decoration: InputDecoration( | |||
| labelText: ((field.isMandatory ?? false) ?? false) ? '${field.description} *' : '${field.description}', | |||
| hintText: field.description), | |||
| labelText: ((field.isMandatory ?? false) ?? false) | |||
| ? '${field.name} *' | |||
| : '${field.name}', | |||
| hintText: field.name), | |||
| controller: textFieldControllers[field.id.toString()], | |||
| onSaved: (newValue) {}, | |||
| validator: ((field.isMandatory ?? false) ?? false) | |||
| ? (String? value) { | |||
| return Validators.validateNotNullOrEmpty( | |||
| value ?? '', | |||
| 'Vui lòng nhập ${field.description}', | |||
| 'Vui lòng nhập ${field.name}', | |||
| ); | |||
| } | |||
| : null, | |||
| @@ -323,15 +336,19 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| children: [ | |||
| groupName(field.groupName ?? ''), | |||
| WidgetTextFormFieldNumber( | |||
| hintValue: field.description ?? '', | |||
| labelText: ((field.isMandatory ?? false) ?? false) ? '${field.description} *' : '${field.description}', | |||
| textController: textFieldControllers[field.id.toString()] ?? TextEditingController(), | |||
| hintValue: field.name ?? '', | |||
| labelText: ((field.isMandatory ?? false) ?? false) | |||
| ? '${field.name} *' | |||
| : '${field.name}', | |||
| textController: | |||
| textFieldControllers[field.id.toString()] ?? | |||
| TextEditingController(), | |||
| onSaved: (newValue) {}, | |||
| validator: ((field.isMandatory ?? false) ?? false) | |||
| ? (String? value) { | |||
| return Validators.validNumberOrEmpty( | |||
| value ?? '', | |||
| 'Vui lòng nhập ${field.description}', | |||
| 'Vui lòng nhập ${field.name}', | |||
| ); | |||
| } | |||
| : null, | |||
| @@ -343,15 +360,18 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| children: [ | |||
| groupName(field.groupName ?? ''), | |||
| TextFieldAreaWidget( | |||
| hint: field.description ?? '', | |||
| labelText: (field.isMandatory ?? false) ? '${field.description} *' : '${field.description}', | |||
| controller: textFieldControllers[field.id.toString()] ?? TextEditingController(), | |||
| hint: field.name ?? '', | |||
| labelText: (field.isMandatory ?? false) | |||
| ? '${field.name} *' | |||
| : '${field.name}', | |||
| controller: textFieldControllers[field.id.toString()] ?? | |||
| TextEditingController(), | |||
| onSaved: (newValue) {}, | |||
| validator: (field.isMandatory ?? false) | |||
| ? (String? value) { | |||
| return Validators.validateNotNullOrEmpty( | |||
| value ?? '', | |||
| 'Vui lòng nhập ${field.description}', | |||
| 'Vui lòng nhập ${field.name}', | |||
| ); | |||
| } | |||
| : null, | |||
| @@ -363,15 +383,17 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| children: [ | |||
| groupName(field.groupName ?? ''), | |||
| DropdownSupplyWidget( | |||
| titleName: field.description ?? '', | |||
| titleName: field.name ?? '', | |||
| tbSupply: field.tbActivityExtendTypeExternalTable ?? '', | |||
| tag: field.name ?? '', | |||
| value: field.description, | |||
| hint: '${field.description} ${(field.isMandatory ?? false) ? '*' : ''}', | |||
| value: field.name, | |||
| hint: | |||
| '${field.name} ${(field.isMandatory ?? false) ? '*' : ''}', | |||
| condition: field.tbActivityExtendTypeCondition ?? '', | |||
| invalidMessage: '', | |||
| onPressed: (commonData) { | |||
| valueObjects[field.id.toString()] = commonData.id.toString(); | |||
| valueObjects[field.id.toString()] = | |||
| commonData.id.toString(); | |||
| }, | |||
| ), | |||
| ], | |||
| @@ -385,7 +407,8 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| condition: field.tbActivityExtendTypeCondition ?? '', | |||
| supply: field.tbActivityExtendTypeExternalTable ?? '', | |||
| onPressed: (commonData) { | |||
| valueObjects[field.id.toString()] = commonData.id.toString(); | |||
| valueObjects[field.id.toString()] = | |||
| commonData.id.toString(); | |||
| }, | |||
| ), | |||
| ], | |||
| @@ -397,14 +420,17 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| FieldDateWidget( | |||
| tag: field.name ?? '', | |||
| isValidated: isValidated, | |||
| value: field.description, | |||
| hint: '${field.description} ${(field.isMandatory ?? false) ? '*' : ''}', | |||
| value: field.name, | |||
| hint: | |||
| '${field.name} ${(field.isMandatory ?? false) ? '*' : ''}', | |||
| onPressed: (selectedDate) { | |||
| valueObjects[field.id.toString()] = selectedDate.convertLocalDateTimeToStringUtcDateTime(); | |||
| valueObjects[field.id.toString()] = selectedDate | |||
| .convertLocalDateTimeToStringUtcDateTime(); | |||
| }, | |||
| validator: (field.isMandatory ?? false) | |||
| ? (String? value) { | |||
| return Validators.validateNotNullOrEmpty(value ?? '', 'Vui lòng nhập ${field.description}'); | |||
| return Validators.validateNotNullOrEmpty( | |||
| value ?? '', 'Vui lòng nhập ${field.name}'); | |||
| } | |||
| : null, | |||
| ), | |||
| @@ -422,65 +448,37 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| // GENERATE SUPPLY | |||
| // | |||
| Widget generateSupply(String activityType) { | |||
| switch (activityType) { | |||
| case 'ACTIVE_TYPE_NURSERY': | |||
| return WidgetWorker(onChangeWorkers: (nurseryDetails) { | |||
| _nurseryDetails = nurseryDetails; | |||
| }); | |||
| break; | |||
| // case 'ACTIVE_TYPE_PLANTING': | |||
| // return Column( | |||
| // children: [ | |||
| // Container( | |||
| // width: double.infinity, | |||
| // height: 16, | |||
| // color: Colors.grey[200], | |||
| // ), | |||
| // WidgetPlantSupply( | |||
| // currentItems: [], | |||
| // onChangeSupplies: (value) { | |||
| // _supplyUsings = value; | |||
| // }), | |||
| // ], | |||
| // ); | |||
| // break; | |||
| case 'ACTIVE_TYPE_FERTILIZE': | |||
| return Column( | |||
| children: [ | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| WidgetDungSupply( | |||
| currentItems: [], | |||
| onChangeSupplies: (value) { | |||
| _supplyUsings = value; | |||
| }), | |||
| ], | |||
| ); | |||
| break; | |||
| case 'ACTIVE_TYPE_SPRAYING_PESTICIDES': | |||
| return Column( | |||
| children: [ | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| WidgetSprayingSupply( | |||
| currentItems: [], | |||
| onChangeSupplies: (value) { | |||
| _supplyUsings = value; | |||
| }), | |||
| ], | |||
| ); | |||
| break; | |||
| default: | |||
| return Container(); | |||
| break; | |||
| Widget generateSupply({ | |||
| required String supplyGroup, | |||
| bool isUseSupply = false, | |||
| bool isStart = false, | |||
| int position = 0, | |||
| required String urlSupply, | |||
| }) { | |||
| if (isStart && position == 1) { | |||
| return WidgetWorker(onChangeWorkers: (nurseryDetails) { | |||
| _nurseryDetails = nurseryDetails; | |||
| }); | |||
| } | |||
| if (isUseSupply) { | |||
| return Column( | |||
| children: [ | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| SupplyWidget( | |||
| currentItems: [], | |||
| urlSupply: urlSupply, | |||
| supplyGroup: supplyGroup, | |||
| onChangeSupplies: (value) { | |||
| _supplyUsings = value; | |||
| }), | |||
| ], | |||
| ); | |||
| } | |||
| return SizedBox.shrink(); | |||
| } | |||
| void showDataWhenEdit(BuildContext context) { | |||
| @@ -500,15 +498,18 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| } | |||
| SchedulerBinding.instance.addPostFrameCallback((_) { | |||
| if ( | |||
| // widget.activityType == 'ACTIVE_TYPE_PLANTING' || | |||
| widget.activityType == 'ACTIVE_TYPE_FERTILIZE' || | |||
| widget.activityType == 'ACTIVE_TYPE_SPRAYING_PESTICIDES') { | |||
| final tbActivityType = _actionUIForm.tbActivityTypeDTO; | |||
| final isUseSupply = tbActivityType?.isUseSupply ?? false; | |||
| final isNursery = | |||
| tbActivityType?.isStart == true && tbActivityType?.position == 1; | |||
| if (isUseSupply) { | |||
| //list supply | |||
| Get.find<ChangeSupplyUsing>().changeInitList(_requestActivity.tbSuppliesUsingDetailsDTOs ?? []); | |||
| } else if (widget.activityType == 'ACTIVE_TYPE_NURSERY') { | |||
| Get.find<ChangeSupplyUsing>() | |||
| .changeInitList(_requestActivity.tbSuppliesUsingDetailsDTOs ?? []); | |||
| } else if (isNursery) { | |||
| //list nursery | |||
| Get.find<ChangeWorker>().changeInitList(_requestActivity.tbNurseryDetailsDTOList ?? []); | |||
| Get.find<ChangeWorker>() | |||
| .changeInitList(_requestActivity.tbNurseryDetailsDTOList ?? []); | |||
| } | |||
| }); | |||
| @@ -516,22 +517,35 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| if (_requestActivity.tbObjectUpdateDTOList != null) { | |||
| print(textFieldControllers.keys.toList()); | |||
| _requestActivity.tbObjectUpdateDTOList?.forEach((element) { | |||
| if (element.tbObjectParameterDTO?.tbControlTypeName == 'text' || element.tbObjectParameterDTO?.tbControlTypeName == 'textarea') { | |||
| if (element.tbObjectParameterDTO?.tbControlTypeName == 'text' || | |||
| element.tbObjectParameterDTO?.tbControlTypeName == 'textarea') { | |||
| SchedulerBinding.instance.addPostFrameCallback((_) { | |||
| textFieldControllers[element.tbObjectParameterId.toString()]?.text = element.index ?? ''; | |||
| textFieldControllers[element.tbObjectParameterId.toString()]?.text = | |||
| element.index ?? ''; | |||
| }); | |||
| } else if (element.tbObjectParameterDTO?.tbControlTypeName == 'number') { | |||
| } else if (element.tbObjectParameterDTO?.tbControlTypeName == | |||
| 'number') { | |||
| SchedulerBinding.instance.addPostFrameCallback((_) { | |||
| textFieldControllers[element.tbObjectParameterId.toString()]?.text = element.index?.formatStringToStringDecimal() ?? ''; | |||
| textFieldControllers[element.tbObjectParameterId.toString()]?.text = | |||
| element.index?.formatStringToStringDecimal() ?? ''; | |||
| }); | |||
| } else { | |||
| SchedulerBinding.instance.addPostFrameCallback((_) { | |||
| if (element.tbObjectParameterDTO?.tbControlTypeName == 'dropdown' || | |||
| element.tbObjectParameterDTO?.tbControlTypeName?.toLowerCase() == 'radiobutton') { | |||
| element.tbObjectParameterDTO?.tbControlTypeName | |||
| ?.toLowerCase() == | |||
| 'radiobutton') { | |||
| var dropdownValueName = ''; | |||
| if ((element.tbObjectParameterDTO?.tbActivityExtendTypeDropDownDTOList ?? []).isNotEmpty || | |||
| element.tbObjectParameterDTO?.tbActivityExtendTypeDropDownDTOList != null) { | |||
| element.tbObjectParameterDTO?.tbActivityExtendTypeDropDownDTOList?.forEach((dropdownData) { | |||
| if ((element.tbObjectParameterDTO | |||
| ?.tbActivityExtendTypeDropDownDTOList ?? | |||
| []) | |||
| .isNotEmpty || | |||
| element.tbObjectParameterDTO | |||
| ?.tbActivityExtendTypeDropDownDTOList != | |||
| null) { | |||
| element | |||
| .tbObjectParameterDTO?.tbActivityExtendTypeDropDownDTOList | |||
| ?.forEach((dropdownData) { | |||
| if (dropdownData.id == int.tryParse(element.index ?? '-1')) { | |||
| dropdownValueName = dropdownData.name ?? ''; | |||
| } | |||
| @@ -540,10 +554,16 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| var commonData = CommonData() | |||
| ..id = int.tryParse(element.index ?? '-1') | |||
| ..name = dropdownValueName; | |||
| Get.find<ChangeDropdownController>(tag: element.tbObjectParameterDTO?.name).change(commonData); | |||
| } else if (element.tbObjectParameterDTO?.tbControlTypeName == 'date') { | |||
| Get.find<ChangeDateTimePicker>(tag: element.tbObjectParameterDTO?.name).change( | |||
| element.index?.convertStringServerDateTimeToLocalDateTime() ?? DateTime.now(), | |||
| Get.find<ChangeDropdownController>( | |||
| tag: element.tbObjectParameterDTO?.name) | |||
| .change(commonData); | |||
| } else if (element.tbObjectParameterDTO?.tbControlTypeName == | |||
| 'date') { | |||
| Get.find<ChangeDateTimePicker>( | |||
| tag: element.tbObjectParameterDTO?.name) | |||
| .change( | |||
| element.index?.convertStringServerDateTimeToLocalDateTime() ?? | |||
| DateTime.now(), | |||
| ); | |||
| } | |||
| }); | |||
| @@ -567,7 +587,8 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| action: InkWell( | |||
| child: Text( | |||
| 'Lưu', | |||
| style: TextStyle(color: Colors.red, fontWeight: FontWeight.normal), | |||
| style: TextStyle( | |||
| color: Colors.red, fontWeight: FontWeight.normal), | |||
| ), | |||
| onTap: () { | |||
| FocusScopeNode currentFocus = FocusScope.of(context); | |||
| @@ -581,11 +602,15 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| body: MultiBlocProvider( | |||
| providers: [ | |||
| BlocProvider<ActionUiCubit>( | |||
| create: (context) => ActionUiCubit(repository: Repository()) | |||
| ..getActionUIForm( | |||
| actionId: widget.idAction, actionType: widget.activityType, isEdit: widget.isEdit, activityId: widget.activityId)), | |||
| create: (context) => | |||
| ActionUiCubit(repository: Repository()) | |||
| ..getActionUIForm( | |||
| actionId: widget.idAction, | |||
| isEdit: widget.isEdit, | |||
| activityId: widget.activityId)), | |||
| BlocProvider<MediaHelperBloc>( | |||
| create: (context) => MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| create: (context) => | |||
| MediaHelperBloc()..add(ChangeListMedia(items: [])), | |||
| ) | |||
| ], | |||
| child: Form( | |||
| @@ -599,20 +624,27 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| child: LoadingListPage(), | |||
| ); | |||
| } else if (state is ActionUiSuccess) { | |||
| _actionUIForm = state.actionUIForm ?? ActionUIForm(); | |||
| _requestActivity = state.activityDetail ?? RequestActivity(); | |||
| _actionUIForm = | |||
| state.actionUIForm ?? ActionUIForm(); | |||
| _requestActivity = | |||
| state.activityDetail ?? RequestActivity(); | |||
| //CREATE UI | |||
| _actionUIForm.objectParameterDTOList?.forEach((element) { | |||
| _actionUIForm.objectParameterDTOList | |||
| ?.forEach((element) { | |||
| //generate controller | |||
| if (element.tbControlTypeName == 'text' || | |||
| element.tbControlTypeName == 'number' || | |||
| element.tbControlTypeName == 'textarea') { | |||
| var textEditingController = new TextEditingController(); | |||
| textFieldControllers.putIfAbsent(element.id.toString(), () => textEditingController); | |||
| var textEditingController = | |||
| new TextEditingController(); | |||
| textFieldControllers.putIfAbsent( | |||
| element.id.toString(), | |||
| () => textEditingController); | |||
| } | |||
| // generate value each parameter | |||
| valueObjects.putIfAbsent(element.id.toString(), () => ''); | |||
| valueObjects.putIfAbsent( | |||
| element.id.toString(), () => ''); | |||
| }); | |||
| //SHOW EDIT DATA | |||
| if (widget.isEdit) { | |||
| @@ -630,14 +662,18 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| width: double.infinity, | |||
| child: Text( | |||
| "Ngày thực hiện *", | |||
| style: TextStyle(color: Colors.black54, fontSize: 13.0), | |||
| style: TextStyle( | |||
| color: Colors.black54, | |||
| fontSize: 13.0), | |||
| ), | |||
| ), | |||
| _btnExecuteTimePicker(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| generateField(_actionUIForm.objectParameterDTOList ?? []), | |||
| generateField(_actionUIForm | |||
| .objectParameterDTOList ?? | |||
| []), | |||
| _executeByField(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| @@ -645,21 +681,43 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| ], | |||
| ), | |||
| ), | |||
| generateSupply(widget.activityType), | |||
| generateSupply( | |||
| supplyGroup: _actionUIForm | |||
| .tbActivityTypeDTO?.supplyGroup ?? | |||
| '', | |||
| isUseSupply: _actionUIForm | |||
| .tbActivityTypeDTO?.isUseSupply ?? | |||
| false, | |||
| isStart: _actionUIForm | |||
| .tbActivityTypeDTO?.isStart ?? | |||
| false, | |||
| position: _actionUIForm | |||
| .tbActivityTypeDTO?.position ?? | |||
| 0, | |||
| urlSupply: _actionUIForm | |||
| .tbActivityTypeDTO?.urlSupply ?? | |||
| '', | |||
| ), | |||
| Container( | |||
| width: double.infinity, | |||
| height: 16, | |||
| color: Colors.grey[200], | |||
| ), | |||
| BlocBuilder<MediaHelperBloc, MediaHelperState>(builder: (context, state) { | |||
| BlocBuilder<MediaHelperBloc, | |||
| MediaHelperState>( | |||
| builder: (context, state) { | |||
| if (state is MediaHelperSuccess) { | |||
| return WidgetMediaPicker( | |||
| currentItems: state.items, | |||
| onChangeFiles: (newPathFiles, deletePathFiles) async { | |||
| Get.find<ChangeFileController>().change(newPathFiles, deletePathFiles); | |||
| onChangeFiles: (newPathFiles, | |||
| deletePathFiles) async { | |||
| Get.find<ChangeFileController>() | |||
| .change(newPathFiles, | |||
| deletePathFiles); | |||
| }); | |||
| } else { | |||
| return Center(child: CircularProgressIndicator()); | |||
| return Center( | |||
| child: CircularProgressIndicator()); | |||
| } | |||
| }), | |||
| Padding( | |||
| @@ -667,7 +725,8 @@ class _ActionScreenState extends State<ActionScreen> { | |||
| child: ButtonWidget( | |||
| title: 'CẬP NHẬT', | |||
| onPressed: () { | |||
| FocusScopeNode currentFocus = FocusScope.of(context); | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| @@ -26,7 +26,8 @@ import '../util_action.dart'; | |||
| class WidgetSprayingSupply extends StatefulWidget { | |||
| final List<SuppliesUsing>? currentItems; | |||
| final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; | |||
| WidgetSprayingSupply({this.currentItems, required this.onChangeSupplies}); | |||
| final String urlSupply; | |||
| WidgetSprayingSupply({required this.urlSupply, this.currentItems, required this.onChangeSupplies}); | |||
| @override | |||
| _WidgetSprayingSupplyState createState() => _WidgetSprayingSupplyState(); | |||
| } | |||
| @@ -162,7 +163,7 @@ class _WidgetSprayingSupplyState extends State<WidgetSprayingSupply> { | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => ResourceHelperScreen( | |||
| titleName: "Thuốc BVTV", | |||
| type: ConstCommon.supplyTypeProtectPlant, | |||
| urlSupply: widget.urlSupply, | |||
| selectedId: changeSelectedSupply.selectedSupplyId ?? -1, | |||
| currentItems: changeSupplyUsing.currentItems ?? [], | |||
| currentEditId: ((currentIndexEdit ?? -1) >= 0) | |||
| @@ -0,0 +1,733 @@ | |||
| import 'package:farm_tpf/custom_model/Device.dart'; | |||
| import 'package:farm_tpf/custom_model/SuppliesUsing.dart'; | |||
| import 'package:farm_tpf/custom_model/Supply.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/WidgetErrorTextField.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.dart'; | |||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeDevice.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeFieldInForm.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeFormButton.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeSupplyUsing.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/controller/ChangeUnit.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/resource_device_activity/sc_device_activity.dart'; | |||
| import 'package:farm_tpf/presentation/screens/actions/state_management_helper/change_supply.dart'; | |||
| import 'package:farm_tpf/presentation/screens/resources/sc_resource_helper.dart'; | |||
| import 'package:farm_tpf/utils/const_string.dart'; | |||
| import 'package:farm_tpf/utils/const_style.dart'; | |||
| import 'package:farm_tpf/utils/validators.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:get/get.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| import 'util_action.dart'; | |||
| class SupplyWidget extends StatefulWidget { | |||
| final List<SuppliesUsing> currentItems; | |||
| final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; | |||
| final String urlSupply; | |||
| final String supplyGroup; | |||
| SupplyWidget({ | |||
| required this.currentItems, | |||
| required this.onChangeSupplies, | |||
| required this.urlSupply, | |||
| required this.supplyGroup, | |||
| }); | |||
| @override | |||
| _SupplyWidgetState createState() => _SupplyWidgetState(); | |||
| } | |||
| class _SupplyWidgetState extends State<SupplyWidget> { | |||
| final _dosageController = TextEditingController(); | |||
| final _quantityController = TextEditingController(); | |||
| final _howToUseController = TextEditingController(); | |||
| final changeSelectedSupply = Get.put(ChangeSupply()); | |||
| final changeSupplyUsing = Get.put(ChangeSupplyUsing()); | |||
| final changeUnit = Get.put(ChangeUnit()); | |||
| final changeButton = Get.put(ChangeButtonInForm()); | |||
| final changeSelectedDevice = Get.put(ChangeDevice()); | |||
| final changeFormField = Get.put(ChangeFieldFormSupply()); | |||
| GlobalKey<FormState> _formSupplyKey = GlobalKey(); | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| changeSelectedSupply.initValue(); | |||
| changeSelectedDevice.initValue(); | |||
| changeSupplyUsing.init(widget.currentItems); | |||
| changeUnit.initValue(); | |||
| changeButton.resetValue(); | |||
| changeFormField.init(); | |||
| } | |||
| Widget _buildListSupply() { | |||
| return GetBuilder<ChangeSupplyUsing>( | |||
| init: changeSupplyUsing, | |||
| builder: (value) { | |||
| widget.onChangeSupplies(value.currentItems ?? []); | |||
| if (value.currentItems!.isEmpty) { | |||
| return Container(); | |||
| } else { | |||
| return Container( | |||
| height: 120, | |||
| child: ListView.builder( | |||
| physics: ClampingScrollPhysics(), | |||
| scrollDirection: Axis.horizontal, | |||
| shrinkWrap: true, | |||
| itemCount: value.currentItems?.length, | |||
| itemBuilder: (context, index) { | |||
| return GestureDetector( | |||
| onTap: () { | |||
| print("edit"); | |||
| changeSupplyUsing.changeIndexEdit(index); | |||
| changeButton.updateToEdit(true); | |||
| var editedSupplyUsing = | |||
| value.currentItems?[index] ?? SuppliesUsing(); | |||
| var editedSupply = Supply() | |||
| ..id = editedSupplyUsing.tbSuppliesInWarehouseId | |||
| ..tbSuppliesName = editedSupplyUsing.supplyName | |||
| ..unit = editedSupplyUsing.supplyUnit; | |||
| changeSelectedSupply.change(editedSupply); | |||
| var editedDevice = Device() | |||
| ..id = editedSupplyUsing.tbEquipmentOfCustomerId | |||
| ..name = editedSupplyUsing.equipmentName; | |||
| changeSelectedDevice.change(editedDevice); | |||
| changeUnit.updateListByUnitName( | |||
| editedSupplyUsing.supplyUnit ?? ''); | |||
| changeUnit.updateSelected( | |||
| editedSupplyUsing.supplyUnit ?? ''); | |||
| _dosageController.text = | |||
| editedSupplyUsing.dosage ?? ''; | |||
| _howToUseController.text = | |||
| editedSupplyUsing.howToUse ?? ''; | |||
| _quantityController.text = editedSupplyUsing | |||
| .quantity | |||
| ?.formatNumtoStringDecimal() ?? | |||
| '0'; | |||
| }, | |||
| child: Card( | |||
| child: Stack( | |||
| alignment: Alignment.bottomCenter, | |||
| children: <Widget>[ | |||
| Positioned( | |||
| child: ClipRRect( | |||
| borderRadius: BorderRadius.circular(8), | |||
| child: Container( | |||
| padding: EdgeInsets.all(4), | |||
| width: 150, | |||
| child: Column( | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment.center, | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| children: [ | |||
| SizedBox( | |||
| height: 12.0, | |||
| ), | |||
| Flexible( | |||
| child: Text( | |||
| value.currentItems?[index] | |||
| .supplyName ?? | |||
| "", | |||
| overflow: TextOverflow.ellipsis, | |||
| maxLines: 1), | |||
| ), | |||
| Validators.stringNotNullOrEmpty(value | |||
| .currentItems?[index] | |||
| .dosage ?? | |||
| '') | |||
| ? Flexible( | |||
| child: Text( | |||
| "${value.currentItems?[index].dosage ?? ""}")) | |||
| : SizedBox(), | |||
| Validators.stringNotNullOrEmpty(value | |||
| .currentItems?[index].quantity | |||
| ?.formatNumtoStringDecimal() ?? | |||
| '0') | |||
| ? Flexible( | |||
| child: Text( | |||
| "${value.currentItems?[index].quantity?.formatNumtoStringDecimal() ?? ""} ${value.currentItems?[index].supplyUnit ?? ""}")) | |||
| : SizedBox(), | |||
| Validators.stringNotNullOrEmpty(value | |||
| .currentItems?[index] | |||
| .equipmentName ?? | |||
| '') | |||
| ? Flexible( | |||
| child: Text( | |||
| "${value.currentItems?[index].equipmentName ?? ""}")) | |||
| : SizedBox(), | |||
| Validators.stringNotNullOrEmpty(value | |||
| .currentItems?[index] | |||
| .howToUse ?? | |||
| '') | |||
| ? Flexible( | |||
| child: Text( | |||
| "${value.currentItems?[index].howToUse ?? ""}")) | |||
| : SizedBox(), | |||
| ], | |||
| ), | |||
| ), | |||
| )), | |||
| Positioned( | |||
| top: -10, | |||
| right: -10, | |||
| child: IconButton( | |||
| icon: Icon( | |||
| Icons.cancel, | |||
| color: Colors.redAccent, | |||
| ), | |||
| onPressed: () { | |||
| changeSupplyUsing.deleteSupply(index); | |||
| }), | |||
| ) | |||
| ], | |||
| ))); | |||
| })); | |||
| } | |||
| }); | |||
| } | |||
| Widget _btnSelectSubstrates() { | |||
| return GetBuilder<ChangeSupply>( | |||
| init: changeSelectedSupply, | |||
| builder: (data) { | |||
| return TextButton( | |||
| onPressed: () { | |||
| var currentIndexEdit = changeSupplyUsing.currentIndex; | |||
| Navigator.of(context) | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => ResourceHelperScreen( | |||
| titleName: widget.supplyGroup, | |||
| urlSupply: widget.urlSupply, | |||
| selectedId: | |||
| changeSelectedSupply.selectedSupplyId ?? -1, | |||
| currentItems: | |||
| changeSupplyUsing.currentItems ?? [], | |||
| currentEditId: ((currentIndexEdit ?? 0) >= 0) | |||
| ? changeSupplyUsing | |||
| .currentItems![currentIndexEdit!] | |||
| .tbSuppliesInWarehouseId ?? | |||
| -1 | |||
| : -1, | |||
| ), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) { | |||
| var result = value as Supply; | |||
| changeSelectedSupply.change(result); | |||
| changeUnit.updateListByUnitName(result.unit ?? ''); | |||
| changeFormField.change(true); | |||
| } | |||
| }); | |||
| }, | |||
| child: GetBuilder<ChangeSupply>( | |||
| init: changeSelectedSupply, | |||
| builder: (_) { | |||
| var isValid = changeSelectedSupply.isValid; | |||
| return Column( | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| children: [ | |||
| Container( | |||
| padding: EdgeInsets.only( | |||
| top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: Border( | |||
| bottom: BorderSide( | |||
| width: 1, | |||
| color: (isValid ?? false) | |||
| ? Colors.grey | |||
| : Colors.red)), | |||
| ), | |||
| child: Column( | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| children: [ | |||
| Validators.stringNotNullOrEmpty( | |||
| changeSelectedSupply | |||
| .selectedSupplyName ?? | |||
| '') | |||
| ? Text( | |||
| 'Tên thương mại *', | |||
| style: TextStyle( | |||
| fontSize: 13, | |||
| fontWeight: FontWeight.normal, | |||
| color: (isValid ?? false) | |||
| ? Colors.black54 | |||
| : Colors.red[600]), | |||
| ) | |||
| : Text( | |||
| '', | |||
| style: TextStyle( | |||
| fontSize: 13, | |||
| fontWeight: FontWeight.normal, | |||
| color: (isValid ?? false) | |||
| ? Colors.black54 | |||
| : Colors.red[600]), | |||
| ), | |||
| Row( | |||
| children: [ | |||
| Expanded( | |||
| child: Validators.stringNotNullOrEmpty( | |||
| changeSelectedSupply | |||
| .selectedSupplyName ?? | |||
| '') | |||
| ? Text( | |||
| changeSelectedSupply | |||
| .selectedSupplyName ?? | |||
| '', | |||
| style: TextStyle( | |||
| fontSize: 14.0, | |||
| color: Colors.black87)) | |||
| : Text("Tên thương mại*", | |||
| style: TextStyle( | |||
| fontSize: 14.0, | |||
| color: Colors.black54)), | |||
| ), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ) | |||
| ], | |||
| )), | |||
| (isValid ?? false) ? SizedBox() : WidgetErrorTextField() | |||
| ], | |||
| ); | |||
| })); | |||
| }); | |||
| } | |||
| Widget _btnSelectDevice() { | |||
| return GetBuilder<ChangeDevice>( | |||
| init: changeSelectedDevice, | |||
| builder: (data) { | |||
| return TextButton( | |||
| onPressed: () { | |||
| Navigator.of(context) | |||
| .push(MaterialPageRoute( | |||
| builder: (_) => ListDeviceActivity( | |||
| selectedId: | |||
| changeSelectedDevice.selectedDeviceId ?? -1), | |||
| fullscreenDialog: false)) | |||
| .then((value) { | |||
| if (value != null) { | |||
| var result = value as Device; | |||
| changeSelectedDevice.change(result); | |||
| changeFormField.change(true); | |||
| } | |||
| }); | |||
| }, | |||
| child: Container( | |||
| padding: EdgeInsets.only( | |||
| top: 0.0, right: 0.0, bottom: 10.5, left: 0.0), | |||
| decoration: BoxDecoration( | |||
| border: kBorderTextField, | |||
| ), | |||
| child: Column( | |||
| crossAxisAlignment: CrossAxisAlignment.start, | |||
| children: [ | |||
| Validators.stringNotNullOrEmpty( | |||
| changeSelectedDevice.selectedDeviceName ?? '') | |||
| ? Text( | |||
| 'Thiết bị', | |||
| style: TextStyle( | |||
| fontSize: 13, | |||
| fontWeight: FontWeight.normal, | |||
| color: Colors.black54), | |||
| ) | |||
| : Text( | |||
| '', | |||
| style: TextStyle( | |||
| fontSize: 13, | |||
| fontWeight: FontWeight.normal, | |||
| color: Colors.black54), | |||
| ), | |||
| Row( | |||
| children: [ | |||
| GetBuilder<ChangeSupply>( | |||
| init: changeSelectedSupply, | |||
| builder: (_) => Expanded( | |||
| child: Validators.stringNotNullOrEmpty( | |||
| changeSelectedDevice | |||
| .selectedDeviceName ?? | |||
| '') | |||
| ? Text( | |||
| changeSelectedDevice | |||
| .selectedDeviceName ?? | |||
| '', | |||
| style: TextStyle( | |||
| fontSize: 14.0, | |||
| color: Colors.black87)) | |||
| : Text("Thiết bị", | |||
| style: TextStyle( | |||
| fontSize: 14.0, | |||
| color: Colors.black54)), | |||
| )), | |||
| Icon( | |||
| Icons.arrow_drop_down, | |||
| color: Colors.grey, | |||
| ), | |||
| ], | |||
| ), | |||
| ], | |||
| ))); | |||
| }); | |||
| } | |||
| Widget _dropdownUnitTypes() { | |||
| return GetBuilder<ChangeUnit>( | |||
| init: changeUnit, | |||
| builder: (data) { | |||
| return DropdownButtonFormField<String>( | |||
| itemHeight: 50, | |||
| value: !Validators.stringNotNullOrEmpty(data.selectedUnit ?? '') | |||
| ? null | |||
| : data.selectedUnit, | |||
| items: data.currentUnits! | |||
| .map((label) => DropdownMenuItem( | |||
| child: Text(label), | |||
| value: label, | |||
| )) | |||
| .toList(), | |||
| onChanged: (value) { | |||
| var currentQuantity = _quantityController.text; | |||
| num assignValue = currentQuantity.parseDoubleThousand(); | |||
| if (assignValue != null) { | |||
| var oldSelected = data.selectedUnit; | |||
| if (oldSelected == value) { | |||
| } else { | |||
| assignValue = UtilAction.convertUnit( | |||
| inputValue: assignValue, | |||
| oldUnit: oldSelected ?? '', | |||
| newUnit: value ?? '', | |||
| ); | |||
| } | |||
| _quantityController.text = | |||
| assignValue.formatNumtoStringDecimal(); | |||
| } | |||
| changeUnit.updateSelected(value ?? ''); | |||
| }, | |||
| ); | |||
| }); | |||
| } | |||
| _quantityField() { | |||
| return WidgetTextFormFieldNumber( | |||
| hintValue: "Tổng lượng sử dụng *", | |||
| labelText: "Tổng lượng sử dụng *", | |||
| textController: _quantityController, | |||
| validator: (String? value) { | |||
| return Validators.validateNotNullOrEmpty( | |||
| value ?? '', label_validate_input_empty); | |||
| }, | |||
| onChanged: (value) { | |||
| if (!Validators.stringNotNullOrEmpty(value ?? '') && | |||
| !Validators.stringNotNullOrEmpty(_howToUseController.text) && | |||
| !Validators.stringNotNullOrEmpty(_dosageController.text) && | |||
| (Get.find<ChangeSupply>().selectedSupplyId ?? -1) <= 0 && | |||
| (changeSelectedDevice.selectedDeviceId ?? -1) <= 0) { | |||
| changeFormField.change(false); | |||
| } else { | |||
| changeFormField.change(true); | |||
| } | |||
| }, | |||
| ); | |||
| } | |||
| _buttonInForm() { | |||
| return GetBuilder<ChangeButtonInForm>( | |||
| init: changeButton, | |||
| builder: (_) { | |||
| return Row( | |||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
| children: [ | |||
| _.isEdit ?? false | |||
| ? TextButton( | |||
| child: Text("Huỷ"), | |||
| onPressed: () { | |||
| changeButton.resetValue(); | |||
| _resetForm(); | |||
| _hidenKeyboard(context); | |||
| }) | |||
| : SizedBox(), | |||
| _.isEdit ?? false | |||
| ? Expanded( | |||
| child: TextButton( | |||
| onPressed: () { | |||
| if (_formSupplyKey.currentState!.validate()) { | |||
| _formSupplyKey.currentState!.save(); | |||
| if ((changeSelectedSupply.selectedSupplyId ?? | |||
| -1) <= | |||
| 0) { | |||
| changeSelectedSupply.changeValid(false); | |||
| } else { | |||
| changeSelectedSupply.changeValid(true); | |||
| } | |||
| var currentSupply = | |||
| changeSelectedSupply.currentSupply; | |||
| var currentDevice = | |||
| changeSelectedDevice.currentDevice; | |||
| var currentQuantity = _quantityController.text | |||
| .parseDoubleThousand(); | |||
| if (currentSupply?.id != null && | |||
| (currentQuantity ?? 0) > 0) { | |||
| var quantityWithCurrentSupplyUnit = | |||
| UtilAction.convertUnit( | |||
| inputValue: currentQuantity, | |||
| oldUnit: changeUnit.selectedUnit ?? '', | |||
| newUnit: changeSelectedSupply | |||
| .currentSupply?.unit ?? | |||
| '', | |||
| ); | |||
| SuppliesUsing newSup = SuppliesUsing() | |||
| ..dosage = _dosageController.text | |||
| ..howToUse = _howToUseController.text | |||
| ..quantity = quantityWithCurrentSupplyUnit | |||
| ..tbSuppliesInWarehouseId = currentSupply?.id | |||
| ..suppliesInWarehouseId = currentSupply?.id | |||
| ..supplyName = currentSupply?.tbSuppliesName | |||
| ..tbEquipmentOfCustomerId = | |||
| currentDevice?.id ?? -1 | |||
| ..equipmentOfCustomerId = | |||
| currentDevice?.id ?? -1 | |||
| ..equipmentName = currentDevice?.name ?? '' | |||
| ..supplyUnit = currentSupply?.unit | |||
| ..unit = currentSupply?.unit; | |||
| changeSupplyUsing.editSupply( | |||
| changeSupplyUsing.currentIndex ?? -1, | |||
| newSup); | |||
| _resetForm(); | |||
| _hidenKeyboard(context); | |||
| } else if (currentSupply?.id == null || | |||
| ((currentQuantity ?? 0) <= 0)) { | |||
| Utils.showSnackBarWarning( | |||
| message: | |||
| "Vui lòng nhập vật tư và số lượng"); | |||
| } | |||
| } else { | |||
| Utils.showSnackBarWarning( | |||
| message: "Vui lòng nhập vật tư và số lượng"); | |||
| if ((changeSelectedSupply.selectedSupplyId ?? | |||
| -1) <= | |||
| 0) { | |||
| changeSelectedSupply.changeValid(false); | |||
| } else { | |||
| changeSelectedSupply.changeValid(true); | |||
| } | |||
| } | |||
| }, | |||
| child: Text( | |||
| "Sửa ${widget.supplyGroup}", | |||
| style: TextStyle(color: Colors.blue), | |||
| )), | |||
| ) | |||
| : Expanded( | |||
| child: TextButton( | |||
| onPressed: () { | |||
| if (_formSupplyKey.currentState!.validate()) { | |||
| _formSupplyKey.currentState!.save(); | |||
| if ((changeSelectedSupply.selectedSupplyId ?? | |||
| -1) <= | |||
| 0) { | |||
| changeSelectedSupply.changeValid(false); | |||
| } else { | |||
| changeSelectedSupply.changeValid(true); | |||
| } | |||
| var currentSupply = | |||
| changeSelectedSupply.currentSupply; | |||
| var currentDevice = | |||
| changeSelectedDevice.currentDevice; | |||
| var currentQuantity = _quantityController.text | |||
| .parseDoubleThousand(); | |||
| if (currentSupply?.id != null && | |||
| (currentQuantity ?? 0) > 0) { | |||
| var quantityWithCurrentSupplyUnit = | |||
| UtilAction.convertUnit( | |||
| inputValue: currentQuantity, | |||
| oldUnit: changeUnit.selectedUnit ?? '', | |||
| newUnit: changeSelectedSupply | |||
| .currentSupply?.unit ?? | |||
| '', | |||
| ); | |||
| SuppliesUsing newSup = SuppliesUsing() | |||
| ..dosage = _dosageController.text | |||
| ..howToUse = _howToUseController.text | |||
| ..quantity = quantityWithCurrentSupplyUnit | |||
| ..tbSuppliesInWarehouseId = currentSupply?.id | |||
| ..suppliesInWarehouseId = currentSupply?.id | |||
| ..supplyName = currentSupply?.tbSuppliesName | |||
| ..supplyUnit = currentSupply?.unit | |||
| ..tbEquipmentOfCustomerId = | |||
| currentDevice?.id ?? -1 | |||
| ..equipmentOfCustomerId = | |||
| currentDevice?.id ?? -1 | |||
| ..equipmentName = currentDevice?.name | |||
| ..unit = currentSupply?.unit; | |||
| changeSupplyUsing.addSupply(newSup); | |||
| _resetForm(); | |||
| _hidenKeyboard(context); | |||
| } else if (currentSupply?.id == null || | |||
| ((currentQuantity ?? 0) <= 0)) { | |||
| Utils.showSnackBarWarning( | |||
| message: | |||
| "Vui lòng nhập vật tư và số lượng"); | |||
| } | |||
| } else { | |||
| Utils.showSnackBarWarning( | |||
| message: "Vui lòng nhập vật tư và số lượng"); | |||
| if ((changeSelectedSupply.selectedSupplyId ?? | |||
| -1) <= | |||
| 0) { | |||
| changeSelectedSupply.changeValid(false); | |||
| } else { | |||
| changeSelectedSupply.changeValid(true); | |||
| } | |||
| // | |||
| } | |||
| }, | |||
| child: Text( | |||
| "+ Thêm ${widget.supplyGroup}", | |||
| style: TextStyle(color: Colors.blue), | |||
| )), | |||
| ) | |||
| ], | |||
| ); | |||
| }); | |||
| } | |||
| Widget _formEdit() { | |||
| return Form( | |||
| key: _formSupplyKey, | |||
| child: Column( | |||
| children: [ | |||
| Container( | |||
| padding: EdgeInsets.all(8.0), | |||
| margin: EdgeInsets.all(8.0), | |||
| decoration: BoxDecoration( | |||
| shape: BoxShape.rectangle, | |||
| borderRadius: BorderRadius.circular(10), | |||
| color: Colors.white, | |||
| border: Border.all(color: Colors.grey), | |||
| ), | |||
| child: Column( | |||
| children: [ | |||
| _btnSelectSubstrates(), | |||
| TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| controller: _dosageController, | |||
| decoration: InputDecoration(labelText: "Liều lượng sử dụng"), | |||
| onSaved: (newValue) {}, | |||
| onChanged: (value) { | |||
| if (!Validators.stringNotNullOrEmpty( | |||
| _quantityController.text) && | |||
| !Validators.stringNotNullOrEmpty( | |||
| _howToUseController.text) && | |||
| !Validators.stringNotNullOrEmpty(value) && | |||
| (Get.find<ChangeSupply>().selectedSupplyId ?? -1) <= | |||
| 0 && | |||
| (changeSelectedDevice.selectedDeviceId ?? -1) <= 0) { | |||
| changeFormField.change(false); | |||
| } else { | |||
| changeFormField.change(true); | |||
| } | |||
| }, | |||
| ), | |||
| Row( | |||
| mainAxisSize: MainAxisSize.min, | |||
| mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |||
| crossAxisAlignment: CrossAxisAlignment.center, | |||
| children: [ | |||
| Expanded( | |||
| flex: 2, | |||
| child: Container( | |||
| height: 70, | |||
| child: _quantityField(), | |||
| ), | |||
| ), | |||
| SizedBox( | |||
| width: 16.0, | |||
| ), | |||
| Expanded( | |||
| flex: 1, | |||
| child: Align( | |||
| alignment: Alignment.bottomCenter, | |||
| child: _dropdownUnitTypes(), | |||
| )), | |||
| ]), | |||
| _btnSelectDevice(), | |||
| TextFormField( | |||
| keyboardType: TextInputType.text, | |||
| controller: _howToUseController, | |||
| decoration: InputDecoration(labelText: "Phương pháp sử dụng"), | |||
| onSaved: (newValue) {}, | |||
| onChanged: (value) { | |||
| if (!Validators.stringNotNullOrEmpty( | |||
| _quantityController.text) && | |||
| !Validators.stringNotNullOrEmpty(value) && | |||
| !Validators.stringNotNullOrEmpty( | |||
| _dosageController.text) && | |||
| (Get.find<ChangeSupply>().selectedSupplyId ?? -1) <= | |||
| 0 && | |||
| (changeSelectedDevice.selectedDeviceId ?? -1) <= 0) { | |||
| changeFormField.change(false); | |||
| } else { | |||
| changeFormField.change(true); | |||
| } | |||
| }, | |||
| ), | |||
| ], | |||
| ), | |||
| ), | |||
| _buttonInForm() | |||
| ], | |||
| ), | |||
| ); | |||
| } | |||
| _resetForm() { | |||
| changeSupplyUsing.changeIndexEdit(-1); | |||
| changeButton.resetValue(); | |||
| _dosageController.text = ""; | |||
| _howToUseController.text = ""; | |||
| _quantityController.text = ""; | |||
| changeUnit.initValue(); | |||
| changeSelectedSupply.initValue(); | |||
| changeSelectedDevice.initValue(); | |||
| changeFormField.change(false); | |||
| } | |||
| _hidenKeyboard(BuildContext context) { | |||
| FocusScopeNode currentFocus = FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Column( | |||
| children: [ | |||
| Padding( | |||
| padding: const EdgeInsets.all(8.0), | |||
| child: Align( | |||
| alignment: Alignment.centerLeft, | |||
| child: Text( | |||
| widget.supplyGroup, | |||
| style: TextStyle(color: Colors.black54, fontSize: 14), | |||
| ), | |||
| ), | |||
| ), | |||
| _buildListSupply(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| _formEdit(), | |||
| SizedBox( | |||
| height: 8.0, | |||
| ), | |||
| ], | |||
| ); | |||
| } | |||
| } | |||
| @@ -35,10 +35,10 @@ class _LoginPageState extends State<LoginPage> { | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| // if (kDebugMode) { | |||
| // loginBloc.usernameCtl.text = 'quanly1'; | |||
| // loginBloc.passwordCtl.text = 'Abcd@1234'; | |||
| // } | |||
| if (kDebugMode) { | |||
| loginBloc.usernameCtl.text = 'quanly1'; | |||
| loginBloc.passwordCtl.text = '1234567890'; | |||
| } | |||
| prepareData(); | |||
| } | |||
| @@ -137,7 +137,7 @@ class _LoginPageState extends State<LoginPage> { | |||
| right: 40.w, | |||
| left: 40.w, | |||
| child: Image.asset( | |||
| AssetPNG.logo, | |||
| AssetPNG.logoWithSlogan, | |||
| height: 150, | |||
| ), | |||
| ), | |||
| @@ -216,7 +216,8 @@ class _LoginPageState extends State<LoginPage> { | |||
| ValueListenableBuilder<String>( | |||
| valueListenable: loginErrorMessage, | |||
| builder: (context, errorMessage, _) { | |||
| if (Validators.stringNotNullOrEmpty(errorMessage)) { | |||
| if (Validators.stringNotNullOrEmpty( | |||
| errorMessage)) { | |||
| return Container( | |||
| decoration: BoxDecoration( | |||
| color: AppColors.semantic7, | |||
| @@ -225,7 +226,8 @@ class _LoginPageState extends State<LoginPage> { | |||
| margin: const EdgeInsets.only( | |||
| top: 16, | |||
| ), | |||
| padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), | |||
| padding: const EdgeInsets.symmetric( | |||
| vertical: 4, horizontal: 8), | |||
| child: Row( | |||
| children: [ | |||
| SvgPicture.asset(AssetSVG.icWarning), | |||
| @@ -284,7 +284,6 @@ class ItemInfinityWidget extends StatelessWidget { | |||
| isEdit: true, | |||
| cropId: item.tbCropId ?? -1, | |||
| activityId: item.externalId ?? -1, | |||
| activityType: item.activityTypeName ?? '', | |||
| title: 'ActionScreen', | |||
| idAction: item.activityTypeId ?? -1, | |||
| )); | |||
| @@ -53,7 +53,6 @@ class _PlotActionScreenState extends State<PlotActionScreen> with AutomaticKeepA | |||
| cropId: widget.cropId ?? -1, | |||
| idAction: actionType.id ?? -1, | |||
| title: actionType.description ?? '', | |||
| activityType: actionType.name ?? '', | |||
| activityId: -1, | |||
| isEdit: false, | |||
| )); | |||
| @@ -86,7 +85,7 @@ class _PlotActionScreenState extends State<PlotActionScreen> with AutomaticKeepA | |||
| color: Colors.grey[300], | |||
| ), | |||
| errorWidget: (context, url, error) => Image.asset( | |||
| AppAssets.logo, | |||
| AppAssets.logoWithSlogan, | |||
| ), | |||
| ), | |||
| ), | |||
| @@ -96,7 +95,7 @@ class _PlotActionScreenState extends State<PlotActionScreen> with AutomaticKeepA | |||
| child: Align( | |||
| alignment: Alignment.center, | |||
| child: AutoSizeText( | |||
| actionType.description ?? '', | |||
| actionType.name ?? '', | |||
| textAlign: TextAlign.center, | |||
| style: TextStyle( | |||
| fontWeight: FontWeight.bold, | |||
| @@ -165,7 +165,7 @@ class ItemInfinityWidget extends StatelessWidget { | |||
| return GestureDetector( | |||
| child: WidgetRowPlotInfo( | |||
| color: index % 2 == 0 ? AppColors.DEFAULT.withOpacity(0.3) : AppColors.DEFAULT.withOpacity(0.1), | |||
| name: '${item.activityTypeDescription ?? ''}', | |||
| name: '${item.activityTypeName ?? ''}', | |||
| value: item.executeDate?.fromUtcToLocal() ?? ''), | |||
| onTap: () { | |||
| if (item.activityTypeName == 'ACTIVE_TYPE_UPDATE_ENV') { | |||
| @@ -179,9 +179,9 @@ class ItemInfinityWidget extends StatelessWidget { | |||
| isEdit: true, | |||
| cropId: item.cropId ?? -1, | |||
| activityId: item.id ?? -1, | |||
| activityType: item.activityTypeName ?? '', | |||
| title: 'ActionScreen', | |||
| idAction: item.activityTypeId ?? -1, | |||
| executeDate: item.executeDate?.convertStringServerDateTimeToLocalDateTime(), | |||
| )); | |||
| } | |||
| }); | |||
| @@ -24,7 +24,8 @@ class PlotInformationScreen extends StatefulWidget { | |||
| _PlotInformationScreenState createState() => _PlotInformationScreenState(); | |||
| } | |||
| class _PlotInformationScreenState extends State<PlotInformationScreen> with AutomaticKeepAliveClientMixin { | |||
| class _PlotInformationScreenState extends State<PlotInformationScreen> | |||
| with AutomaticKeepAliveClientMixin { | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||
| TextEditingController _descriptionController = TextEditingController(); | |||
| @@ -54,7 +55,8 @@ class _PlotInformationScreenState extends State<PlotInformationScreen> with Auto | |||
| default: | |||
| statusCrop = plot_status_unknown; | |||
| } | |||
| _descriptionController.text = _crop.description == null ? "" : _crop.description.toString(); | |||
| _descriptionController.text = | |||
| _crop.description == null ? "" : _crop.description.toString(); | |||
| if (_crop.tbDetailUsers != null) { | |||
| for (var i = 0; i < (_crop.tbDetailUsers ?? []).length; i++) { | |||
| if (i == 0) { | |||
| @@ -92,7 +94,10 @@ class _PlotInformationScreenState extends State<PlotInformationScreen> with Auto | |||
| keyboardType: TextInputType.text, | |||
| controller: _descriptionController, | |||
| decoration: InputDecoration( | |||
| labelText: "Ghi chú", hintText: 'Ghi chú', enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 0.35))), | |||
| labelText: "Ghi chú", | |||
| hintText: 'Ghi chú', | |||
| enabledBorder: UnderlineInputBorder( | |||
| borderSide: BorderSide(color: Colors.grey, width: 0.35))), | |||
| onSaved: (newValue) { | |||
| _crop.description = newValue; | |||
| }, | |||
| @@ -121,7 +126,8 @@ class _PlotInformationScreenState extends State<PlotInformationScreen> with Auto | |||
| body: KeyboardDismisser( | |||
| child: StreamBuilder( | |||
| stream: getPlotInfoBloc.actions, | |||
| builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) { | |||
| builder: | |||
| (BuildContext context, AsyncSnapshot<dynamic> snapshot) { | |||
| if (snapshot.hasData) { | |||
| return Form( | |||
| key: _formKey, | |||
| @@ -130,33 +136,74 @@ class _PlotInformationScreenState extends State<PlotInformationScreen> with Auto | |||
| child: Column( | |||
| children: <Widget>[ | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.1), name: 'Mã lô', value: '${cropPlot.tbCropDTO?.code ?? ''}'), | |||
| WidgetRowPlotInfo(color: AppColors.DEFAULT.withOpacity(0.3), name: 'Trạng thái', value: '$statusCrop'), | |||
| color: AppColors.DEFAULT.withOpacity(0.1), | |||
| name: 'Mã lô', | |||
| value: '${cropPlot.tbCropDTO?.code ?? ''}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.3), | |||
| name: 'Trạng thái', | |||
| value: '$statusCrop'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.1), | |||
| name: 'Nhà màng', | |||
| value: '${cropPlot.tbCropDTO?.netHouseName ?? '--'}'), | |||
| value: | |||
| '${cropPlot.tbCropDTO?.netHouseName ?? '--'}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.3), name: 'Giống', value: '${cropPlot.tbCropDTO?.suppliesName ?? '--'}'), | |||
| color: AppColors.DEFAULT.withOpacity(0.3), | |||
| name: 'Giống', | |||
| value: | |||
| '${cropPlot.tbCropDTO?.suppliesName ?? '--'}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.1), | |||
| name: 'Ngày gieo trồng', | |||
| value: '${cropPlot.plantingDate?.fromUtcToLocal() ?? '--'}'), | |||
| name: 'Ngày ươm', | |||
| value: | |||
| '${cropPlot.sowingDate?.fromUtcToLocal() ?? '--'}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.3), name: 'Số lượng cây trồng', value: '${cropPlot.numberPlants ?? '--'}'), | |||
| color: AppColors.DEFAULT.withOpacity(0.3), | |||
| name: 'Ngày gieo trồng', | |||
| value: | |||
| '${cropPlot.plantingDate?.fromUtcToLocal() ?? '--'}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.1), | |||
| name: 'Số lượng cây trồng', | |||
| value: '${cropPlot.numberPlants ?? '--'}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.3), | |||
| name: 'Số lượng cây hiện tại', | |||
| value: '${cropPlot.numberCurrentPlants ?? '--'}'), | |||
| value: | |||
| '${cropPlot.numberCurrentPlants ?? '--'}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.1), | |||
| name: 'Số lượng loại bỏ', | |||
| value: | |||
| '${cropPlot.numberRemovals ?? '--'}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.3), | |||
| name: 'Ngày kết thúc canh tác', | |||
| value: '${cropPlot.tbCropDTO?.endDate?.fromUtcToLocal() ?? '--'}'), | |||
| WidgetRowPlotInfo(color: AppColors.DEFAULT.withOpacity(0.1), name: 'Kỹ sư trực tiếp', value: '$technicians'), | |||
| value: | |||
| '${cropPlot.tbCropDTO?.endDate?.fromUtcToLocal() ?? '--'}'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.1), | |||
| name: 'Kỹ sư trực tiếp', | |||
| value: '$technicians'), | |||
| WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity(0.3), | |||
| name: 'Diện tích (m\u00B2)', | |||
| value: '${cropPlot.tbCropDTO?.areaM2 == null ? '--' : cropPlot.tbCropDTO!.areaM2!.formatNumtoStringDecimal()}'), | |||
| value: | |||
| '${cropPlot.tbCropDTO?.areaM2 == null ? '--' : cropPlot.tbCropDTO!.areaM2!.formatNumtoStringDecimal()}'), | |||
| if (cropPlot.objectParameterDataDTOS != null) | |||
| ...cropPlot.objectParameterDataDTOS! | |||
| .asMap() | |||
| .entries | |||
| .map((e) { | |||
| final index = e.key; | |||
| final value = e.value; | |||
| return WidgetRowPlotInfo( | |||
| color: AppColors.DEFAULT.withOpacity( | |||
| index % 2 == 0 ? 0.1 : 0.3), | |||
| name: value.name ?? '--', | |||
| value: value.index ?? '--'); | |||
| }).toList(), | |||
| SizedBox( | |||
| height: 8, | |||
| ), | |||
| @@ -172,8 +219,10 @@ class _PlotInformationScreenState extends State<PlotInformationScreen> with Auto | |||
| onPressed: controller.isChanged == false | |||
| ? () {} | |||
| : () { | |||
| FocusScopeNode currentFocus = FocusScope.of(context); | |||
| if (!currentFocus.hasPrimaryFocus) { | |||
| FocusScopeNode currentFocus = | |||
| FocusScope.of(context); | |||
| if (!currentFocus | |||
| .hasPrimaryFocus) { | |||
| currentFocus.unfocus(); | |||
| } | |||
| _validateInputs(); | |||
| @@ -4,7 +4,6 @@ import 'package:bloc/bloc.dart'; | |||
| import 'package:equatable/equatable.dart'; | |||
| import 'package:farm_tpf/custom_model/Supply.dart'; | |||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||
| import 'package:meta/meta.dart'; | |||
| part 'supply_event.dart'; | |||
| part 'supply_state.dart'; | |||
| @@ -19,7 +18,7 @@ class SupplyBloc extends Bloc<SupplyEvent, SupplyState> { | |||
| ) async* { | |||
| if (event is DataFetched) { | |||
| try { | |||
| final response = await repository.getSupplies(event.type); | |||
| final response = await repository.getSupplies(event.urlSupply); | |||
| List<Supply> supplies = response.map((supply) { | |||
| if (supply.id == event.selectedId) { | |||
| supply.isSelected = true; | |||
| @@ -27,12 +26,12 @@ class SupplyBloc extends Bloc<SupplyEvent, SupplyState> { | |||
| return supply; | |||
| }).toList(); | |||
| yield SupplySuccess(items: supplies); | |||
| } catch (_) { | |||
| } catch (e) { | |||
| yield SupplyFailure(); | |||
| } | |||
| } else if (event is OnRefresh) { | |||
| try { | |||
| final response = await repository.getSupplies(event.type); | |||
| final response = await repository.getSupplies(event.urlSupply); | |||
| List<Supply> supplies = response.map((supply) { | |||
| if (supply.id == event.selectedId) { | |||
| supply.isSelected = true; | |||
| @@ -45,7 +44,8 @@ class SupplyBloc extends Bloc<SupplyEvent, SupplyState> { | |||
| } | |||
| } else if (event is OnSearch) { | |||
| try { | |||
| final response = await repository.getSupplies(event.type ?? '', query: event.searchString ?? ''); | |||
| final response = await repository.getSupplies(event.urlSupply, | |||
| query: event.searchString ?? ''); | |||
| List<Supply> supplies = response.map((supply) { | |||
| if (supply.id == event.selectedId) { | |||
| supply.isSelected = true; | |||
| @@ -9,19 +9,19 @@ abstract class SupplyEvent extends Equatable { | |||
| class DataFetched extends SupplyEvent { | |||
| final int? selectedId; | |||
| final String type; | |||
| DataFetched({this.selectedId, required this.type}); | |||
| final String urlSupply; | |||
| DataFetched({this.selectedId, required this.urlSupply}); | |||
| } | |||
| class OnRefresh extends SupplyEvent { | |||
| final int? selectedId; | |||
| final String type; | |||
| OnRefresh({this.selectedId, required this.type}); | |||
| final String urlSupply; | |||
| OnRefresh({this.selectedId, required this.urlSupply}); | |||
| } | |||
| class OnSearch extends SupplyEvent { | |||
| final String? searchString; | |||
| final int? selectedId; | |||
| final String? type; | |||
| OnSearch({this.searchString, this.selectedId, this.type}); | |||
| final String urlSupply; | |||
| OnSearch({this.searchString, this.selectedId, required this.urlSupply}); | |||
| } | |||
| @@ -14,17 +14,17 @@ import 'package:get/get.dart'; | |||
| import 'package:farm_tpf/utils/formatter.dart'; | |||
| class ResourceHelperScreen extends StatefulWidget { | |||
| final String type; | |||
| final int selectedId; | |||
| final String titleName; | |||
| final List<SuppliesUsing> currentItems; | |||
| final int currentEditId; | |||
| final String urlSupply; | |||
| ResourceHelperScreen({ | |||
| required this.type, | |||
| required this.selectedId, | |||
| required this.titleName, | |||
| required this.currentItems, | |||
| required this.currentEditId, | |||
| required this.urlSupply, | |||
| }); | |||
| @override | |||
| _ResourceHelperScreenState createState() => _ResourceHelperScreenState(); | |||
| @@ -34,10 +34,10 @@ class _ResourceHelperScreenState extends State<ResourceHelperScreen> { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return BlocProvider( | |||
| create: (context) => SupplyBloc(repository: Repository())..add(DataFetched(type: widget.type, selectedId: widget.selectedId)), | |||
| create: (context) => SupplyBloc(repository: Repository())..add(DataFetched(urlSupply: widget.urlSupply, selectedId: widget.selectedId)), | |||
| child: HoldInfinityWidget( | |||
| selectedId: widget.selectedId, | |||
| type: widget.type, | |||
| urlSupply: widget.urlSupply, | |||
| titleName: widget.titleName, | |||
| currentItems: widget.currentItems, | |||
| currentEditId: widget.currentEditId, | |||
| @@ -48,12 +48,12 @@ class _ResourceHelperScreenState extends State<ResourceHelperScreen> { | |||
| class HoldInfinityWidget extends StatelessWidget { | |||
| final int selectedId; | |||
| final String type; | |||
| final String titleName; | |||
| final List<SuppliesUsing> currentItems; | |||
| final int currentEditId; | |||
| final String urlSupply; | |||
| HoldInfinityWidget( | |||
| {required this.selectedId, required this.type, required this.titleName, required this.currentItems, required this.currentEditId}); | |||
| {required this.selectedId, required this.urlSupply, required this.titleName, required this.currentItems, required this.currentEditId}); | |||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| @@ -72,13 +72,13 @@ class HoldInfinityWidget extends StatelessWidget { | |||
| ), | |||
| ), | |||
| WidgetSearch( | |||
| type: type, | |||
| urlSupply: urlSupply, | |||
| selectedId: selectedId, | |||
| ), | |||
| Expanded( | |||
| child: InfinityView( | |||
| selectedId: selectedId, | |||
| type: type, | |||
| urlSupply: urlSupply, | |||
| currentItems: currentItems, | |||
| currentEditId: currentEditId, | |||
| )) | |||
| @@ -89,10 +89,10 @@ class HoldInfinityWidget extends StatelessWidget { | |||
| class InfinityView extends StatefulWidget { | |||
| final int selectedId; | |||
| final String type; | |||
| final String urlSupply; | |||
| final List<SuppliesUsing> currentItems; | |||
| final int currentEditId; | |||
| InfinityView({required this.selectedId, required this.type, required this.currentItems, required this.currentEditId}); | |||
| InfinityView({required this.selectedId, required this.urlSupply, required this.currentItems, required this.currentEditId}); | |||
| @override | |||
| _InfinityViewState createState() => _InfinityViewState(); | |||
| } | |||
| @@ -103,7 +103,7 @@ class _InfinityViewState extends State<InfinityView> { | |||
| @override | |||
| void initState() { | |||
| _supplyBloc = BlocProvider.of<SupplyBloc>(context); | |||
| _supplyBloc?.add(DataFetched(type: widget.type, selectedId: widget.selectedId)); | |||
| _supplyBloc?.add(DataFetched(urlSupply: widget.urlSupply, selectedId: widget.selectedId)); | |||
| super.initState(); | |||
| } | |||
| @@ -132,7 +132,7 @@ class _InfinityViewState extends State<InfinityView> { | |||
| itemCount: state.items?.length ?? 0, | |||
| ), | |||
| onRefresh: () async { | |||
| _supplyBloc?.add(OnRefresh(type: widget.type, selectedId: widget.selectedId)); | |||
| _supplyBloc?.add(OnRefresh(urlSupply: widget.urlSupply, selectedId: widget.selectedId)); | |||
| }); | |||
| } | |||
| return Center( | |||
| @@ -4,9 +4,9 @@ import 'package:flutter/material.dart'; | |||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||
| class WidgetSearch extends StatefulWidget { | |||
| final String? type; | |||
| final String urlSupply; | |||
| final int? selectedId; | |||
| WidgetSearch({this.type, this.selectedId}); | |||
| WidgetSearch({required this.urlSupply, this.selectedId}); | |||
| @override | |||
| _WidgetSearchState createState() => _WidgetSearchState(); | |||
| } | |||
| @@ -54,7 +54,7 @@ class _WidgetSearchState extends State<WidgetSearch> { | |||
| BlocProvider.of<SupplyBloc>(_blocContext!).add( | |||
| OnSearch( | |||
| searchString: _searchController.text, | |||
| type: widget.type ?? '', | |||
| urlSupply: widget.urlSupply, | |||
| selectedId: widget.selectedId ?? -1, | |||
| ), | |||
| ); | |||
| @@ -66,7 +66,7 @@ class _WidgetSearchState extends State<WidgetSearch> { | |||
| BlocProvider.of<SupplyBloc>(_blocContext!).add( | |||
| OnSearch( | |||
| searchString: value, | |||
| type: widget.type ?? '', | |||
| urlSupply: widget.urlSupply, | |||
| selectedId: widget.selectedId ?? -1, | |||
| ), | |||
| ); | |||
| @@ -60,7 +60,7 @@ class TaskBloc extends Bloc<TaskEvent, TaskState> { | |||
| yield response.isEmpty | |||
| ? (currentState is TaskSuccess ? currentState.copyWith(hasReachedMax: true) : TaskSuccess(items: [], hasReachedMax: true)) | |||
| : (currentState is TaskSuccess | |||
| ? TaskSuccess(items: (currentState.items ?? []) + response, hasReachedMax: hasReachedMax) | |||
| ? currentState.copyWith(items: (currentState.items ?? []) + response, hasReachedMax: hasReachedMax) | |||
| : TaskSuccess(items: response, hasReachedMax: hasReachedMax)); | |||
| } catch (e) { | |||
| isFetching = false; | |||
| @@ -4,7 +4,7 @@ abstract class TaskState extends Equatable { | |||
| const TaskState(); | |||
| @override | |||
| List<Object> get props => []; | |||
| List<Object?> get props => []; | |||
| } | |||
| class TaskInitial extends TaskState {} | |||
| @@ -30,4 +30,7 @@ class TaskSuccess<Task> extends TaskState { | |||
| hasReachedMax: hasReachedMax ?? this.hasReachedMax, | |||
| ); | |||
| } | |||
| @override | |||
| List<Object?> get props => [items, page, hasReachedMax]; | |||
| } | |||
| @@ -16,6 +16,7 @@ class AssetPNG { | |||
| static const icActionPlant = baseAssets + 'icActionPlant.png'; | |||
| static const icActionSpraying = baseAssets + 'icActionSpraying.png'; | |||
| static const icActionUseWater = baseAssets + 'icActionUseWater.png'; | |||
| static const logoWithSlogan = baseAssets + 'logoWithSlogan.png'; | |||
| } | |||
| class AssetSVG { | |||
| @@ -70,7 +71,8 @@ class AssetSVG { | |||
| static const icVeterinaryMedicine = baseAssets + 'ic_veterinary_medicine.svg'; | |||
| static const icMeadow = baseAssets + 'ic_meadow.svg'; | |||
| static const icFoodProcessing = baseAssets + 'ic_food_processing.svg'; | |||
| static const icFertilizerProduction = baseAssets + 'ic_fertilizer_production.svg'; | |||
| static const icFertilizerProduction = | |||
| baseAssets + 'ic_fertilizer_production.svg'; | |||
| static const icLogout = baseAssets + 'ic_logout.svg'; | |||
| static const icCart = baseAssets + 'ic_cart.svg'; | |||
| static const icCartChecked = baseAssets + 'ic_cart_checked.svg'; | |||
| @@ -98,3 +98,5 @@ const String exception_dio_1019 = | |||
| const String exception_dio_1020 = | |||
| "Người dùng hiện tại không thể truy cập thông tin này"; | |||
| const String exception_dio_1021 = "Số lượng vật tư lớn hơn trong kho"; | |||
| const String exception_dio_9999 = "Đã quá thời gian sửa hoạt động"; | |||
| const String exception_dio_minus_1 = "Số lượng vượt quá giới hạn"; | |||
| @@ -77,10 +77,10 @@ packages: | |||
| dependency: transitive | |||
| description: | |||
| name: build | |||
| sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" | |||
| sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "2.4.1" | |||
| version: "2.3.1" | |||
| build_config: | |||
| dependency: transitive | |||
| description: | |||
| @@ -2,7 +2,7 @@ name: farm_tpf | |||
| description: A new Flutter project. | |||
| publish_to: 'none' | |||
| version: 1.1.16+36 | |||
| version: 1.1.18+38 | |||
| environment: | |||
| sdk: ">=3.0.0 <4.0.0" | |||