feat: implement submit inspection functionality in poultry science feature, including new data source methods, repository updates, and UI enhancements for image uploads and inspection submission
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class NewInspectionPoultryScienceLogic extends GetxController {
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<SubmitInspectionResponse>>> submitInspectionList =
|
||||
Resource<PaginationModel<SubmitInspectionResponse>>.loading().obs;
|
||||
|
||||
PoultryScienceRootLogic rootLogic = Get.find<PoultryScienceRootLogic>();
|
||||
|
||||
final RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
RxList<XFile> pickedImages = <XFile>[].obs;
|
||||
final List<MultipartFile> _multiPartPickedImages = <MultipartFile>[];
|
||||
|
||||
RxBool isOnUpload = false.obs;
|
||||
|
||||
RxDouble presentUpload = 0.0.obs;
|
||||
RxList<String> routesName = RxList();
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
|
||||
RxnString searchedValue = RxnString();
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
routesName.value = ['اقدام'].toList();
|
||||
|
||||
ever(selectedSegmentIndex, (callback) {
|
||||
routesName.removeLast();
|
||||
routesName.add(callback == 0 ? 'بازرسی' : 'بایگانی');
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
|
||||
getReport();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getReport([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<SubmitInspectionResponse>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async =>
|
||||
await rootLogic.poultryRepository.getSubmitInspectionList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
role: 'PoultryScience',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<SubmitInspectionResponse>>.empty();
|
||||
} else {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<SubmitInspectionResponse>>.success(
|
||||
PaginationModel<SubmitInspectionResponse>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [
|
||||
...(submitInspectionList.value.data?.results ?? []),
|
||||
...(res?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> pickImages() async {
|
||||
determineCurrentPosition();
|
||||
var tmp = await pickCameraImage();
|
||||
if (tmp?.path != null && pickedImages.length < 7) {
|
||||
pickedImages.add(tmp!);
|
||||
}
|
||||
}
|
||||
|
||||
void removeImage(int index) {
|
||||
pickedImages.removeAt(index);
|
||||
}
|
||||
|
||||
void closeBottomSheet() {
|
||||
Get.back();
|
||||
}
|
||||
|
||||
double calculateUploadProgress({required int sent, required int total}) {
|
||||
if (total != 0) {
|
||||
double progress = (sent * 100 / total) / 100;
|
||||
return progress;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
void setSearchValue(String? data) {
|
||||
dLog('Search Value: $data');
|
||||
searchedValue.value = data?.trim();
|
||||
getReport();
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getReport();
|
||||
}
|
||||
|
||||
String getStatus(SubmitInspectionResponse item) {
|
||||
if (item.inspectionStatus == null || item.inspectionStatus!.isEmpty) {
|
||||
return 'در حال بررسی';
|
||||
}
|
||||
return item.inspectionStatus!;
|
||||
}
|
||||
|
||||
Color getStatusColor(SubmitInspectionResponse item) {
|
||||
if (item.inspectionStatus == null || item.inspectionStatus!.isEmpty) {
|
||||
return AppColor.yellowNormal;
|
||||
}
|
||||
// میتوانید منطق رنگ را بر اساس inspectionStatus تنظیم کنید
|
||||
return AppColor.greenNormal;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@ class PoultryActionLogic extends GetxController {
|
||||
|
||||
PoultryActionItem(
|
||||
title: "بازرسی مزارع طیور",
|
||||
route: ChickenRoutes.poultryFarmInspectionHome,
|
||||
route: PoultryScienceRoutes.newInspectionPoultryScience,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
].obs;
|
||||
|
||||
@@ -7,6 +7,8 @@ import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/gen
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/new_inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/new_inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/killing_registration/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/killing_registration/view.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/pages/poultry_action/logic.dart';
|
||||
@@ -46,6 +48,17 @@ class PoultrySciencePages {
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: PoultryScienceRoutes.newInspectionPoultryScience,
|
||||
page: () => NewInspectionPoultrySciencePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => NewInspectionPoultryScienceLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: PoultryScienceRoutes.actionPoultryScience,
|
||||
page: () => PoultryActionPage(),
|
||||
|
||||
@@ -5,6 +5,7 @@ sealed class PoultryScienceRoutes {
|
||||
static const initPoultryScience = '$_base/';
|
||||
static const actionPoultryScience = '$_base/action';
|
||||
static const inspectionPoultryScience = '$_base/inspection';
|
||||
static const newInspectionPoultryScience = '$_base/newInspection';
|
||||
static const farmPoultryScience = '$_base/farm';
|
||||
static const activeHatchingPoultryScience = '$_base/activeHatching';
|
||||
static const genocidePoultryScience = '$_base/genocidePoultryScience';
|
||||
|
||||
@@ -16,7 +16,6 @@ class CreateInspectionBottomSheet
|
||||
step2Page(controller),
|
||||
step3Page(controller),
|
||||
step4Page(controller),
|
||||
step5Page(controller),
|
||||
];
|
||||
|
||||
@override
|
||||
@@ -47,20 +46,40 @@ class CreateInspectionBottomSheet
|
||||
child: ObxValue((data) {
|
||||
return RElevated(
|
||||
height: 40.h,
|
||||
enabled: data.value,
|
||||
enabled:
|
||||
data.value && !controller.isUploadingImages.value,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
children: [
|
||||
Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||
|
||||
Text('ادامه'),
|
||||
if (controller.isUploadingImages.value)
|
||||
SizedBox(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
Colors.white,
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||
SizedBox(width: 8.w),
|
||||
Text(
|
||||
controller.isUploadingImages.value
|
||||
? 'در حال آپلود...'
|
||||
: (controller.activeStepperIndex.value < 3)
|
||||
? 'ادامه'
|
||||
: 'ثبت',
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
if (controller.activeStepperIndex.value < 4) {
|
||||
if (controller.activeStepperIndex.value < 3) {
|
||||
controller.activeStepperIndex.value++;
|
||||
} else {
|
||||
controller.submitInspection();
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -71,7 +90,9 @@ class CreateInspectionBottomSheet
|
||||
borderColor: AppColor.error,
|
||||
height: 40.h,
|
||||
child: Text('برگشت'),
|
||||
enabled: controller.activeStepperIndex.value > 0,
|
||||
enabled:
|
||||
controller.activeStepperIndex.value > 0 &&
|
||||
!controller.isUploadingImages.value,
|
||||
onPressed: () {
|
||||
if (controller.activeStepperIndex.value > 0) {
|
||||
controller.activeStepperIndex.value--;
|
||||
@@ -83,6 +104,53 @@ class CreateInspectionBottomSheet
|
||||
),
|
||||
);
|
||||
}, controller.activeStepperIndex),
|
||||
|
||||
// نمایش وضعیت آپلود
|
||||
Obx(() {
|
||||
if (controller.isUploadingImages.value) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
margin: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.whiteNormalActive,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 4,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
controller.uploadStatusMessage.value,
|
||||
style: AppFonts.yekan14,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
LinearProgressIndicator(
|
||||
value: controller.uploadProgress.value,
|
||||
backgroundColor: AppColor.whiteNormalActive,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
'${(controller.uploadProgress.value * 100).toInt()}%',
|
||||
style: AppFonts.yekan12.copyWith(
|
||||
color: AppColor.iconColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return SizedBox.shrink();
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -199,7 +267,7 @@ class stepper extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
/* Expanded(
|
||||
child: Divider(
|
||||
color: activeStep >= 4
|
||||
? AppColor.greenNormalHover
|
||||
@@ -207,7 +275,7 @@ class stepper extends StatelessWidget {
|
||||
thickness: 8,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: activeStep >= 4
|
||||
@@ -224,7 +292,7 @@ class stepper extends StatelessWidget {
|
||||
color: activeStep >= 3 ? Colors.white : AppColor.iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
), */
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/repositories/poultry_science_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
@@ -12,10 +13,9 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
.get<PoultryScienceRepository>();
|
||||
|
||||
TokenStorageService tokenStorageService = Get.find<TokenStorageService>();
|
||||
|
||||
var gService = Get.find<GService>();
|
||||
RxInt selectedSegmentIndex = 0.obs;
|
||||
|
||||
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
|
||||
late TabController tabController;
|
||||
@@ -28,7 +28,14 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
|
||||
RxBool nextStepButtonEnabled = false.obs;
|
||||
|
||||
RxInt casualtiesInformationHeight = 300.obs;
|
||||
RxInt casualtiesInformationHeight = 310.obs;
|
||||
|
||||
SubmitInspectionResponse? submitInspectionResponse;
|
||||
|
||||
// Upload states
|
||||
RxBool isUploadingImages = false.obs;
|
||||
RxString uploadStatusMessage = ''.obs;
|
||||
RxDouble uploadProgress = 0.0.obs;
|
||||
|
||||
//step1
|
||||
|
||||
@@ -155,6 +162,7 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
RxBool trainingStatus = false.obs;
|
||||
RxnString newBeneficiaryRequest = RxnString();
|
||||
RxBool overdueStatus = false.obs;
|
||||
RxBool hasFacilities = false.obs;
|
||||
TextEditingController paymentYearController = TextEditingController();
|
||||
Rx<Jalali> selectedPaymentYear = Jalali.now().obs;
|
||||
|
||||
@@ -213,11 +221,164 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
resetAllData();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void resetAllData() {
|
||||
// Reset stepper and navigation
|
||||
activeStepperIndex.value = 0;
|
||||
selectedTabIndex.value = 0;
|
||||
selectedSegmentIndex.value = 0;
|
||||
expandedIndex.value = -1;
|
||||
nextStepButtonEnabled.value = false;
|
||||
casualtiesInformationHeight.value = 310;
|
||||
|
||||
// Reset upload states
|
||||
isUploadingImages.value = false;
|
||||
uploadStatusMessage.value = '';
|
||||
uploadProgress.value = 0.0;
|
||||
|
||||
// Reset location
|
||||
currentLocation.value = null;
|
||||
isLoadingLocation.value = false;
|
||||
|
||||
// Clear all TextEditingControllers - Step 1
|
||||
unitNameController.clear();
|
||||
breedingUniqueIdController.clear();
|
||||
healthLicenseController.clear();
|
||||
tenantStatusController.clear();
|
||||
tenantNameController.clear();
|
||||
tenantNationalIdController.clear();
|
||||
tenantPhoneNumberController.clear();
|
||||
ownerNameController.clear();
|
||||
ownerNationalCodeController.clear();
|
||||
ownerPhoneNumberController.clear();
|
||||
totalCapacityController.clear();
|
||||
|
||||
// Clear Step 1 additional fields
|
||||
hatchingDateController.clear();
|
||||
visitDateController.clear();
|
||||
hatchingCountController.clear();
|
||||
hatchingAverageWeightController.clear();
|
||||
hatchingBreedController.clear();
|
||||
|
||||
// Clear Step 2 fields
|
||||
causeOfUnusualCasualties.value = null;
|
||||
isOthercauseOfUnusualCasualties.value = false;
|
||||
otherCauseOfUnusualCasualtiesController.clear();
|
||||
typeOfDisease.value = null;
|
||||
isOtherTypeOfDiseaseSelected.value = false;
|
||||
otherTypeOfDiseaseController.clear();
|
||||
hatchingTemperatureController.clear();
|
||||
waterHardnessController.clear();
|
||||
normalLossesController.clear();
|
||||
abnormalLossesController.clear();
|
||||
sourceOfHatchingController.clear();
|
||||
samplingDone.value = false;
|
||||
technicalHealthOfficerNameController.clear();
|
||||
technicalEngineeringOfficerNameController.clear();
|
||||
|
||||
// Reset Step 2 selection indices
|
||||
sanitaryConditionOfTheHallIndex.value = -1;
|
||||
ventilationStatusIndex.value = -1;
|
||||
beddingStatusIndex.value = -1;
|
||||
waterQualityIndex.value = -1;
|
||||
sampleTypeIndex.value = -1;
|
||||
sanitaryConditionOfTheHall.value = null;
|
||||
ventilationStatus.value = null;
|
||||
beddingStatus.value = null;
|
||||
waterQuality.value = null;
|
||||
sampleType.value = null;
|
||||
|
||||
// Clear Step 3 fields
|
||||
inputStatus.value = null;
|
||||
companyNameController.clear();
|
||||
trackingCodeController.clear();
|
||||
typeOfGrain.value = null;
|
||||
inputInventoryInWarehouseController.clear();
|
||||
inputInventoryUntilVisitController.clear();
|
||||
generatorTypeController.clear();
|
||||
generatorModelController.clear();
|
||||
generatorCountController.clear();
|
||||
generatorCapacityController.clear();
|
||||
emergencyFuelInventoryController.clear();
|
||||
powerCutDurationController.clear();
|
||||
powerCutHourController.clear();
|
||||
additionalNotesController.clear();
|
||||
fuelType.value = null;
|
||||
powerCutHistory.value = false;
|
||||
|
||||
// Reset Step 3 selection indices
|
||||
grainQualityInputIndex.value = -1;
|
||||
generatorOperatingStatusIndex.value = -1;
|
||||
workerContractStatusIndex.value = -1;
|
||||
newBeneficiaryRequestIndex.value = -1;
|
||||
grainQualityInput.value = null;
|
||||
generatorOperatingStatus.value = null;
|
||||
workerContractStatus.value = null;
|
||||
newBeneficiaryRequest.value = null;
|
||||
trainingStatus.value = false;
|
||||
overdueStatus.value = false;
|
||||
hasFacilities.value = false;
|
||||
|
||||
// Clear Step 3 worker fields
|
||||
employedWorkersCountController.clear();
|
||||
nativeWorkersCountController.clear();
|
||||
nonNativeWorkersCountController.clear();
|
||||
activeFacilityController.clear();
|
||||
facilityTypeController.clear();
|
||||
facilityAmountController.clear();
|
||||
paymentYearController.clear();
|
||||
selectedPaymentYear.value = Jalali.now();
|
||||
|
||||
// Clear Step 4 fields
|
||||
facilityYearController.clear();
|
||||
selectedFacilityYear.value = Jalali.now();
|
||||
inspectorConclusionIndex.value = -1;
|
||||
inspectorConclusion.value = null;
|
||||
inspectorConclusionDescriptionController.clear();
|
||||
|
||||
// Clear all images
|
||||
pultryImages.clear();
|
||||
pultryImagesUrls.clear();
|
||||
hallImages.clear();
|
||||
hallImagesUrls.clear();
|
||||
inputWarehouseImages.clear();
|
||||
inputWarehouseImagesUrls.clear();
|
||||
lossesImages.clear();
|
||||
lossesImagesUrls.clear();
|
||||
|
||||
// Reset fuel type index
|
||||
fuelTypeIndex.value = -1;
|
||||
|
||||
// Reset submitInspectionResponse
|
||||
submitInspectionResponse = null;
|
||||
|
||||
// Reset hatching model
|
||||
hatchingModel = null;
|
||||
|
||||
// Reset page controller
|
||||
if (pageController.hasClients) {
|
||||
pageController.jumpToPage(0);
|
||||
}
|
||||
}
|
||||
|
||||
void initData() {
|
||||
submitInspectionResponse = SubmitInspectionResponse(
|
||||
generalConditionHall: GeneralConditionHall(),
|
||||
casualties: Casualties(),
|
||||
technicalOfficer: TechnicalOfficer(),
|
||||
inputStatus: InputStatus(),
|
||||
infrastructureEnergy: InfrastructureEnergy(),
|
||||
hr: Hr(),
|
||||
facilities: Facilities(),
|
||||
);
|
||||
|
||||
submitInspectionResponse?.poultryHatchingId = hatchingModel?.id;
|
||||
|
||||
submitInspectionResponse?.role = gService.getRole(Module.chicken);
|
||||
|
||||
unitNameController.text =
|
||||
hatchingModel?.poultry?.unitName ?? 'واحد مرغداری نامشخص';
|
||||
|
||||
@@ -296,6 +457,8 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
|
||||
void setSanitaryConditionOfTheHallIndex(int index, String item) {
|
||||
sanitaryConditionOfTheHall.value = item;
|
||||
submitInspectionResponse?.generalConditionHall?.healthStatus = item;
|
||||
|
||||
sanitaryConditionOfTheHallIndex.value =
|
||||
index == sanitaryConditionOfTheHallIndex.value ? -1 : index;
|
||||
}
|
||||
@@ -307,6 +470,7 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
|
||||
void setVentilationStatusIndex(int index, String item) {
|
||||
ventilationStatus.value = item;
|
||||
submitInspectionResponse?.generalConditionHall?.ventilationStatus = item;
|
||||
ventilationStatusIndex.value = index == ventilationStatusIndex.value
|
||||
? -1
|
||||
: index;
|
||||
@@ -314,21 +478,25 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
|
||||
void setBeddingStatusIndex(int index, String item) {
|
||||
beddingStatus.value = item;
|
||||
submitInspectionResponse?.generalConditionHall?.bedCondition = item;
|
||||
beddingStatusIndex.value = index == beddingStatusIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setWaterQualityIndex(int index, String item) {
|
||||
waterQuality.value = item;
|
||||
submitInspectionResponse?.generalConditionHall?.drinkingWaterSource = item;
|
||||
waterQualityIndex.value = index == waterQualityIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setSampleTypeIndex(int index, String item) {
|
||||
sampleType.value = item;
|
||||
submitInspectionResponse?.casualties?.typeSampling = item;
|
||||
sampleTypeIndex.value = index == sampleTypeIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setGrainQualityInput(int index, String item) {
|
||||
grainQualityInput.value = item;
|
||||
submitInspectionResponse?.inputStatus?.gradeGrain = item;
|
||||
grainQualityInputIndex.value = index == grainQualityInputIndex.value
|
||||
? -1
|
||||
: index;
|
||||
@@ -336,13 +504,14 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
|
||||
void setGeneratorOperatingStatusIndex(int index, String item) {
|
||||
generatorOperatingStatus.value = item;
|
||||
submitInspectionResponse?.infrastructureEnergy?.generatorPerformance = item;
|
||||
generatorOperatingStatusIndex.value =
|
||||
index == generatorOperatingStatusIndex.value ? -1 : index;
|
||||
}
|
||||
|
||||
void setWorkerContractStatusIndex(int index, String item) {
|
||||
workerContractStatus.value = item;
|
||||
|
||||
submitInspectionResponse?.hr?.contractStatus = item;
|
||||
workerContractStatusIndex.value = index == workerContractStatusIndex.value
|
||||
? -1
|
||||
: index;
|
||||
@@ -374,6 +543,10 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
final latLng = await determineCurrentLatLng();
|
||||
currentLocation.value = latLng;
|
||||
isLoadingLocation.value = false;
|
||||
|
||||
submitInspectionResponse?.lat = latLng.latitude.toString();
|
||||
submitInspectionResponse?.log = latLng.longitude.toString();
|
||||
|
||||
setUpNextButtonListeners();
|
||||
} catch (e) {
|
||||
isLoadingLocation.value = false;
|
||||
@@ -390,7 +563,7 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> pickImageFromCamera() async {
|
||||
Future<void> pickImageFromCamera(RxMap<XFile, bool> images) async {
|
||||
try {
|
||||
final XFile? image = await imagePicker.pickImage(
|
||||
source: ImageSource.camera,
|
||||
@@ -400,7 +573,7 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
);
|
||||
|
||||
if (image != null) {
|
||||
pultryImages[image] = false;
|
||||
images[image] = false;
|
||||
|
||||
//await uploadImage(image);
|
||||
}
|
||||
@@ -436,8 +609,137 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
);
|
||||
}
|
||||
|
||||
void removeImage(XFile image) {
|
||||
pultryImages.remove(image);
|
||||
Future<List<String>?> uploadImageBatch(List<XFile> images) async {
|
||||
if (images.isEmpty) return [];
|
||||
|
||||
List<String>? result;
|
||||
await safeCall(
|
||||
call: () async {
|
||||
final urls = await repository.uploadImages(
|
||||
token: tokenStorageService.accessToken.value ?? '',
|
||||
images: images,
|
||||
);
|
||||
return urls;
|
||||
},
|
||||
onSuccess: (urls) {
|
||||
result = urls;
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
result = null;
|
||||
},
|
||||
showError: false, // خطاها در uploadAllImages مدیریت میشوند
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<bool> uploadAllImages() async {
|
||||
isUploadingImages.value = true;
|
||||
uploadProgress.value = 0.0;
|
||||
uploadStatusMessage.value = 'در حال آپلود عکسها...';
|
||||
|
||||
try {
|
||||
int totalImages = 0;
|
||||
int uploadedCount = 0;
|
||||
|
||||
// شمارش کل عکسها
|
||||
totalImages =
|
||||
hallImages.length +
|
||||
inputWarehouseImages.length +
|
||||
lossesImages.length +
|
||||
pultryImages.length;
|
||||
|
||||
if (totalImages == 0) {
|
||||
isUploadingImages.value = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// آپلود عکسهای سالن
|
||||
if (hallImages.isNotEmpty) {
|
||||
uploadStatusMessage.value = 'در حال آپلود عکسهای سالن...';
|
||||
final hallImageFiles = hallImages.keys.toList();
|
||||
final hallUrls = await uploadImageBatch(hallImageFiles);
|
||||
|
||||
if (hallUrls != null && hallUrls.isNotEmpty) {
|
||||
submitInspectionResponse?.generalConditionHall?.images = hallUrls;
|
||||
uploadedCount += hallImageFiles.length;
|
||||
uploadProgress.value = uploadedCount / totalImages;
|
||||
} else {
|
||||
throw Exception('خطا در آپلود عکسهای سالن');
|
||||
}
|
||||
}
|
||||
|
||||
// آپلود عکسهای انبار دان
|
||||
if (inputWarehouseImages.isNotEmpty) {
|
||||
uploadStatusMessage.value = 'در حال آپلود عکسهای انبار دان...';
|
||||
final inputImageFiles = inputWarehouseImages.keys.toList();
|
||||
final inputUrls = await uploadImageBatch(inputImageFiles);
|
||||
|
||||
if (inputUrls != null && inputUrls.isNotEmpty) {
|
||||
submitInspectionResponse?.inputStatus?.images = inputUrls;
|
||||
uploadedCount += inputImageFiles.length;
|
||||
uploadProgress.value = uploadedCount / totalImages;
|
||||
} else {
|
||||
throw Exception('خطا در آپلود عکسهای انبار دان');
|
||||
}
|
||||
}
|
||||
|
||||
// آپلود عکسهای تلفات
|
||||
if (lossesImages.isNotEmpty) {
|
||||
uploadStatusMessage.value = 'در حال آپلود عکسهای تلفات...';
|
||||
final lossesImageFiles = lossesImages.keys.toList();
|
||||
final lossesUrls = await uploadImageBatch(lossesImageFiles);
|
||||
|
||||
if (lossesUrls != null && lossesUrls.isNotEmpty) {
|
||||
submitInspectionResponse?.casualties?.images = lossesUrls;
|
||||
uploadedCount += lossesImageFiles.length;
|
||||
uploadProgress.value = uploadedCount / totalImages;
|
||||
} else {
|
||||
throw Exception('خطا در آپلود عکسهای تلفات');
|
||||
}
|
||||
}
|
||||
|
||||
// آپلود عکسهای مرغداری
|
||||
if (pultryImages.isNotEmpty) {
|
||||
uploadStatusMessage.value = 'در حال آپلود عکسهای مرغداری...';
|
||||
final poultryImageFiles = pultryImages.keys.toList();
|
||||
final poultryUrls = await uploadImageBatch(poultryImageFiles);
|
||||
|
||||
if (poultryUrls != null && poultryUrls.isNotEmpty) {
|
||||
// اگر فیلد جداگانهای برای عکسهای مرغداری نداریم، به generalConditionHall اضافه میکنیم
|
||||
if (submitInspectionResponse?.generalConditionHall?.images == null) {
|
||||
submitInspectionResponse?.generalConditionHall?.images = [];
|
||||
}
|
||||
submitInspectionResponse?.generalConditionHall?.images?.addAll(
|
||||
poultryUrls,
|
||||
);
|
||||
uploadedCount += poultryImageFiles.length;
|
||||
uploadProgress.value = uploadedCount / totalImages;
|
||||
} else {
|
||||
throw Exception('خطا در آپلود عکسهای مرغداری');
|
||||
}
|
||||
}
|
||||
|
||||
uploadProgress.value = 1.0;
|
||||
uploadStatusMessage.value = 'آپلود عکسها با موفقیت انجام شد';
|
||||
isUploadingImages.value = false;
|
||||
return true;
|
||||
} catch (e) {
|
||||
isUploadingImages.value = false;
|
||||
uploadStatusMessage.value = 'خطا در آپلود عکسها: ${e.toString()}';
|
||||
Get.snackbar(
|
||||
'خطا',
|
||||
'خطا در آپلود عکسها: ${e.toString()}',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void removeImage(RxMap<XFile, bool> images, XFile image) {
|
||||
images.remove(image);
|
||||
}
|
||||
|
||||
void setTypeOfDiseaseIndex(String item) {
|
||||
@@ -469,9 +771,10 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
void setSamplingDone(String value) {
|
||||
if (samplingDone.value && value != 'انجام شد') {
|
||||
casualtiesInformationHeight.value =
|
||||
casualtiesInformationHeight.value -80;
|
||||
casualtiesInformationHeight.value - 80;
|
||||
}
|
||||
samplingDone.value = value == 'انجام شد';
|
||||
submitInspectionResponse?.casualties?.samplingDone = samplingDone.value;
|
||||
if (value == 'انجام شد') {
|
||||
casualtiesInformationHeight.value =
|
||||
casualtiesInformationHeight.value + 80;
|
||||
@@ -480,30 +783,45 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
|
||||
void setInputStatus(String item) {
|
||||
inputStatus.value = item;
|
||||
submitInspectionResponse?.inputStatus?.inputStatus = item;
|
||||
}
|
||||
|
||||
void setTypeOfGrain(String item) {
|
||||
typeOfGrain.value = item;
|
||||
submitInspectionResponse?.inputStatus?.typeOfGrain = item;
|
||||
}
|
||||
|
||||
void setFuelType(String item) {
|
||||
fuelType.value = item;
|
||||
submitInspectionResponse?.infrastructureEnergy?.fuelType = item;
|
||||
}
|
||||
|
||||
void setPowerCutHistory(String item) {
|
||||
powerCutHistory.value = item == 'دارد';
|
||||
submitInspectionResponse?.infrastructureEnergy?.hasPowerCutHistory =
|
||||
powerCutHistory.value;
|
||||
}
|
||||
|
||||
void setTrainingStatus(String item) {
|
||||
trainingStatus.value = item == 'بله';
|
||||
submitInspectionResponse?.hr?.trained = item == 'بله';
|
||||
submitInspectionResponse?.hr?.trained = trainingStatus.value;
|
||||
}
|
||||
|
||||
void setNewBeneficiaryRequest(String item) {
|
||||
newBeneficiaryRequest.value = item;
|
||||
submitInspectionResponse?.facilities?.requestFacilities =
|
||||
newBeneficiaryRequest.value;
|
||||
}
|
||||
|
||||
void setHasFacilities(String item) {
|
||||
hasFacilities.value = item == 'دارد';
|
||||
submitInspectionResponse?.facilities?.hasFacilities = hasFacilities.value;
|
||||
}
|
||||
|
||||
void setOverdueStatus(String item) {
|
||||
overdueStatus.value = item == 'دارای معوقه';
|
||||
submitInspectionResponse?.facilities?.repaymentStatus = item;
|
||||
}
|
||||
|
||||
void showPaymentYearDatePicker() {
|
||||
@@ -542,4 +860,117 @@ class CreateInspectionBottomSheetLogic extends GetxController
|
||||
void removeLossesImage(XFile key) {
|
||||
lossesImages.remove(key);
|
||||
}
|
||||
|
||||
Future<void> submitInspection() async {
|
||||
// ابتدا عکسها را آپلود میکنیم
|
||||
final imagesUploaded = await uploadAllImages();
|
||||
if (!imagesUploaded) {
|
||||
return; // اگر آپلود عکسها ناموفق بود، متوقف میشویم
|
||||
}
|
||||
|
||||
// پر کردن دادههای فرم
|
||||
submitInspectionResponse?.generalConditionHall?.temperature =
|
||||
hatchingTemperatureController.text;
|
||||
submitInspectionResponse?.generalConditionHall?.drinkingWaterQuality =
|
||||
waterQuality.value;
|
||||
submitInspectionResponse?.casualties?.abnormalLosses = int.parse(
|
||||
abnormalLossesController.text,
|
||||
);
|
||||
submitInspectionResponse?.casualties?.normalLosses = int.parse(
|
||||
normalLossesController.text,
|
||||
);
|
||||
|
||||
if (isOthercauseOfUnusualCasualties.value) {
|
||||
submitInspectionResponse?.casualties?.causeAbnormalLosses =
|
||||
otherCauseOfUnusualCasualtiesController.text;
|
||||
} else {
|
||||
submitInspectionResponse?.casualties?.causeAbnormalLosses =
|
||||
causeOfUnusualCasualties.value;
|
||||
}
|
||||
|
||||
if (isOtherTypeOfDiseaseSelected.value) {
|
||||
submitInspectionResponse?.casualties?.typeDisease =
|
||||
otherTypeOfDiseaseController.text;
|
||||
} else {
|
||||
submitInspectionResponse?.casualties?.typeDisease = typeOfDisease.value;
|
||||
}
|
||||
|
||||
submitInspectionResponse?.technicalOfficer?.technicalHealthOfficer =
|
||||
technicalHealthOfficerNameController.text;
|
||||
submitInspectionResponse?.technicalOfficer?.technicalEngineeringOfficer =
|
||||
technicalEngineeringOfficerNameController.text;
|
||||
|
||||
if (inputStatus.value == 'وابسته') {
|
||||
submitInspectionResponse?.inputStatus?.companyName =
|
||||
companyNameController.text;
|
||||
} else {
|
||||
submitInspectionResponse?.inputStatus?.trackingCode =
|
||||
trackingCodeController.text;
|
||||
}
|
||||
|
||||
submitInspectionResponse?.inputStatus?.inventoryUntilVisit =
|
||||
inputInventoryUntilVisitController.text;
|
||||
submitInspectionResponse?.inputStatus?.inventoryInWarehouse =
|
||||
inputInventoryInWarehouseController.text;
|
||||
|
||||
submitInspectionResponse?.infrastructureEnergy?.generatorType =
|
||||
generatorTypeController.text;
|
||||
submitInspectionResponse?.infrastructureEnergy?.generatorModel =
|
||||
generatorModelController.text;
|
||||
submitInspectionResponse?.infrastructureEnergy?.generatorCount =
|
||||
generatorCountController.text;
|
||||
submitInspectionResponse?.infrastructureEnergy?.generatorCapacity =
|
||||
generatorCapacityController.text;
|
||||
submitInspectionResponse?.infrastructureEnergy?.emergencyFuelInventory =
|
||||
emergencyFuelInventoryController.text;
|
||||
submitInspectionResponse?.infrastructureEnergy?.powerCutDuration =
|
||||
powerCutDurationController.text;
|
||||
submitInspectionResponse?.infrastructureEnergy?.powerCutHour =
|
||||
powerCutHourController.text;
|
||||
submitInspectionResponse?.infrastructureEnergy?.additionalNotes =
|
||||
additionalNotesController.text;
|
||||
|
||||
submitInspectionResponse?.hr?.numberEmployed = int.parse(
|
||||
employedWorkersCountController.text.clearComma,
|
||||
);
|
||||
submitInspectionResponse?.hr?.numberIndigenous = int.parse(
|
||||
nativeWorkersCountController.text.clearComma,
|
||||
);
|
||||
submitInspectionResponse?.hr?.numberNonIndigenous = int.parse(
|
||||
nonNativeWorkersCountController.text.clearComma,
|
||||
);
|
||||
iLog(submitInspectionResponse?.toJson());
|
||||
|
||||
|
||||
await safeCall(
|
||||
call: () async {
|
||||
await repository.submitInspection(
|
||||
token: tokenStorageService.accessToken.value ?? '',
|
||||
request: submitInspectionResponse!,
|
||||
);
|
||||
},
|
||||
onSuccess: (result) {
|
||||
|
||||
Get.back();
|
||||
|
||||
Future.delayed(Duration(seconds: 2), () { Get.snackbar(
|
||||
'موفق',
|
||||
'بازرسی با موفقیت ثبت شد',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
);});
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
Get.snackbar(
|
||||
'خطا',
|
||||
'خطا در ثبت بازرسی: ${error.toString()}',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
},
|
||||
showError: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ Widget step1Page(CreateInspectionBottomSheetLogic controller) {
|
||||
|
||||
Container(
|
||||
height: controller.tenantStatusController.text == 'دارد'
|
||||
? 570.h
|
||||
? 588.h
|
||||
: 445.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
|
||||
@@ -14,7 +14,7 @@ Widget step2Page(CreateInspectionBottomSheetLogic controller) {
|
||||
SizedBox(height: 35.h),
|
||||
|
||||
Container(
|
||||
height: 580.h,
|
||||
height: 600.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
@@ -46,7 +46,7 @@ Widget step2Page(CreateInspectionBottomSheetLogic controller) {
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
controller: controller,
|
||||
title: 'بیماریها و وضعیت سلامت',
|
||||
title: 'مسئول فنی ',
|
||||
child: diseasesAndHealthInformation(controller),
|
||||
),
|
||||
),
|
||||
@@ -102,7 +102,7 @@ Column generalConditionOfTheHall(CreateInspectionBottomSheetLogic controller) {
|
||||
right: -4,
|
||||
child: GestureDetector(
|
||||
onTap: () =>
|
||||
controller.removeImage(entry.key),
|
||||
controller.removeImage(controller.pultryImages, entry.key),
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
@@ -144,10 +144,10 @@ Column generalConditionOfTheHall(CreateInspectionBottomSheetLogic controller) {
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
,
|
||||
// Add image button
|
||||
GestureDetector(
|
||||
onTap: () => controller.pickImageFromCamera(),
|
||||
onTap: () => controller.pickImageFromCamera(controller.pultryImages),
|
||||
child: Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
|
||||
@@ -14,7 +14,7 @@ Widget step3Page(CreateInspectionBottomSheetLogic controller) {
|
||||
SizedBox(height: 35.h),
|
||||
|
||||
Container(
|
||||
height: 350.h,
|
||||
height: 360.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
@@ -27,7 +27,7 @@ Widget step3Page(CreateInspectionBottomSheetLogic controller) {
|
||||
SizedBox(height: 30.h),
|
||||
|
||||
Container(
|
||||
height: 600.h,
|
||||
height: 610.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
@@ -51,7 +51,7 @@ Widget step3Page(CreateInspectionBottomSheetLogic controller) {
|
||||
SizedBox(height: 24.h),
|
||||
|
||||
Container(
|
||||
height: 320.h,
|
||||
height: 325.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
@@ -461,12 +461,11 @@ Column facilitiesAndSupport(CreateInspectionBottomSheetLogic controller) {
|
||||
children: [
|
||||
SizedBox(height: 1.h),
|
||||
|
||||
RTextField(
|
||||
controller: controller.activeFacilityController,
|
||||
label: 'تسهیلات دریافتی فعال',
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
maxLines: 1,
|
||||
ResourceOverlayDropdown(
|
||||
items: Resource.success([ 'دارد', 'ندارد']),
|
||||
onChanged: (item) => controller.setHasFacilities(item),
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) => Text(selected ?? ' تسهیلات دریافتی فعال'),
|
||||
),
|
||||
|
||||
RTextField(
|
||||
|
||||
@@ -16,7 +16,7 @@ Widget step4Page(CreateInspectionBottomSheetLogic controller) {
|
||||
SizedBox(height: 35.h),
|
||||
|
||||
Container(
|
||||
height: 430.h,
|
||||
height: 440.h,
|
||||
clipBehavior: Clip.none,
|
||||
width: Get.width,
|
||||
child: farmInfoWidget(
|
||||
@@ -62,80 +62,60 @@ Column documents(CreateInspectionBottomSheetLogic controller) {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
...controller.hallImages.entries
|
||||
.map(
|
||||
(entry) => Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.blackLightHover,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.file(
|
||||
File(entry.key.path),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
...controller.hallImages.entries.map(
|
||||
(entry) => Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.blackLightHover,
|
||||
),
|
||||
// Delete button
|
||||
Positioned(
|
||||
top: -4,
|
||||
right: -4,
|
||||
child: GestureDetector(
|
||||
onTap: () =>
|
||||
controller.removeImage(entry.key),
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.file(
|
||||
File(entry.key.path),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
// Upload indicator
|
||||
if (entry.value == false)
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation<Color>(
|
||||
Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
// Delete button
|
||||
Positioned(
|
||||
top: 4,
|
||||
left: 4,
|
||||
child: GestureDetector(
|
||||
onTap: () => controller.removeImage(
|
||||
controller.hallImages,
|
||||
entry.key,
|
||||
),
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Upload indicator
|
||||
],
|
||||
),
|
||||
),
|
||||
// Add image button
|
||||
GestureDetector(
|
||||
onTap: () => controller.pickImageFromCamera(),
|
||||
onTap: () =>
|
||||
controller.pickImageFromCamera(controller.hallImages),
|
||||
child: Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
@@ -192,80 +172,58 @@ Column documents(CreateInspectionBottomSheetLogic controller) {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
...controller.inputWarehouseImages.entries
|
||||
.map(
|
||||
(entry) => Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.blackLightHover,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.file(
|
||||
File(entry.key.path),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
...controller.inputWarehouseImages.entries.map(
|
||||
(entry) => Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.blackLightHover,
|
||||
),
|
||||
// Delete button
|
||||
Positioned(
|
||||
top: -4,
|
||||
right: -4,
|
||||
child: GestureDetector(
|
||||
onTap: () => controller
|
||||
.removeInputWarehouseImage(entry.key),
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.file(
|
||||
File(entry.key.path),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
// Upload indicator
|
||||
if (entry.value == false)
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation<Color>(
|
||||
Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
// Delete button
|
||||
Positioned(
|
||||
top: 4,
|
||||
left: 4,
|
||||
child: GestureDetector(
|
||||
onTap: () => controller.removeInputWarehouseImage(
|
||||
entry.key,
|
||||
),
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Add image button
|
||||
GestureDetector(
|
||||
onTap: () => controller.pickImageFromCamera(),
|
||||
onTap: () => controller.pickImageFromCamera(
|
||||
controller.inputWarehouseImages,
|
||||
),
|
||||
child: Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
@@ -310,80 +268,58 @@ Column documents(CreateInspectionBottomSheetLogic controller) {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
...controller.lossesImages.entries
|
||||
.map(
|
||||
(entry) => Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.blackLightHover,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.file(
|
||||
File(entry.key.path),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
...controller.lossesImages.entries.map(
|
||||
(entry) => Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.blackLightHover,
|
||||
),
|
||||
// Delete button
|
||||
Positioned(
|
||||
top: -4,
|
||||
right: -4,
|
||||
child: GestureDetector(
|
||||
onTap: () => controller
|
||||
.removeInputWarehouseImage(entry.key),
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.file(
|
||||
File(entry.key.path),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
// Upload indicator
|
||||
if (entry.value == false)
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation<Color>(
|
||||
Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
// Delete button
|
||||
Positioned(
|
||||
top: 4,
|
||||
left: 4,
|
||||
child: GestureDetector(
|
||||
onTap: () => controller.removeInputWarehouseImage(
|
||||
entry.key,
|
||||
),
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Add image button
|
||||
GestureDetector(
|
||||
onTap: () => controller.pickImageFromCamera(),
|
||||
onTap: () => controller.pickImageFromCamera(
|
||||
controller.lossesImages,
|
||||
),
|
||||
child: Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
|
||||
Reference in New Issue
Block a user