Browse Source

refactor: update dynamic API for supplier and change logo

undefined
tranleanhquoc 3 months ago
parent
commit
11ba7a2233
32 changed files with 1255 additions and 263 deletions
  1. +6
    -6
      ios/Runner.xcodeproj/project.pbxproj
  2. +38
    -1
      lib/custom_model/CropPlot.dart
  3. +1
    -1
      lib/custom_model/ErrorCommon.dart
  4. +9
    -0
      lib/custom_model/action_form/ActionUIForm.dart
  5. +72
    -0
      lib/custom_model/action_form/ActivityTypeDTO.dart
  6. +16
    -1
      lib/data/api/app_exception.dart
  7. +4
    -4
      lib/data/api/rest_client.dart
  8. +4
    -5
      lib/data/api/rest_client.g.dart
  9. +18
    -9
      lib/data/repository/repository.dart
  10. +1
    -1
      lib/presentation/custom_widgets/widget_loading.dart
  11. +1
    -2
      lib/presentation/screens/actions/cubit/action_ui_cubit.dart
  12. +3
    -3
      lib/presentation/screens/actions/dung/widget_dung_supply.dart
  13. +3
    -1
      lib/presentation/screens/actions/harvest_process/widget_harvest_process_supply.dart
  14. +3
    -2
      lib/presentation/screens/actions/plant/widget_plant_supply.dart
  15. +221
    -162
      lib/presentation/screens/actions/sc_action.dart
  16. +3
    -2
      lib/presentation/screens/actions/spraying/widget_spraying_supply.dart
  17. +733
    -0
      lib/presentation/screens/actions/supply_widget.dart
  18. +9
    -7
      lib/presentation/screens/login/login_page.dart
  19. +0
    -1
      lib/presentation/screens/notification/sc_notification.dart
  20. +2
    -3
      lib/presentation/screens/plot_detail/sc_plot_action.dart
  21. +2
    -2
      lib/presentation/screens/plot_detail/sc_plot_history.dart
  22. +66
    -17
      lib/presentation/screens/plot_detail/sc_plot_information.dart
  23. +5
    -5
      lib/presentation/screens/resources/bloc/supply_bloc.dart
  24. +6
    -6
      lib/presentation/screens/resources/bloc/supply_event.dart
  25. +12
    -12
      lib/presentation/screens/resources/sc_resource_helper.dart
  26. +4
    -4
      lib/presentation/screens/resources/widget_search.dart
  27. +1
    -1
      lib/presentation/screens/task/bloc/task_bloc.dart
  28. +4
    -1
      lib/presentation/screens/task/bloc/task_state.dart
  29. +3
    -1
      lib/utils/app_images.dart
  30. +2
    -0
      lib/utils/const_string.dart
  31. +2
    -2
      pubspec.lock
  32. +1
    -1
      pubspec.yaml

+ 6
- 6
ios/Runner.xcodeproj/project.pbxproj View File

CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 36;
CURRENT_PROJECT_VERSION = 37;
DEVELOPMENT_TEAM = C3DTD2JH94; DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
MARKETING_VERSION = 1.1.16;
MARKETING_VERSION = 1.1.17;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo; PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 36;
CURRENT_PROJECT_VERSION = 37;
DEVELOPMENT_TEAM = C3DTD2JH94; DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
MARKETING_VERSION = 1.1.16;
MARKETING_VERSION = 1.1.17;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo; PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 36;
CURRENT_PROJECT_VERSION = 37;
DEVELOPMENT_TEAM = C3DTD2JH94; DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Flutter", "$(PROJECT_DIR)/Flutter",
); );
MARKETING_VERSION = 1.1.16;
MARKETING_VERSION = 1.1.17;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo; PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

+ 38
- 1
lib/custom_model/CropPlot.dart View File

int? numberPlants; int? numberPlants;
int? numberCurrentPlants; int? numberCurrentPlants;
String? endOfFarmingDate; String? endOfFarmingDate;
int? numberRemovals;
List<ObjectParameterDataDTOS>? objectParameterDataDTOS;


CropPlot({ CropPlot({
this.tbCropDTO, this.tbCropDTO,
this.numberPlants, this.numberPlants,
this.numberCurrentPlants, this.numberCurrentPlants,
this.endOfFarmingDate, this.endOfFarmingDate,
this.numberRemovals,
this.objectParameterDataDTOS,
}); });


CropPlot.fromJson(Map<String, dynamic> json) { 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) { if (json['activities'] != null) {
activities = <Activities>[]; activities = <Activities>[];
json['activities'].forEach((v) { json['activities'].forEach((v) {
activities?.add(new Activities.fromJson(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']; sowingDate = json['sowingDate'];
plantingDate = json['plantingDate']; plantingDate = json['plantingDate'];
soakSeedsTime = json['soakSeedsTime']; soakSeedsTime = json['soakSeedsTime'];
numberPlants = json['numberPlants']; numberPlants = json['numberPlants'];
numberCurrentPlants = json['numberCurrentPlants']; numberCurrentPlants = json['numberCurrentPlants'];
endOfFarmingDate = json['endOfFarmingDate']; endOfFarmingDate = json['endOfFarmingDate'];
numberRemovals = json['numberRemovals'];
} }


Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
if (this.activities != null) { if (this.activities != null) {
data['activities'] = this.activities?.map((v) => v.toJson()).toList(); 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['sowingDate'] = this.sowingDate;
data['soakSeedsTime'] = this.soakSeedsTime; data['soakSeedsTime'] = this.soakSeedsTime;
data['seedIncubationTime'] = this.seedIncubationTime; data['seedIncubationTime'] = this.seedIncubationTime;
data['numberPlants'] = this.numberPlants; data['numberPlants'] = this.numberPlants;
data['numberCurrentPlants'] = this.numberCurrentPlants; data['numberCurrentPlants'] = this.numberCurrentPlants;
data['endOfFarmingDate'] = this.endOfFarmingDate; 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; return data;
} }
} }

+ 1
- 1
lib/custom_model/ErrorCommon.dart View File

class ErrorCommon { class ErrorCommon {
String? entityName; String? entityName;
String? errorKey; String? errorKey;
int? status;
dynamic status;


ErrorCommon({ ErrorCommon({
this.entityName, this.entityName,

+ 9
- 0
lib/custom_model/action_form/ActionUIForm.dart View File

import 'package:farm_tpf/custom_model/action_form/ActivityTypeDTO.dart';

import 'ActionUIField.dart'; import 'ActionUIField.dart';
import 'ActionUISupply.dart'; import 'ActionUISupply.dart';


class ActionUIForm { class ActionUIForm {
ActivityTypeDTO? tbActivityTypeDTO;
List<ActionUIField>? objectParameterDTOList; List<ActionUIField>? objectParameterDTOList;
List<ActionUISupply>? activityExtendTypeDTOList; List<ActionUISupply>? activityExtendTypeDTOList;


ActionUIForm({this.objectParameterDTOList, this.activityExtendTypeDTOList}); ActionUIForm({this.objectParameterDTOList, this.activityExtendTypeDTOList});


ActionUIForm.fromJson(Map<String, dynamic> json) { ActionUIForm.fromJson(Map<String, dynamic> json) {
if (json['tbActivityTypeDTO'] != null) {
tbActivityTypeDTO = new ActivityTypeDTO.fromJson(json['tbActivityTypeDTO']);
}
if (json['objectParameterDTOList'] != null) { if (json['objectParameterDTOList'] != null) {
objectParameterDTOList = <ActionUIField>[]; objectParameterDTOList = <ActionUIField>[];
json['objectParameterDTOList'].forEach((v) { json['objectParameterDTOList'].forEach((v) {


Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>(); final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.tbActivityTypeDTO != null) {
data['tbActivityTypeDTO'] = this.tbActivityTypeDTO!.toJson();
}
if (this.objectParameterDTOList != null) { if (this.objectParameterDTOList != null) {
data['objectParameterDTOList'] = this.objectParameterDTOList?.map((v) => v.toJson()).toList(); data['objectParameterDTOList'] = this.objectParameterDTOList?.map((v) => v.toJson()).toList();
} }

+ 72
- 0
lib/custom_model/action_form/ActivityTypeDTO.dart View File

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
- 1
lib/data/api/app_exception.dart View File

if (statusCode == 400) { if (statusCode == 400) {
errorDescription = customMessageError ?? exception_dio_400; errorDescription = customMessageError ?? exception_dio_400;
try { 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; var errorCode = ErrorCommon.fromJson(errorMap).errorKey;


switch (errorCode) { switch (errorCode) {
case '-1':
errorDescription = exception_dio_minus_1;
break;
case '1000': case '1000':
errorDescription = exception_dio_1000; errorDescription = exception_dio_1000;
break; break;
case '1021': case '1021':
errorDescription = exception_dio_1021; errorDescription = exception_dio_1021;
break; break;
case '9999':
errorDescription = exception_dio_9999;
break;
default: default:
errorDescription = customMessageError ?? exception_dio_400; errorDescription = customMessageError ?? exception_dio_400;
} }

+ 4
- 4
lib/data/api/rest_client.dart View File

{@Path() int page = 0, @Path() int size = 20, @Path() String query = '', @DioOptions() Options? options}); {@Path() int page = 0, @Path() int size = 20, @Path() String query = '', @DioOptions() Options? options});


//Crop //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}); Future<CropPlot> getCropDetail(@Path() int cropId, {@Path() int page = 0, @Path() int size = 20});


@GET("/api/tb-crops-scan-qrCode/{cropCode}") @GET("/api/tb-crops-scan-qrCode/{cropCode}")
@GET("/api/list-environment-updates-display/{cropId}?page={page}&size={size}") @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}); Future<List<EnvironmentParameter>> getEnvironmentParameters(@Path() int cropId, {@Path() int page = 0, @Path() int size = 20});
//NEW Activity implement //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); 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);
} }

+ 4
- 5
lib/data/api/rest_client.g.dart View File

queryParameters.removeWhere((k, v) => v == null); queryParameters.removeWhere((k, v) => v == null);
final _data = <String, dynamic>{}; final _data = <String, dynamic>{};
var _result = await _dio.request( var _result = await _dio.request(
'/api/tb-crops-detail-for-app/$cropId',
'/api/v2/tb-crops-detail-for-app/$cropId',
queryParameters: queryParameters, queryParameters: queryParameters,
data: _data, data: _data,
); );
newOptions.extra.addAll(_extra); newOptions.extra.addAll(_extra);
newOptions.headers.addAll(<String, dynamic>{}); newOptions.headers.addAll(<String, dynamic>{});
final _result = 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>()); final value = ActionUIForm.fromJson(_result.data ?? Map<String, dynamic>());
return value; return value;
} }


@override @override
getDetailActivityCommon(actionType, activityId) async {
ArgumentError.checkNotNull(actionType, 'actionType');
getDetailActivityCommon(activityId) async {
ArgumentError.checkNotNull(activityId, 'activityId'); ArgumentError.checkNotNull(activityId, 'activityId');
const _extra = <String, dynamic>{}; const _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{}; final queryParameters = <String, dynamic>{};
queryParameters.removeWhere((k, v) => v == null); queryParameters.removeWhere((k, v) => v == null);
final _data = <String, dynamic>{}; 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); queryParameters: queryParameters, data: _data);
final value = RequestActivity.fromJson(_result.data ?? Map<String, dynamic>()); final value = RequestActivity.fromJson(_result.data ?? Map<String, dynamic>());
return value; return value;

+ 18
- 9
lib/data/repository/repository.dart View File

return value; 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)); 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 { Future<List<Device>> getDeviceForActivity() async {
} }


Future<void> createActionCommon(Function(dynamic) onSuccess, Function(dynamic) onError, 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(); var formData = FormData();
if (filePaths != null) { if (filePaths != null) {
filePaths.forEach((f) { filePaths.forEach((f) {


formData.fields.add(MapEntry('tbCommonActivityDTO', activityData)); formData.fields.add(MapEntry('tbCommonActivityDTO', activityData));
try { 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); onSuccess(value.data);
}); });
} on DioError catch (e) { } on DioError catch (e) {
} }


Future<void> updateActionCommon(Function(dynamic) onSuccess, Function(dynamic) onError, 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(); var formData = FormData();
if (filePaths != null) { if (filePaths != null) {
filePaths.forEach((f) { filePaths.forEach((f) {


formData.fields.add(MapEntry('tbCommonActivityDTO', activityData)); formData.fields.add(MapEntry('tbCommonActivityDTO', activityData));
try { 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); onSuccess(value.data);
}); });
} on DioError catch (e) { } on DioError catch (e) {
} }
} }


Future<RequestActivity> detailCommonAction({required int activityId, required String activityType}) async {
Future<RequestActivity> detailCommonAction({required int activityId}) async {
final client = RestClient(dio); final client = RestClient(dio);
return client.getDetailActivityCommon(activityType, activityId);
return client.getDetailActivityCommon(activityId);
} }


// Stamp // Stamp

+ 1
- 1
lib/presentation/custom_widgets/widget_loading.dart View File

child: SizedBox( child: SizedBox(
width: 25, width: 25,
height: 25, height: 25,
child: Image.asset(AppAssets.logo)),
child: Image.asset(AppAssets.logoWithSlogan)),
), ),
Container( Container(
alignment: Alignment.center, alignment: Alignment.center,

+ 1
- 2
lib/presentation/screens/actions/cubit/action_ui_cubit.dart View File

Future<void> getActionUIForm({ Future<void> getActionUIForm({
required bool isEdit, required bool isEdit,
required int actionId, required int actionId,
required String actionType,
required int activityId, required int activityId,
}) async { }) async {
try { try {
var actionUIForm = await repository.getActionUIForm(idAction: actionId); var actionUIForm = await repository.getActionUIForm(idAction: actionId);
if (isEdit) { if (isEdit) {
try { try {
actionDetail = await repository.detailCommonAction(activityId: activityId, activityType: actionType);
actionDetail = await repository.detailCommonAction(activityId: activityId);
print(actionDetail); print(actionDetail);
} catch (e) { } catch (e) {
print(e); print(e);

+ 3
- 3
lib/presentation/screens/actions/dung/widget_dung_supply.dart View File

import 'package:farm_tpf/presentation/screens/actions/resource_device_activity/sc_device_activity.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/actions/state_management_helper/change_supply.dart';
import 'package:farm_tpf/presentation/screens/resources/sc_resource_helper.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_string.dart';
import 'package:farm_tpf/utils/const_style.dart'; import 'package:farm_tpf/utils/const_style.dart';
import 'package:farm_tpf/utils/validators.dart'; import 'package:farm_tpf/utils/validators.dart';
class WidgetDungSupply extends StatefulWidget { class WidgetDungSupply extends StatefulWidget {
final List<SuppliesUsing> currentItems; final List<SuppliesUsing> currentItems;
final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; 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 @override
_WidgetDungSupplyState createState() => _WidgetDungSupplyState(); _WidgetDungSupplyState createState() => _WidgetDungSupplyState();
} }
.push(MaterialPageRoute( .push(MaterialPageRoute(
builder: (_) => ResourceHelperScreen( builder: (_) => ResourceHelperScreen(
titleName: "Phân bón", titleName: "Phân bón",
type: ConstCommon.supplyTypeDung,
urlSupply: widget.urlSupply,
selectedId: changeSelectedSupply.selectedSupplyId ?? -1, selectedId: changeSelectedSupply.selectedSupplyId ?? -1,
currentItems: changeSupplyUsing.currentItems ?? [], currentItems: changeSupplyUsing.currentItems ?? [],
currentEditId: ((currentIndexEdit ?? 0) >= 0) currentEditId: ((currentIndexEdit ?? 0) >= 0)

+ 3
- 1
lib/presentation/screens/actions/harvest_process/widget_harvest_process_supply.dart View File

class WidgetHarvestProcessSupply extends StatefulWidget { class WidgetHarvestProcessSupply extends StatefulWidget {
final List<SuppliesUsing>? currentItems; final List<SuppliesUsing>? currentItems;
final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies;
final String urlSupply;
WidgetHarvestProcessSupply({ WidgetHarvestProcessSupply({
required this.urlSupply,
this.currentItems, this.currentItems,
required this.onChangeSupplies, required this.onChangeSupplies,
}); });
.push(MaterialPageRoute( .push(MaterialPageRoute(
builder: (_) => ResourceHelperScreen( builder: (_) => ResourceHelperScreen(
titleName: "Hoá chất xử lý", titleName: "Hoá chất xử lý",
type: ConstCommon.supplyTypeAll,
urlSupply: widget.urlSupply,
selectedId: changeSelectedSupply.selectedSupplyId ?? -1, selectedId: changeSelectedSupply.selectedSupplyId ?? -1,
currentItems: changeSupplyUsing.currentItems ?? [], currentItems: changeSupplyUsing.currentItems ?? [],
currentEditId: ((currentIndexEdit ?? -1) >= 0) currentEditId: ((currentIndexEdit ?? -1) >= 0)

+ 3
- 2
lib/presentation/screens/actions/plant/widget_plant_supply.dart View File

class WidgetPlantSupply extends StatefulWidget { class WidgetPlantSupply extends StatefulWidget {
final List<SuppliesUsing>? currentItems; final List<SuppliesUsing>? currentItems;
final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; 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 @override
_WidgetPlantSupplyState createState() => _WidgetPlantSupplyState(); _WidgetPlantSupplyState createState() => _WidgetPlantSupplyState();
} }
.push(MaterialPageRoute( .push(MaterialPageRoute(
builder: (_) => ResourceHelperScreen( builder: (_) => ResourceHelperScreen(
titleName: "Hoá chất xử lý", titleName: "Hoá chất xử lý",
type: ConstCommon.supplyTypeAll,
urlSupply: widget.urlSupply,
selectedId: changeSelectedSupply.selectedSupplyId ?? -1, selectedId: changeSelectedSupply.selectedSupplyId ?? -1,
currentItems: changeSupplyUsing.currentItems ?? [], currentItems: changeSupplyUsing.currentItems ?? [],
currentEditId: ((currentIndexEdit ?? -1) >= 0) currentEditId: ((currentIndexEdit ?? -1) >= 0)

+ 221
- 162
lib/presentation/screens/actions/sc_action.dart View File

import 'package:farm_tpf/presentation/custom_widgets/widget_text_form_field.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/custom_widgets/widget_utils.dart';
import 'package:farm_tpf/presentation/screens/actions/cubit/action_ui_cubit.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/const_string.dart';
import 'package:farm_tpf/utils/pref.dart'; import 'package:farm_tpf/utils/pref.dart';
import 'package:farm_tpf/utils/validators.dart'; import 'package:farm_tpf/utils/validators.dart';
import 'controller/ChangeFieldInForm.dart'; import 'controller/ChangeFieldInForm.dart';
import 'controller/ChangeSupplyUsing.dart'; import 'controller/ChangeSupplyUsing.dart';
import 'controller/ChangeWorker.dart'; import 'controller/ChangeWorker.dart';
import 'dung/widget_dung_supply.dart';
import 'nursery/widget_worker.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_dropdown_controller.dart';
import 'state_management_helper/change_file_controller.dart'; import 'state_management_helper/change_file_controller.dart';
import 'util_action.dart'; import 'util_action.dart';
final bool isEdit; final bool isEdit;
final int cropId; final int cropId;
final int idAction; final int idAction;
final String activityType;
final String title; final String title;
final int activityId; final int activityId;
final DateTime? executeDate;
ActionScreen({ ActionScreen({
required this.isEdit, required this.isEdit,
required this.cropId, required this.cropId,
required this.idAction, required this.idAction,
required this.title, required this.title,
required this.activityType,
required this.activityId, required this.activityId,
this.executeDate,
}); });


@override @override
super.initState(); super.initState();
getSharedPrefs(); getSharedPrefs();
changeFileController.initValue(); changeFileController.initValue();
if (widget.executeDate != null) {
executeTime = widget.executeDate!;
}
} }


_submitForm() async { _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(); _validateInputs();
}
break;
default:
});
} else {
_validateInputs(); _validateInputs();
break;
}
} else {
_validateInputs();
} }
} }


..tbActivityTypeId = widget.idAction ..tbActivityTypeId = widget.idAction
..tbCropId = widget.cropId; ..tbCropId = widget.cropId;
if ((_actionUIForm.activityExtendTypeDTOList ?? []).isNotEmpty) { if ((_actionUIForm.activityExtendTypeDTOList ?? []).isNotEmpty) {
_requestActivity..externalTable = _actionUIForm?.activityExtendTypeDTOList?.first?.externalTable ?? '';
_requestActivity
..externalTable = _actionUIForm
?.activityExtendTypeDTOList?.first?.externalTable ??
'';
} }


filePaths = Get.find<ChangeFileController>().newFiles ?? []; filePaths = Get.find<ChangeFileController>().newFiles ?? [];
_requestActivity.tbObjectUpdateDTOList?.forEach((element) { _requestActivity.tbObjectUpdateDTOList?.forEach((element) {
print(valueObjects[element.tbObjectParameterId.toString()]); print(valueObjects[element.tbObjectParameterId.toString()]);
var updateValue = ''; 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 { } else {
updateValue = element.index ?? ''; updateValue = element.index ?? '';
} }
_requestActivity.tbObjectUpdateDTOList = _objectPrameters; _requestActivity.tbObjectUpdateDTOList = _objectPrameters;
} }


final tbActivityType = _actionUIForm.tbActivityTypeDTO;
final isUseSupply = tbActivityType?.isUseSupply ?? false;
final isNursery =
tbActivityType?.isStart == true && tbActivityType?.position == 1;
//CHECK NURSERY //CHECK NURSERY
if (widget.activityType == 'ACTIVE_TYPE_NURSERY') {
if (isNursery) {
_requestActivity.tbNurseryDetailsDTOList = _nurseryDetails; _requestActivity.tbNurseryDetailsDTOList = _nurseryDetails;
} else if ( } else if (
// widget.activityType == 'ACTIVE_TYPE_PLANTING' || // widget.activityType == 'ACTIVE_TYPE_PLANTING' ||
widget.activityType == 'ACTIVE_TYPE_FERTILIZE' ||
widget.activityType == 'ACTIVE_TYPE_SPRAYING_PESTICIDES') {
isUseSupply) {
_requestActivity.tbSuppliesUsingDetailsDTOs = _supplyUsings; _requestActivity.tbSuppliesUsingDetailsDTOs = _supplyUsings;
} }
//delete images //delete images
_requestActivity.deletedImages = Get.find<ChangeFileController>().deleteFiles;
_requestActivity.deletedImages =
Get.find<ChangeFileController>().deleteFiles;
//convert data to json //convert data to json
var activityCommonData = jsonEncode(_requestActivity.toJson()).toString();
var activityCommonData =
jsonEncode(_requestActivity.toJson()).toString();
print(activityCommonData); print(activityCommonData);


if (widget.activityId < 0) { if (widget.activityId < 0) {
}, (error) { }, (error) {
LoadingDialog.hideLoadingDialog(context); LoadingDialog.hideLoadingDialog(context);
Utils.showSnackBarError(message: AppException.handleError(error)); Utils.showSnackBarError(message: AppException.handleError(error));
}, activityType: widget.activityType, activityData: activityCommonData, filePaths: filePaths);
}, activityData: activityCommonData, filePaths: filePaths);
} else { } else {
//UPDATE //UPDATE
_repository.updateActionCommon((data) { _repository.updateActionCommon((data) {
}, (error) { }, (error) {
LoadingDialog.hideLoadingDialog(context); LoadingDialog.hideLoadingDialog(context);
Utils.showSnackBarError(message: AppException.handleError(error)); Utils.showSnackBarError(message: AppException.handleError(error));
}, activityType: widget.activityType, activityData: activityCommonData, filePaths: filePaths);
}, activityData: activityCommonData, filePaths: filePaths);
} }


//ADD NEW //ADD NEW
return WidgetFieldDateTimePicker( return WidgetFieldDateTimePicker(
initDateTime: executeTime, initDateTime: executeTime,
onUpdateDateTime: (selectedDate) { onUpdateDateTime: (selectedDate) {
_requestActivity.executeDate = selectedDate.convertLocalDateTimeToStringUtcDateTime();
_requestActivity.executeDate =
selectedDate.convertLocalDateTimeToStringUtcDateTime();
}); });
} }


// GENERATE DYNAMIC FORM // GENERATE DYNAMIC FORM
// //
Widget groupName(String name) { Widget groupName(String name) {
if (_previousGroupFieldName == name || !Validators.stringNotNullOrEmpty(name)) {
if (_previousGroupFieldName == name ||
!Validators.stringNotNullOrEmpty(name)) {
return SizedBox(); return SizedBox();
} else { } else {
_previousGroupFieldName = name ?? ''; _previousGroupFieldName = name ?? '';
TextFormField( TextFormField(
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
decoration: InputDecoration( 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()], controller: textFieldControllers[field.id.toString()],
onSaved: (newValue) {}, onSaved: (newValue) {},
validator: ((field.isMandatory ?? false) ?? false) validator: ((field.isMandatory ?? false) ?? false)
? (String? value) { ? (String? value) {
return Validators.validateNotNullOrEmpty( return Validators.validateNotNullOrEmpty(
value ?? '', value ?? '',
'Vui lòng nhập ${field.description}',
'Vui lòng nhập ${field.name}',
); );
} }
: null, : null,
children: [ children: [
groupName(field.groupName ?? ''), groupName(field.groupName ?? ''),
WidgetTextFormFieldNumber( 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) {}, onSaved: (newValue) {},
validator: ((field.isMandatory ?? false) ?? false) validator: ((field.isMandatory ?? false) ?? false)
? (String? value) { ? (String? value) {
return Validators.validNumberOrEmpty( return Validators.validNumberOrEmpty(
value ?? '', value ?? '',
'Vui lòng nhập ${field.description}',
'Vui lòng nhập ${field.name}',
); );
} }
: null, : null,
children: [ children: [
groupName(field.groupName ?? ''), groupName(field.groupName ?? ''),
TextFieldAreaWidget( 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) {}, onSaved: (newValue) {},
validator: (field.isMandatory ?? false) validator: (field.isMandatory ?? false)
? (String? value) { ? (String? value) {
return Validators.validateNotNullOrEmpty( return Validators.validateNotNullOrEmpty(
value ?? '', value ?? '',
'Vui lòng nhập ${field.description}',
'Vui lòng nhập ${field.name}',
); );
} }
: null, : null,
children: [ children: [
groupName(field.groupName ?? ''), groupName(field.groupName ?? ''),
DropdownSupplyWidget( DropdownSupplyWidget(
titleName: field.description ?? '',
titleName: field.name ?? '',
tbSupply: field.tbActivityExtendTypeExternalTable ?? '', tbSupply: field.tbActivityExtendTypeExternalTable ?? '',
tag: field.name ?? '', tag: field.name ?? '',
value: field.description,
hint: '${field.description} ${(field.isMandatory ?? false) ? '*' : ''}',
value: field.name,
hint:
'${field.name} ${(field.isMandatory ?? false) ? '*' : ''}',
condition: field.tbActivityExtendTypeCondition ?? '', condition: field.tbActivityExtendTypeCondition ?? '',
invalidMessage: '', invalidMessage: '',
onPressed: (commonData) { onPressed: (commonData) {
valueObjects[field.id.toString()] = commonData.id.toString();
valueObjects[field.id.toString()] =
commonData.id.toString();
}, },
), ),
], ],
condition: field.tbActivityExtendTypeCondition ?? '', condition: field.tbActivityExtendTypeCondition ?? '',
supply: field.tbActivityExtendTypeExternalTable ?? '', supply: field.tbActivityExtendTypeExternalTable ?? '',
onPressed: (commonData) { onPressed: (commonData) {
valueObjects[field.id.toString()] = commonData.id.toString();
valueObjects[field.id.toString()] =
commonData.id.toString();
}, },
), ),
], ],
FieldDateWidget( FieldDateWidget(
tag: field.name ?? '', tag: field.name ?? '',
isValidated: isValidated, isValidated: isValidated,
value: field.description,
hint: '${field.description} ${(field.isMandatory ?? false) ? '*' : ''}',
value: field.name,
hint:
'${field.name} ${(field.isMandatory ?? false) ? '*' : ''}',
onPressed: (selectedDate) { onPressed: (selectedDate) {
valueObjects[field.id.toString()] = selectedDate.convertLocalDateTimeToStringUtcDateTime();
valueObjects[field.id.toString()] = selectedDate
.convertLocalDateTimeToStringUtcDateTime();
}, },
validator: (field.isMandatory ?? false) validator: (field.isMandatory ?? false)
? (String? value) { ? (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, : null,
), ),
// GENERATE SUPPLY // 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) { void showDataWhenEdit(BuildContext context) {
} }


SchedulerBinding.instance.addPostFrameCallback((_) { 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 //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 //list nursery
Get.find<ChangeWorker>().changeInitList(_requestActivity.tbNurseryDetailsDTOList ?? []);
Get.find<ChangeWorker>()
.changeInitList(_requestActivity.tbNurseryDetailsDTOList ?? []);
} }
}); });


if (_requestActivity.tbObjectUpdateDTOList != null) { if (_requestActivity.tbObjectUpdateDTOList != null) {
print(textFieldControllers.keys.toList()); print(textFieldControllers.keys.toList());
_requestActivity.tbObjectUpdateDTOList?.forEach((element) { _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((_) { 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((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
textFieldControllers[element.tbObjectParameterId.toString()]?.text = element.index?.formatStringToStringDecimal() ?? '';
textFieldControllers[element.tbObjectParameterId.toString()]?.text =
element.index?.formatStringToStringDecimal() ?? '';
}); });
} else { } else {
SchedulerBinding.instance.addPostFrameCallback((_) { SchedulerBinding.instance.addPostFrameCallback((_) {
if (element.tbObjectParameterDTO?.tbControlTypeName == 'dropdown' || if (element.tbObjectParameterDTO?.tbControlTypeName == 'dropdown' ||
element.tbObjectParameterDTO?.tbControlTypeName?.toLowerCase() == 'radiobutton') {
element.tbObjectParameterDTO?.tbControlTypeName
?.toLowerCase() ==
'radiobutton') {
var dropdownValueName = ''; 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')) { if (dropdownData.id == int.tryParse(element.index ?? '-1')) {
dropdownValueName = dropdownData.name ?? ''; dropdownValueName = dropdownData.name ?? '';
} }
var commonData = CommonData() var commonData = CommonData()
..id = int.tryParse(element.index ?? '-1') ..id = int.tryParse(element.index ?? '-1')
..name = dropdownValueName; ..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(),
); );
} }
}); });
action: InkWell( action: InkWell(
child: Text( child: Text(
'Lưu', 'Lưu',
style: TextStyle(color: Colors.red, fontWeight: FontWeight.normal),
style: TextStyle(
color: Colors.red, fontWeight: FontWeight.normal),
), ),
onTap: () { onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context); FocusScopeNode currentFocus = FocusScope.of(context);
body: MultiBlocProvider( body: MultiBlocProvider(
providers: [ providers: [
BlocProvider<ActionUiCubit>( 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>( BlocProvider<MediaHelperBloc>(
create: (context) => MediaHelperBloc()..add(ChangeListMedia(items: [])),
create: (context) =>
MediaHelperBloc()..add(ChangeListMedia(items: [])),
) )
], ],
child: Form( child: Form(
child: LoadingListPage(), child: LoadingListPage(),
); );
} else if (state is ActionUiSuccess) { } else if (state is ActionUiSuccess) {
_actionUIForm = state.actionUIForm ?? ActionUIForm();
_requestActivity = state.activityDetail ?? RequestActivity();
_actionUIForm =
state.actionUIForm ?? ActionUIForm();
_requestActivity =
state.activityDetail ?? RequestActivity();


//CREATE UI //CREATE UI
_actionUIForm.objectParameterDTOList?.forEach((element) {
_actionUIForm.objectParameterDTOList
?.forEach((element) {
//generate controller //generate controller
if (element.tbControlTypeName == 'text' || if (element.tbControlTypeName == 'text' ||
element.tbControlTypeName == 'number' || element.tbControlTypeName == 'number' ||
element.tbControlTypeName == 'textarea') { 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 // generate value each parameter
valueObjects.putIfAbsent(element.id.toString(), () => '');
valueObjects.putIfAbsent(
element.id.toString(), () => '');
}); });
//SHOW EDIT DATA //SHOW EDIT DATA
if (widget.isEdit) { if (widget.isEdit) {
width: double.infinity, width: double.infinity,
child: Text( child: Text(
"Ngày thực hiện *", "Ngày thực hiện *",
style: TextStyle(color: Colors.black54, fontSize: 13.0),
style: TextStyle(
color: Colors.black54,
fontSize: 13.0),
), ),
), ),
_btnExecuteTimePicker(), _btnExecuteTimePicker(),
SizedBox( SizedBox(
height: 8.0, height: 8.0,
), ),
generateField(_actionUIForm.objectParameterDTOList ?? []),
generateField(_actionUIForm
.objectParameterDTOList ??
[]),
_executeByField(), _executeByField(),
SizedBox( SizedBox(
height: 8.0, height: 8.0,
], ],
), ),
), ),
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( Container(
width: double.infinity, width: double.infinity,
height: 16, height: 16,
color: Colors.grey[200], color: Colors.grey[200],
), ),
BlocBuilder<MediaHelperBloc, MediaHelperState>(builder: (context, state) {
BlocBuilder<MediaHelperBloc,
MediaHelperState>(
builder: (context, state) {
if (state is MediaHelperSuccess) { if (state is MediaHelperSuccess) {
return WidgetMediaPicker( return WidgetMediaPicker(
currentItems: state.items, currentItems: state.items,
onChangeFiles: (newPathFiles, deletePathFiles) async {
Get.find<ChangeFileController>().change(newPathFiles, deletePathFiles);
onChangeFiles: (newPathFiles,
deletePathFiles) async {
Get.find<ChangeFileController>()
.change(newPathFiles,
deletePathFiles);
}); });
} else { } else {
return Center(child: CircularProgressIndicator());
return Center(
child: CircularProgressIndicator());
} }
}), }),
Padding( Padding(
child: ButtonWidget( child: ButtonWidget(
title: 'CẬP NHẬT', title: 'CẬP NHẬT',
onPressed: () { onPressed: () {
FocusScopeNode currentFocus = FocusScope.of(context);
FocusScopeNode currentFocus =
FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) { if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus(); currentFocus.unfocus();
} }

+ 3
- 2
lib/presentation/screens/actions/spraying/widget_spraying_supply.dart View File

class WidgetSprayingSupply extends StatefulWidget { class WidgetSprayingSupply extends StatefulWidget {
final List<SuppliesUsing>? currentItems; final List<SuppliesUsing>? currentItems;
final Function(List<SuppliesUsing> supplyChanges) onChangeSupplies; 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 @override
_WidgetSprayingSupplyState createState() => _WidgetSprayingSupplyState(); _WidgetSprayingSupplyState createState() => _WidgetSprayingSupplyState();
} }
.push(MaterialPageRoute( .push(MaterialPageRoute(
builder: (_) => ResourceHelperScreen( builder: (_) => ResourceHelperScreen(
titleName: "Thuốc BVTV", titleName: "Thuốc BVTV",
type: ConstCommon.supplyTypeProtectPlant,
urlSupply: widget.urlSupply,
selectedId: changeSelectedSupply.selectedSupplyId ?? -1, selectedId: changeSelectedSupply.selectedSupplyId ?? -1,
currentItems: changeSupplyUsing.currentItems ?? [], currentItems: changeSupplyUsing.currentItems ?? [],
currentEditId: ((currentIndexEdit ?? -1) >= 0) currentEditId: ((currentIndexEdit ?? -1) >= 0)

+ 733
- 0
lib/presentation/screens/actions/supply_widget.dart View File

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,
),
],
);
}
}

+ 9
- 7
lib/presentation/screens/login/login_page.dart View File

@override @override
void initState() { void initState() {
super.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(); prepareData();
} }


right: 40.w, right: 40.w,
left: 40.w, left: 40.w,
child: Image.asset( child: Image.asset(
AssetPNG.logo,
AssetPNG.logoWithSlogan,
height: 150, height: 150,
), ),
), ),
ValueListenableBuilder<String>( ValueListenableBuilder<String>(
valueListenable: loginErrorMessage, valueListenable: loginErrorMessage,
builder: (context, errorMessage, _) { builder: (context, errorMessage, _) {
if (Validators.stringNotNullOrEmpty(errorMessage)) {
if (Validators.stringNotNullOrEmpty(
errorMessage)) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.semantic7, color: AppColors.semantic7,
margin: const EdgeInsets.only( margin: const EdgeInsets.only(
top: 16, top: 16,
), ),
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
padding: const EdgeInsets.symmetric(
vertical: 4, horizontal: 8),
child: Row( child: Row(
children: [ children: [
SvgPicture.asset(AssetSVG.icWarning), SvgPicture.asset(AssetSVG.icWarning),

+ 0
- 1
lib/presentation/screens/notification/sc_notification.dart View File

isEdit: true, isEdit: true,
cropId: item.tbCropId ?? -1, cropId: item.tbCropId ?? -1,
activityId: item.externalId ?? -1, activityId: item.externalId ?? -1,
activityType: item.activityTypeName ?? '',
title: 'ActionScreen', title: 'ActionScreen',
idAction: item.activityTypeId ?? -1, idAction: item.activityTypeId ?? -1,
)); ));

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

cropId: widget.cropId ?? -1, cropId: widget.cropId ?? -1,
idAction: actionType.id ?? -1, idAction: actionType.id ?? -1,
title: actionType.description ?? '', title: actionType.description ?? '',
activityType: actionType.name ?? '',
activityId: -1, activityId: -1,
isEdit: false, isEdit: false,
)); ));
color: Colors.grey[300], color: Colors.grey[300],
), ),
errorWidget: (context, url, error) => Image.asset( errorWidget: (context, url, error) => Image.asset(
AppAssets.logo,
AppAssets.logoWithSlogan,
), ),
), ),
), ),
child: Align( child: Align(
alignment: Alignment.center, alignment: Alignment.center,
child: AutoSizeText( child: AutoSizeText(
actionType.description ?? '',
actionType.name ?? '',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,

+ 2
- 2
lib/presentation/screens/plot_detail/sc_plot_history.dart View File

return GestureDetector( return GestureDetector(
child: WidgetRowPlotInfo( child: WidgetRowPlotInfo(
color: index % 2 == 0 ? AppColors.DEFAULT.withOpacity(0.3) : AppColors.DEFAULT.withOpacity(0.1), color: index % 2 == 0 ? AppColors.DEFAULT.withOpacity(0.3) : AppColors.DEFAULT.withOpacity(0.1),
name: '${item.activityTypeDescription ?? ''}',
name: '${item.activityTypeName ?? ''}',
value: item.executeDate?.fromUtcToLocal() ?? ''), value: item.executeDate?.fromUtcToLocal() ?? ''),
onTap: () { onTap: () {
if (item.activityTypeName == 'ACTIVE_TYPE_UPDATE_ENV') { if (item.activityTypeName == 'ACTIVE_TYPE_UPDATE_ENV') {
isEdit: true, isEdit: true,
cropId: item.cropId ?? -1, cropId: item.cropId ?? -1,
activityId: item.id ?? -1, activityId: item.id ?? -1,
activityType: item.activityTypeName ?? '',
title: 'ActionScreen', title: 'ActionScreen',
idAction: item.activityTypeId ?? -1, idAction: item.activityTypeId ?? -1,
executeDate: item.executeDate?.convertStringServerDateTimeToLocalDateTime(),
)); ));
} }
}); });

+ 66
- 17
lib/presentation/screens/plot_detail/sc_plot_information.dart View File

_PlotInformationScreenState createState() => _PlotInformationScreenState(); _PlotInformationScreenState createState() => _PlotInformationScreenState();
} }


class _PlotInformationScreenState extends State<PlotInformationScreen> with AutomaticKeepAliveClientMixin {
class _PlotInformationScreenState extends State<PlotInformationScreen>
with AutomaticKeepAliveClientMixin {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
GlobalKey<FormState> _formKey = GlobalKey(); GlobalKey<FormState> _formKey = GlobalKey();
TextEditingController _descriptionController = TextEditingController(); TextEditingController _descriptionController = TextEditingController();
default: default:
statusCrop = plot_status_unknown; statusCrop = plot_status_unknown;
} }
_descriptionController.text = _crop.description == null ? "" : _crop.description.toString();
_descriptionController.text =
_crop.description == null ? "" : _crop.description.toString();
if (_crop.tbDetailUsers != null) { if (_crop.tbDetailUsers != null) {
for (var i = 0; i < (_crop.tbDetailUsers ?? []).length; i++) { for (var i = 0; i < (_crop.tbDetailUsers ?? []).length; i++) {
if (i == 0) { if (i == 0) {
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
controller: _descriptionController, controller: _descriptionController,
decoration: InputDecoration( 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) { onSaved: (newValue) {
_crop.description = newValue; _crop.description = newValue;
}, },
body: KeyboardDismisser( body: KeyboardDismisser(
child: StreamBuilder( child: StreamBuilder(
stream: getPlotInfoBloc.actions, stream: getPlotInfoBloc.actions,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
builder:
(BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
return Form( return Form(
key: _formKey, key: _formKey,
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
WidgetRowPlotInfo( 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( WidgetRowPlotInfo(
color: AppColors.DEFAULT.withOpacity(0.1), color: AppColors.DEFAULT.withOpacity(0.1),
name: 'Nhà màng', name: 'Nhà màng',
value: '${cropPlot.tbCropDTO?.netHouseName ?? '--'}'),
value:
'${cropPlot.tbCropDTO?.netHouseName ?? '--'}'),
WidgetRowPlotInfo( 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( WidgetRowPlotInfo(
color: AppColors.DEFAULT.withOpacity(0.1), 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( 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( WidgetRowPlotInfo(
color: AppColors.DEFAULT.withOpacity(0.1), 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', 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( WidgetRowPlotInfo(
color: AppColors.DEFAULT.withOpacity(0.3), color: AppColors.DEFAULT.withOpacity(0.3),
name: 'Ngày kết thúc canh tác', 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( WidgetRowPlotInfo(
color: AppColors.DEFAULT.withOpacity(0.3), color: AppColors.DEFAULT.withOpacity(0.3),
name: 'Diện tích (m\u00B2)', 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( SizedBox(
height: 8, height: 8,
), ),
onPressed: controller.isChanged == false onPressed: controller.isChanged == false
? () {} ? () {}
: () { : () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
FocusScopeNode currentFocus =
FocusScope.of(context);
if (!currentFocus
.hasPrimaryFocus) {
currentFocus.unfocus(); currentFocus.unfocus();
} }
_validateInputs(); _validateInputs();

+ 5
- 5
lib/presentation/screens/resources/bloc/supply_bloc.dart View File

import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:farm_tpf/custom_model/Supply.dart'; import 'package:farm_tpf/custom_model/Supply.dart';
import 'package:farm_tpf/data/repository/repository.dart'; import 'package:farm_tpf/data/repository/repository.dart';
import 'package:meta/meta.dart';


part 'supply_event.dart'; part 'supply_event.dart';
part 'supply_state.dart'; part 'supply_state.dart';
) async* { ) async* {
if (event is DataFetched) { if (event is DataFetched) {
try { try {
final response = await repository.getSupplies(event.type);
final response = await repository.getSupplies(event.urlSupply);
List<Supply> supplies = response.map((supply) { List<Supply> supplies = response.map((supply) {
if (supply.id == event.selectedId) { if (supply.id == event.selectedId) {
supply.isSelected = true; supply.isSelected = true;
return supply; return supply;
}).toList(); }).toList();
yield SupplySuccess(items: supplies); yield SupplySuccess(items: supplies);
} catch (_) {
} catch (e) {
yield SupplyFailure(); yield SupplyFailure();
} }
} else if (event is OnRefresh) { } else if (event is OnRefresh) {
try { try {
final response = await repository.getSupplies(event.type);
final response = await repository.getSupplies(event.urlSupply);
List<Supply> supplies = response.map((supply) { List<Supply> supplies = response.map((supply) {
if (supply.id == event.selectedId) { if (supply.id == event.selectedId) {
supply.isSelected = true; supply.isSelected = true;
} }
} else if (event is OnSearch) { } else if (event is OnSearch) {
try { 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) { List<Supply> supplies = response.map((supply) {
if (supply.id == event.selectedId) { if (supply.id == event.selectedId) {
supply.isSelected = true; supply.isSelected = true;

+ 6
- 6
lib/presentation/screens/resources/bloc/supply_event.dart View File



class DataFetched extends SupplyEvent { class DataFetched extends SupplyEvent {
final int? selectedId; 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 { class OnRefresh extends SupplyEvent {
final int? selectedId; 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 { class OnSearch extends SupplyEvent {
final String? searchString; final String? searchString;
final int? selectedId; final int? selectedId;
final String? type;
OnSearch({this.searchString, this.selectedId, this.type});
final String urlSupply;
OnSearch({this.searchString, this.selectedId, required this.urlSupply});
} }

+ 12
- 12
lib/presentation/screens/resources/sc_resource_helper.dart View File

import 'package:farm_tpf/utils/formatter.dart'; import 'package:farm_tpf/utils/formatter.dart';


class ResourceHelperScreen extends StatefulWidget { class ResourceHelperScreen extends StatefulWidget {
final String type;
final int selectedId; final int selectedId;
final String titleName; final String titleName;
final List<SuppliesUsing> currentItems; final List<SuppliesUsing> currentItems;
final int currentEditId; final int currentEditId;
final String urlSupply;
ResourceHelperScreen({ ResourceHelperScreen({
required this.type,
required this.selectedId, required this.selectedId,
required this.titleName, required this.titleName,
required this.currentItems, required this.currentItems,
required this.currentEditId, required this.currentEditId,
required this.urlSupply,
}); });
@override @override
_ResourceHelperScreenState createState() => _ResourceHelperScreenState(); _ResourceHelperScreenState createState() => _ResourceHelperScreenState();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( 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( child: HoldInfinityWidget(
selectedId: widget.selectedId, selectedId: widget.selectedId,
type: widget.type,
urlSupply: widget.urlSupply,
titleName: widget.titleName, titleName: widget.titleName,
currentItems: widget.currentItems, currentItems: widget.currentItems,
currentEditId: widget.currentEditId, currentEditId: widget.currentEditId,


class HoldInfinityWidget extends StatelessWidget { class HoldInfinityWidget extends StatelessWidget {
final int selectedId; final int selectedId;
final String type;
final String titleName; final String titleName;
final List<SuppliesUsing> currentItems; final List<SuppliesUsing> currentItems;
final int currentEditId; final int currentEditId;
final String urlSupply;
HoldInfinityWidget( 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>(); final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
), ),
), ),
WidgetSearch( WidgetSearch(
type: type,
urlSupply: urlSupply,
selectedId: selectedId, selectedId: selectedId,
), ),
Expanded( Expanded(
child: InfinityView( child: InfinityView(
selectedId: selectedId, selectedId: selectedId,
type: type,
urlSupply: urlSupply,
currentItems: currentItems, currentItems: currentItems,
currentEditId: currentEditId, currentEditId: currentEditId,
)) ))


class InfinityView extends StatefulWidget { class InfinityView extends StatefulWidget {
final int selectedId; final int selectedId;
final String type;
final String urlSupply;
final List<SuppliesUsing> currentItems; final List<SuppliesUsing> currentItems;
final int currentEditId; 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 @override
_InfinityViewState createState() => _InfinityViewState(); _InfinityViewState createState() => _InfinityViewState();
} }
@override @override
void initState() { void initState() {
_supplyBloc = BlocProvider.of<SupplyBloc>(context); _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(); super.initState();
} }


itemCount: state.items?.length ?? 0, itemCount: state.items?.length ?? 0,
), ),
onRefresh: () async { onRefresh: () async {
_supplyBloc?.add(OnRefresh(type: widget.type, selectedId: widget.selectedId));
_supplyBloc?.add(OnRefresh(urlSupply: widget.urlSupply, selectedId: widget.selectedId));
}); });
} }
return Center( return Center(

+ 4
- 4
lib/presentation/screens/resources/widget_search.dart View File

import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';


class WidgetSearch extends StatefulWidget { class WidgetSearch extends StatefulWidget {
final String? type;
final String urlSupply;
final int? selectedId; final int? selectedId;
WidgetSearch({this.type, this.selectedId});
WidgetSearch({required this.urlSupply, this.selectedId});
@override @override
_WidgetSearchState createState() => _WidgetSearchState(); _WidgetSearchState createState() => _WidgetSearchState();
} }
BlocProvider.of<SupplyBloc>(_blocContext!).add( BlocProvider.of<SupplyBloc>(_blocContext!).add(
OnSearch( OnSearch(
searchString: _searchController.text, searchString: _searchController.text,
type: widget.type ?? '',
urlSupply: widget.urlSupply,
selectedId: widget.selectedId ?? -1, selectedId: widget.selectedId ?? -1,
), ),
); );
BlocProvider.of<SupplyBloc>(_blocContext!).add( BlocProvider.of<SupplyBloc>(_blocContext!).add(
OnSearch( OnSearch(
searchString: value, searchString: value,
type: widget.type ?? '',
urlSupply: widget.urlSupply,
selectedId: widget.selectedId ?? -1, selectedId: widget.selectedId ?? -1,
), ),
); );

+ 1
- 1
lib/presentation/screens/task/bloc/task_bloc.dart View File

yield response.isEmpty yield response.isEmpty
? (currentState is TaskSuccess ? currentState.copyWith(hasReachedMax: true) : TaskSuccess(items: [], hasReachedMax: true)) ? (currentState is TaskSuccess ? currentState.copyWith(hasReachedMax: true) : TaskSuccess(items: [], hasReachedMax: true))
: (currentState is TaskSuccess : (currentState is TaskSuccess
? TaskSuccess(items: (currentState.items ?? []) + response, hasReachedMax: hasReachedMax)
? currentState.copyWith(items: (currentState.items ?? []) + response, hasReachedMax: hasReachedMax)
: TaskSuccess(items: response, hasReachedMax: hasReachedMax)); : TaskSuccess(items: response, hasReachedMax: hasReachedMax));
} catch (e) { } catch (e) {
isFetching = false; isFetching = false;

+ 4
- 1
lib/presentation/screens/task/bloc/task_state.dart View File

const TaskState(); const TaskState();


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


class TaskInitial extends TaskState {} class TaskInitial extends TaskState {}
hasReachedMax: hasReachedMax ?? this.hasReachedMax, hasReachedMax: hasReachedMax ?? this.hasReachedMax,
); );
} }

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

+ 3
- 1
lib/utils/app_images.dart View File

static const icActionPlant = baseAssets + 'icActionPlant.png'; static const icActionPlant = baseAssets + 'icActionPlant.png';
static const icActionSpraying = baseAssets + 'icActionSpraying.png'; static const icActionSpraying = baseAssets + 'icActionSpraying.png';
static const icActionUseWater = baseAssets + 'icActionUseWater.png'; static const icActionUseWater = baseAssets + 'icActionUseWater.png';
static const logoWithSlogan = baseAssets + 'logoWithSlogan.png';
} }


class AssetSVG { class AssetSVG {
static const icVeterinaryMedicine = baseAssets + 'ic_veterinary_medicine.svg'; static const icVeterinaryMedicine = baseAssets + 'ic_veterinary_medicine.svg';
static const icMeadow = baseAssets + 'ic_meadow.svg'; static const icMeadow = baseAssets + 'ic_meadow.svg';
static const icFoodProcessing = baseAssets + 'ic_food_processing.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 icLogout = baseAssets + 'ic_logout.svg';
static const icCart = baseAssets + 'ic_cart.svg'; static const icCart = baseAssets + 'ic_cart.svg';
static const icCartChecked = baseAssets + 'ic_cart_checked.svg'; static const icCartChecked = baseAssets + 'ic_cart_checked.svg';

+ 2
- 0
lib/utils/const_string.dart View File

const String exception_dio_1020 = const String exception_dio_1020 =
"Người dùng hiện tại không thể truy cập thông tin này"; "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_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";

+ 2
- 2
pubspec.lock View File

dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1"
version: "2.3.1"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:

+ 1
- 1
pubspec.yaml View File

description: A new Flutter project. description: A new Flutter project.


publish_to: 'none' publish_to: 'none'
version: 1.1.16+36
version: 1.1.18+38


environment: environment:
sdk: ">=3.0.0 <4.0.0" sdk: ">=3.0.0 <4.0.0"

Loading…
Cancel
Save