chore: update app version to 1.3.36+32, change build mode to release, and enhance user role handling in chicken feature with new routes and DI setup
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
sdk.dir=C:\\Users\\Housh11\\AppData\\Local\\Android\\sdk
|
||||
flutter.sdk=C:\\src\\flutter
|
||||
flutter.buildMode=debug
|
||||
flutter.versionName=1.3.35
|
||||
flutter.buildMode=release
|
||||
flutter.versionName=1.3.36
|
||||
flutter.versionCode=32
|
||||
@@ -1,5 +1,12 @@
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/steward/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/vet_farm/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
|
||||
String getFaUserRole(String? role) {
|
||||
@@ -90,7 +97,7 @@ Map<String, String?> getFaUserRoleWithOnTap(String? role) {
|
||||
case "Poultry":
|
||||
return {"مرغدار": null};
|
||||
case "ProvinceOperator":
|
||||
return {"مدیر اجرایی": null};
|
||||
return {"مدیر اجرایی": ProvinceOperatorRoutes.initProvinceOperator};
|
||||
case "ProvinceFinancial":
|
||||
return {"مالی اتحادیه": null};
|
||||
case "KillHouse":
|
||||
@@ -98,17 +105,17 @@ Map<String, String?> getFaUserRoleWithOnTap(String? role) {
|
||||
case "KillHouseVet":
|
||||
return {"دامپزشک کشتارگاه": null};
|
||||
case "VetFarm":
|
||||
return {"دامپزشک فارم": null};
|
||||
return {"دامپزشک فارم": VetFarmRoutes.initVetFarm};
|
||||
case "Driver":
|
||||
return {"راننده": null};
|
||||
case "ProvinceInspector":
|
||||
return {"بازرس اتحادیه": null};
|
||||
return {"بازرس اتحادیه": ProvinceInspectorRoutes.initProvinceInspector};
|
||||
case "VetSupervisor":
|
||||
return {"دامپزشک کل": null};
|
||||
case "Jahad":
|
||||
return {"جهاد کشاورزی استان": null};
|
||||
return {"جهاد کشاورزی استان": JahadRoutes.initJahad};
|
||||
case "CityJahad":
|
||||
return {"جهاد کشاورزی شهرستان": null};
|
||||
return {"جهاد کشاورزی شهرستان": CityJahadRoutes.initCityJahad};
|
||||
case "ProvincialGovernment":
|
||||
return {"استانداری": null};
|
||||
case "Guilds":
|
||||
@@ -124,7 +131,7 @@ Map<String, String?> getFaUserRoleWithOnTap(String? role) {
|
||||
case "Observatory":
|
||||
return {"رصدخانه": null};
|
||||
case "ProvinceSupervisor":
|
||||
return {"ناظر استان": null};
|
||||
return {"ناظر استان": ProvinceSupervisorRoutes.initProvinceSupervisor};
|
||||
case "GuildRoom":
|
||||
return {"اتاق اصناف": null};
|
||||
case "PosCompany":
|
||||
@@ -132,7 +139,7 @@ Map<String, String?> getFaUserRoleWithOnTap(String? role) {
|
||||
case "LiveStockSupport":
|
||||
return {"پشتیبانی امور دام": null};
|
||||
case "SuperAdmin":
|
||||
return {"ادمین کل": null};
|
||||
return {"ادمین کل": SuperAdminRoutes.initSuperAdmin};
|
||||
case "ChainCompany":
|
||||
return {"شرکت زنجیره": null};
|
||||
case "AdminX":
|
||||
|
||||
@@ -7,6 +7,13 @@ import 'package:rasadyar_chicken/data/repositories/kill_house/kill_house_reposit
|
||||
import 'package:rasadyar_chicken/data/repositories/kill_house/kill_house_repository_impl.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/di/poultry_science_di.dart';
|
||||
import 'package:rasadyar_chicken/features/steward/data/di/steward_di.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/di/province_operator_di.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/di/province_inspector_di.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/di/city_jahad_di.dart';
|
||||
import 'package:rasadyar_chicken/features/vet_farm/data/di/vet_farm_di.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/di/super_admin_di.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/di/province_supervisor_di.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/data/di/jahad_di.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
GetIt diChicken = GetIt.asNewInstance();
|
||||
@@ -58,6 +65,27 @@ Future<void> setupChickenDI() async {
|
||||
// Setup steward feature DI
|
||||
await setupStewardDI(diChicken, dioRemote);
|
||||
|
||||
// Setup province_operator feature DI
|
||||
await setupProvinceOperatorDI(diChicken, dioRemote);
|
||||
|
||||
// Setup province_inspector feature DI
|
||||
await setupProvinceInspectorDI(diChicken, dioRemote);
|
||||
|
||||
// Setup city_jahad feature DI
|
||||
await setupCityJahadDI(diChicken, dioRemote);
|
||||
|
||||
// Setup vet_farm feature DI
|
||||
await setupVetFarmDI(diChicken, dioRemote);
|
||||
|
||||
// Setup super_admin feature DI
|
||||
await setupSuperAdminDI(diChicken, dioRemote);
|
||||
|
||||
// Setup province_supervisor feature DI
|
||||
await setupProvinceSupervisorDI(diChicken, dioRemote);
|
||||
|
||||
// Setup jahad feature DI
|
||||
await setupJahadDI(diChicken, dioRemote);
|
||||
|
||||
//region kill house module DI
|
||||
diChicken.registerLazySingleton<KillHouseRemoteDataSource>(
|
||||
() => KillHouseRemoteDataSourceImpl(diChicken.get<DioRemote>()),
|
||||
@@ -103,10 +131,17 @@ Future<void> newSetupAuthDI(String newUrl) async {
|
||||
final dioRemote = diChicken.get<DioRemote>();
|
||||
await dioRemote.init();
|
||||
|
||||
// --- common, poultry_science, steward
|
||||
// --- common, poultry_science, steward, and other features
|
||||
await setupCommonDI(diChicken, dioRemote);
|
||||
await setupPoultryScienceDI(diChicken, dioRemote);
|
||||
await setupStewardDI(diChicken, dioRemote);
|
||||
await setupProvinceOperatorDI(diChicken, dioRemote);
|
||||
await setupProvinceInspectorDI(diChicken, dioRemote);
|
||||
await setupCityJahadDI(diChicken, dioRemote);
|
||||
await setupVetFarmDI(diChicken, dioRemote);
|
||||
await setupSuperAdminDI(diChicken, dioRemote);
|
||||
await setupProvinceSupervisorDI(diChicken, dioRemote);
|
||||
await setupJahadDI(diChicken, dioRemote);
|
||||
}
|
||||
|
||||
Future<void> reRegister<T extends Object>(T Function() factory) async {
|
||||
|
||||
3
packages/chicken/lib/features/city_jahad/city_jahad.dart
Normal file
3
packages/chicken/lib/features/city_jahad/city_jahad.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
export 'data/di/city_jahad_di.dart';
|
||||
export 'presentation/routes/routes.dart';
|
||||
export 'presentation/routes/pages.dart';
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class CityJahadRemoteDataSource {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/datasources/remote/city_jahad_remote_data_source.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class CityJahadRemoteDataSourceImpl implements CityJahadRemoteDataSource {
|
||||
final DioRemote _httpClient;
|
||||
|
||||
CityJahadRemoteDataSourceImpl(this._httpClient);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
var res = await _httpClient.get(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
queryParameters: queryParameters,
|
||||
fromJson: (json) => PaginationModel<PoultryScienceReport>.fromJson(
|
||||
json,
|
||||
(json) => PoultryScienceReport.fromJson(json as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
await _httpClient.post(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
data: request.toJson(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/datasources/remote/city_jahad_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/datasources/remote/city_jahad_remote_data_source_impl.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/repositories/city_jahad_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/repositories/city_jahad_repository_impl.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
/// Setup dependency injection for city_jahad feature
|
||||
Future<void> setupCityJahadDI(GetIt di, DioRemote dioRemote) async {
|
||||
di.registerLazySingleton<CityJahadRemoteDataSource>(
|
||||
() => CityJahadRemoteDataSourceImpl(dioRemote),
|
||||
);
|
||||
|
||||
di.registerLazySingleton<CityJahadRepository>(
|
||||
() => CityJahadRepositoryImpl(di.get<CityJahadRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Re-register city_jahad dependencies (used when base URL changes)
|
||||
Future<void> reRegisterCityJahadDI(GetIt di, DioRemote dioRemote) async {
|
||||
await reRegister(di, () => CityJahadRemoteDataSourceImpl(dioRemote));
|
||||
await reRegister(
|
||||
di,
|
||||
() => CityJahadRepositoryImpl(di.get<CityJahadRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper function to re-register a dependency
|
||||
Future<void> reRegister<T extends Object>(
|
||||
GetIt di,
|
||||
T Function() factory,
|
||||
) async {
|
||||
if (di.isRegistered<T>()) {
|
||||
await di.unregister<T>();
|
||||
}
|
||||
di.registerLazySingleton<T>(factory);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class CityJahadRepository {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/datasources/remote/city_jahad_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/repositories/city_jahad_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class CityJahadRepositoryImpl implements CityJahadRepository {
|
||||
final CityJahadRemoteDataSource _remote;
|
||||
|
||||
CityJahadRepositoryImpl(this._remote);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
return await _remote.getSubmitInspectionList(
|
||||
token: token,
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
return await _remote.submitInspection(token: token, request: request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.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_chicken/features/city_jahad/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingLogic extends GetxController {
|
||||
CityJahadRootLogic rootLogic = Get.find<CityJahadRootLogic>();
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
late PoultryScienceRepository poultryScienceRepository;
|
||||
Rx<Resource<PaginationModel<HatchingModel>>> activeHatchingList =
|
||||
Resource<PaginationModel<HatchingModel>>.loading().obs;
|
||||
|
||||
final RxBool isLoadingMoreList = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
List<String> routesName = ['اقدام', 'جوجه ریزی فعال'];
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
poultryScienceRepository = diChicken.get<PoultryScienceRepository>();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHatchingList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getHatchingList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreList.value = true;
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await poultryScienceRepository.getHatchingPoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'hatching'},
|
||||
role: 'CityJahad',
|
||||
pageSize: 50,
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.empty();
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.success(
|
||||
PaginationModel<HatchingModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [
|
||||
...(activeHatchingList.value.data?.results ?? []),
|
||||
...(res?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getHatchingList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
|
||||
const ActiveHatchingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasSearch: true,
|
||||
hasFilter: false,
|
||||
backId: cityJahadActionKey,
|
||||
routes: controller.routesName,
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getHatchingList();
|
||||
},
|
||||
child: hatchingWidget(),
|
||||
/*widgets: [
|
||||
hatchingWidget()
|
||||
],*/
|
||||
);
|
||||
}
|
||||
|
||||
Widget hatchingWidget() {
|
||||
return ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
var item = data.value.data!.results![index];
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: val.value.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.activeFramSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingList(true),
|
||||
);
|
||||
}, controller.activeHatchingList);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(HatchingModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 32,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: ShapeDecoration(
|
||||
color: AppColor.blueLight,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: AppColor.blueLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'نژاد:${item.breed?.first.breed ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
' سن${item.age} (روز)',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'شماره مجوز جوجه ریزی',
|
||||
value: item.licenceNumber ?? 'N/A',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.quantity.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.leftOver.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'تلفات',
|
||||
value: item.losses.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value:
|
||||
'${item.vetFarm?.vetFarmFullName}(${item.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false
|
||||
? 'ارسال تصویر جوجه ریزی فارم '
|
||||
: 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
),
|
||||
|
||||
RElevated(
|
||||
height: 40.h,
|
||||
isFullWidth: true,
|
||||
onPressed: () {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().setHatchingModel(
|
||||
item,
|
||||
);
|
||||
Get.bottomSheet(
|
||||
CreateInspectionBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).then((value) {
|
||||
if (Get.isRegistered<CreateInspectionBottomSheetLogic>()) {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().clearForm();
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text('ثبت بازرسی'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(HatchingModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class CityJahadActionItem {
|
||||
final String title;
|
||||
final String route;
|
||||
final String icon;
|
||||
|
||||
CityJahadActionItem({
|
||||
required this.title,
|
||||
required this.route,
|
||||
required this.icon,
|
||||
});
|
||||
}
|
||||
|
||||
class CityJahadHomeLogic extends GetxController {
|
||||
RxList<CityJahadActionItem> items = [
|
||||
CityJahadActionItem(
|
||||
title: "جوجه ریزی فعال",
|
||||
route: CityJahadRoutes.activeHatchingCityJahad,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
CityJahadActionItem(
|
||||
title: "بازرسی مزارع طیور",
|
||||
route: CityJahadRoutes.newInspectionCityJahad,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
].obs;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class CityJahadHomePage extends GetView<CityJahadHomeLogic> {
|
||||
CityJahadHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
hasNews: true,
|
||||
hasNotification: true,
|
||||
child: gridWidget(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget gridWidget() {
|
||||
return ObxValue((data) {
|
||||
return GridView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.symmetric(vertical: 18.h, horizontal: 32.w),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 24.h,
|
||||
crossAxisSpacing: 24.w,
|
||||
),
|
||||
itemCount: data.length,
|
||||
hitTestBehavior: HitTestBehavior.opaque,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = data[index];
|
||||
return GlassMorphismCardIcon(
|
||||
title: item.title,
|
||||
vecIcon: item.icon,
|
||||
onTap: () async {
|
||||
Get.toNamed(item.route, id: cityJahadActionKey);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}, controller.items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class NewInspectionLogic extends GetxController {
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<PoultryScienceReport>>> submitInspectionList =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.loading().obs;
|
||||
|
||||
CityJahadRootLogic rootLogic = Get.find<CityJahadRootLogic>();
|
||||
|
||||
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<PoultryScienceReport>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async =>
|
||||
await rootLogic.cityJahadRepository.getSubmitInspectionList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
role: 'CityJahad',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.empty();
|
||||
} else {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.success(
|
||||
PaginationModel<PoultryScienceReport>(
|
||||
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(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return 'در حال بررسی';
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Color getStatusColor(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return AppColor.yellowNormal;
|
||||
}
|
||||
// میتوانید منطق رنگ را بر اساس inspectionStatus تنظیم کنید
|
||||
return AppColor.greenNormal;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/data/repositories/city_jahad_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/routes/pages.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/common/presentation/page/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class CityJahadRootLogic extends GetxController {
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
late CityJahadRepository cityJahadRepository;
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> homeExpandedList = RxMap();
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
RxInt currentPage = 0.obs;
|
||||
|
||||
final pages = [
|
||||
Navigator(
|
||||
key: Get.nestedKey(cityJahadActionKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = CityJahadPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => CityJahadPages.pages.firstWhere(
|
||||
(e) => e.name == CityJahadRoutes.homeCityJahad,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
cityJahadRepository = diChicken.get<CityJahadRepository>();
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (homeExpandedList.keys.contains(index)) {
|
||||
homeExpandedList.remove(index);
|
||||
} else {
|
||||
homeExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
void popBackTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class CityJahadRootPage extends GetView<CityJahadRootLogic> {
|
||||
const CityJahadRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
onPopScopTaped: controller.popBackTaped,
|
||||
child: ObxValue((data) {
|
||||
return Stack(
|
||||
children: [
|
||||
IndexedStack(children: controller.pages, index: data.value),
|
||||
Positioned(
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
items: [
|
||||
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
cityJahadActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
cityJahadActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.currentPage),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/root/view.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/active_hatching/view.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/new_inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/pages/new_inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/city_jahad/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/global_binding.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class CityJahadPages {
|
||||
CityJahadPages._();
|
||||
|
||||
static List<GetPage> get pages => [
|
||||
GetPage(
|
||||
name: CityJahadRoutes.initCityJahad,
|
||||
page: () => CityJahadRootPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ChickenBaseLogic(), fenix: true);
|
||||
Get.lazyPut(() => CityJahadRootLogic());
|
||||
Get.lazyPut(() => CityJahadHomeLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: CityJahadRoutes.homeCityJahad,
|
||||
page: () => CityJahadHomePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
binding: BindingsBuilder(() {
|
||||
Get.put(CityJahadHomeLogic());
|
||||
Get.lazyPut(() => ChickenBaseLogic());
|
||||
}),
|
||||
),
|
||||
|
||||
GetPage(
|
||||
name: CityJahadRoutes.activeHatchingCityJahad,
|
||||
page: () => ActiveHatchingPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ActiveHatchingLogic());
|
||||
Get.lazyPut(() => CreateInspectionBottomSheetLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: CityJahadRoutes.newInspectionCityJahad,
|
||||
page: () => NewInspectionPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => NewInspectionLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
sealed class CityJahadRoutes {
|
||||
CityJahadRoutes._();
|
||||
|
||||
static const _base = '/chicken/cityJahad';
|
||||
static const initCityJahad = '$_base/';
|
||||
static const homeCityJahad = '$_base/home';
|
||||
static const actionCityJahad = '$_base/action';
|
||||
static const activeHatchingCityJahad = '$_base/activeHatching';
|
||||
static const newInspectionCityJahad = '$_base/newInspection';
|
||||
}
|
||||
@@ -135,7 +135,18 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
result?.accessToken ?? '',
|
||||
);
|
||||
var tmpRoles = result?.role?.where((element) {
|
||||
final allowedRoles = {'poultryscience', 'steward', 'killhouse'};
|
||||
final allowedRoles = {
|
||||
'poultryscience',
|
||||
'steward',
|
||||
'killhouse',
|
||||
'provinceinspector',
|
||||
'cityjahad',
|
||||
'jahad',
|
||||
'vetfarm',
|
||||
'provincesupervisor',
|
||||
'superadmin',
|
||||
};
|
||||
|
||||
final lowerElement = element.toString().toLowerCase().trim();
|
||||
return allowedRoles.contains(lowerElement);
|
||||
}).toList();
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class JahadRemoteDataSource {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/data/datasources/remote/jahad_remote_data_source.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class JahadRemoteDataSourceImpl implements JahadRemoteDataSource {
|
||||
final DioRemote _httpClient;
|
||||
|
||||
JahadRemoteDataSourceImpl(this._httpClient);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
var res = await _httpClient.get(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
queryParameters: queryParameters,
|
||||
fromJson: (json) => PaginationModel<PoultryScienceReport>.fromJson(
|
||||
json,
|
||||
(json) => PoultryScienceReport.fromJson(json as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
await _httpClient.post(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
data: request.toJson(),
|
||||
);
|
||||
}
|
||||
}
|
||||
36
packages/chicken/lib/features/jahad/data/di/jahad_di.dart
Normal file
36
packages/chicken/lib/features/jahad/data/di/jahad_di.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:rasadyar_chicken/features/jahad/data/datasources/remote/jahad_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/data/datasources/remote/jahad_remote_data_source_impl.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/data/repositories/jahad_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/data/repositories/jahad_repository_impl.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
/// Setup dependency injection for jahad feature
|
||||
Future<void> setupJahadDI(GetIt di, DioRemote dioRemote) async {
|
||||
di.registerLazySingleton<JahadRemoteDataSource>(
|
||||
() => JahadRemoteDataSourceImpl(dioRemote),
|
||||
);
|
||||
|
||||
di.registerLazySingleton<JahadRepository>(
|
||||
() => JahadRepositoryImpl(di.get<JahadRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Re-register jahad dependencies (used when base URL changes)
|
||||
Future<void> reRegisterJahadDI(GetIt di, DioRemote dioRemote) async {
|
||||
await reRegister(di, () => JahadRemoteDataSourceImpl(dioRemote));
|
||||
await reRegister(
|
||||
di,
|
||||
() => JahadRepositoryImpl(di.get<JahadRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper function to re-register a dependency
|
||||
Future<void> reRegister<T extends Object>(
|
||||
GetIt di,
|
||||
T Function() factory,
|
||||
) async {
|
||||
if (di.isRegistered<T>()) {
|
||||
await di.unregister<T>();
|
||||
}
|
||||
di.registerLazySingleton<T>(factory);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class JahadRepository {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/data/datasources/remote/jahad_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/data/repositories/jahad_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class JahadRepositoryImpl implements JahadRepository {
|
||||
final JahadRemoteDataSource _remote;
|
||||
|
||||
JahadRepositoryImpl(this._remote);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
return await _remote.getSubmitInspectionList(
|
||||
token: token,
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
return await _remote.submitInspection(token: token, request: request);
|
||||
}
|
||||
}
|
||||
3
packages/chicken/lib/features/jahad/jahad.dart
Normal file
3
packages/chicken/lib/features/jahad/jahad.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
export 'data/di/jahad_di.dart';
|
||||
export 'presentation/routes/routes.dart';
|
||||
export 'presentation/routes/pages.dart';
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/root/logic.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';
|
||||
|
||||
class ActiveHatchingLogic extends GetxController {
|
||||
JahadRootLogic rootLogic = Get.find<JahadRootLogic>();
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
late PoultryScienceRepository poultryScienceRepository;
|
||||
Rx<Resource<PaginationModel<HatchingModel>>> activeHatchingList =
|
||||
Resource<PaginationModel<HatchingModel>>.loading().obs;
|
||||
|
||||
final RxBool isLoadingMoreList = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
List<String> routesName = ['اقدام', 'جوجه ریزی فعال'];
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
poultryScienceRepository = diChicken.get<PoultryScienceRepository>();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHatchingList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getHatchingList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreList.value = true;
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await poultryScienceRepository.getHatchingPoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'hatching'},
|
||||
role: 'Jahad',
|
||||
pageSize: 50,
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.empty();
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.success(
|
||||
PaginationModel<HatchingModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [
|
||||
...(activeHatchingList.value.data?.results ?? []),
|
||||
...(res?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getHatchingList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
|
||||
const ActiveHatchingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasSearch: true,
|
||||
hasFilter: false,
|
||||
backId: jahadActionKey,
|
||||
routes: controller.routesName,
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getHatchingList();
|
||||
},
|
||||
child: hatchingWidget(),
|
||||
/*widgets: [
|
||||
hatchingWidget()
|
||||
],*/
|
||||
);
|
||||
}
|
||||
|
||||
Widget hatchingWidget() {
|
||||
return ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
var item = data.value.data!.results![index];
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: val.value.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.activeFramSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingList(true),
|
||||
);
|
||||
}, controller.activeHatchingList);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(HatchingModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 32,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: ShapeDecoration(
|
||||
color: AppColor.blueLight,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: AppColor.blueLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'نژاد:${item.breed?.first.breed ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
' سن${item.age} (روز)',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'شماره مجوز جوجه ریزی',
|
||||
value: item.licenceNumber ?? 'N/A',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.quantity.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.leftOver.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'تلفات',
|
||||
value: item.losses.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value:
|
||||
'${item.vetFarm?.vetFarmFullName}(${item.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false
|
||||
? 'ارسال تصویر جوجه ریزی فارم '
|
||||
: 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
),
|
||||
|
||||
RElevated(
|
||||
height: 40.h,
|
||||
isFullWidth: true,
|
||||
onPressed: () {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().setHatchingModel(
|
||||
item,
|
||||
);
|
||||
Get.bottomSheet(
|
||||
CreateInspectionBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).then((value) {
|
||||
if (Get.isRegistered<CreateInspectionBottomSheetLogic>()) {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().clearForm();
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text('ثبت بازرسی'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(HatchingModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class JahadActionItem {
|
||||
final String title;
|
||||
final String route;
|
||||
final String icon;
|
||||
|
||||
JahadActionItem({
|
||||
required this.title,
|
||||
required this.route,
|
||||
required this.icon,
|
||||
});
|
||||
}
|
||||
|
||||
class JahadHomeLogic extends GetxController {
|
||||
RxList<JahadActionItem> items = [
|
||||
JahadActionItem(
|
||||
title: "جوجه ریزی فعال",
|
||||
route: JahadRoutes.activeHatchingJahad,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
JahadActionItem(
|
||||
title: "بازرسی مزارع طیور",
|
||||
route: JahadRoutes.newInspectionJahad,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
].obs;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class JahadHomePage extends GetView<JahadHomeLogic> {
|
||||
JahadHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
hasNews: true,
|
||||
hasNotification: true,
|
||||
child: gridWidget(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget gridWidget() {
|
||||
return ObxValue((data) {
|
||||
return GridView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.symmetric(vertical: 18.h, horizontal: 32.w),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 24.h,
|
||||
crossAxisSpacing: 24.w,
|
||||
),
|
||||
itemCount: data.length,
|
||||
hitTestBehavior: HitTestBehavior.opaque,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = data[index];
|
||||
return GlassMorphismCardIcon(
|
||||
title: item.title,
|
||||
vecIcon: item.icon,
|
||||
onTap: () async {
|
||||
Get.toNamed(item.route, id: jahadActionKey);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}, controller.items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class NewInspectionLogic extends GetxController {
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<PoultryScienceReport>>> submitInspectionList =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.loading().obs;
|
||||
|
||||
JahadRootLogic rootLogic = Get.find<JahadRootLogic>();
|
||||
|
||||
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<PoultryScienceReport>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.jahadRepository.getSubmitInspectionList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
role: 'Jahad',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.empty();
|
||||
} else {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.success(
|
||||
PaginationModel<PoultryScienceReport>(
|
||||
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(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return 'در حال بررسی';
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Color getStatusColor(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return AppColor.yellowNormal;
|
||||
}
|
||||
// میتوانید منطق رنگ را بر اساس inspectionStatus تنظیم کنید
|
||||
return AppColor.greenNormal;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/data/repositories/jahad_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/routes/pages.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/common/presentation/page/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class JahadRootLogic extends GetxController {
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
late JahadRepository jahadRepository;
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> homeExpandedList = RxMap();
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
RxInt currentPage = 0.obs;
|
||||
|
||||
final pages = [
|
||||
Navigator(
|
||||
key: Get.nestedKey(jahadActionKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = JahadPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => JahadPages.pages.firstWhere(
|
||||
(e) => e.name == JahadRoutes.homeJahad,
|
||||
),
|
||||
);
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
jahadRepository = diChicken.get<JahadRepository>();
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (homeExpandedList.keys.contains(index)) {
|
||||
homeExpandedList.remove(index);
|
||||
} else {
|
||||
homeExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
void popBackTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class JahadRootPage extends GetView<JahadRootLogic> {
|
||||
const JahadRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
onPopScopTaped: controller.popBackTaped,
|
||||
child: ObxValue((data) {
|
||||
return Stack(
|
||||
children: [
|
||||
IndexedStack(children: controller.pages, index: data.value),
|
||||
Positioned(
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
items: [
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
jahadActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
jahadActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.currentPage),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/root/view.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/active_hatching/view.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/new_inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/pages/new_inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/jahad/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/global_binding.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class JahadPages {
|
||||
JahadPages._();
|
||||
|
||||
static List<GetPage> get pages => [
|
||||
GetPage(
|
||||
name: JahadRoutes.initJahad,
|
||||
page: () => JahadRootPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ChickenBaseLogic(), fenix: true);
|
||||
Get.lazyPut(() => JahadRootLogic());
|
||||
Get.lazyPut(() => JahadHomeLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: JahadRoutes.homeJahad,
|
||||
page: () => JahadHomePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
binding: BindingsBuilder(() {
|
||||
Get.put(JahadHomeLogic());
|
||||
Get.lazyPut(() => ChickenBaseLogic());
|
||||
}),
|
||||
),
|
||||
|
||||
GetPage(
|
||||
name: JahadRoutes.activeHatchingJahad,
|
||||
page: () => ActiveHatchingPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ActiveHatchingLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: JahadRoutes.newInspectionJahad,
|
||||
page: () => NewInspectionPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => NewInspectionLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
sealed class JahadRoutes {
|
||||
JahadRoutes._();
|
||||
|
||||
static const _base = '/chicken/jahad';
|
||||
static const initJahad = '$_base/';
|
||||
static const homeJahad = '$_base/home';
|
||||
static const actionJahad = '$_base/action';
|
||||
static const activeHatchingJahad = '$_base/activeHatching';
|
||||
static const newInspectionJahad = '$_base/newInspection';
|
||||
}
|
||||
@@ -1,4 +1,16 @@
|
||||
/// مدل دادهای برای ارسال اطلاعات بازرسی مرغداری به سرور
|
||||
///
|
||||
/// این کلاس شامل تمام اطلاعات مربوط به بازرسی یک واحد مرغداری است که شامل:
|
||||
/// - موقعیت جغرافیایی (عرض و طول جغرافیایی)
|
||||
/// - شناسه جوجهریزی
|
||||
/// - نقش کاربر
|
||||
/// - اطلاعات مختلف بازرسی در بخشهای مختلف
|
||||
///
|
||||
/// این مدل برای ارسال درخواست POST به endpoint `/poultry_science_report/` استفاده میشود.
|
||||
class SubmitInspectionResponse {
|
||||
/// سازنده کلاس SubmitInspectionResponse
|
||||
///
|
||||
/// تمام پارامترها اختیاری هستند و میتوانند null باشند.
|
||||
SubmitInspectionResponse({
|
||||
this.lat,
|
||||
this.log,
|
||||
@@ -15,20 +27,49 @@ class SubmitInspectionResponse {
|
||||
this.inspectionNotes,
|
||||
});
|
||||
|
||||
/// عرض جغرافیایی (Latitude) محل بازرسی
|
||||
String? lat;
|
||||
|
||||
/// طول جغرافیایی (Longitude) محل بازرسی
|
||||
String? log;
|
||||
|
||||
/// شناسه یکتای جوجهریزی که بازرسی برای آن انجام میشود
|
||||
int? poultryHatchingId;
|
||||
|
||||
/// نقش کاربری که بازرسی را انجام میدهد
|
||||
String? role;
|
||||
|
||||
/// اطلاعات مربوط به شرایط عمومی سالن مرغداری
|
||||
GeneralConditionHall? generalConditionHall;
|
||||
|
||||
/// اطلاعات مربوط به تلفات و خسارات
|
||||
Casualties? casualties;
|
||||
|
||||
/// اطلاعات مربوط به کارشناسان فنی
|
||||
TechnicalOfficer? technicalOfficer;
|
||||
|
||||
/// اطلاعات مربوط به وضعیت نهادهها
|
||||
InputStatus? inputStatus;
|
||||
|
||||
/// اطلاعات مربوط به زیرساخت و انرژی
|
||||
InfrastructureEnergy? infrastructureEnergy;
|
||||
|
||||
/// اطلاعات مربوط به نیروی انسانی
|
||||
Hr? hr;
|
||||
|
||||
/// اطلاعات مربوط به تسهیلات
|
||||
Facilities? facilities;
|
||||
|
||||
/// وضعیت بازرسی (مثلاً: انجام شده، در حال انجام، لغو شده)
|
||||
String? inspectionStatus;
|
||||
|
||||
/// یادداشتها و توضیحات بازرس
|
||||
String? inspectionNotes;
|
||||
|
||||
/// تبدیل شیء به فرمت JSON برای ارسال به سرور
|
||||
///
|
||||
/// تمام اطلاعات بازرسی را در یک ساختار JSON سازماندهی میکند.
|
||||
/// بخشهای مختلف بازرسی در زیر کلید `report_information` قرار میگیرند.
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'lat': lat,
|
||||
@@ -49,6 +90,9 @@ class SubmitInspectionResponse {
|
||||
};
|
||||
}
|
||||
|
||||
/// ساخت شیء از JSON دریافتی از سرور
|
||||
///
|
||||
/// این متد برای تبدیل پاسخ JSON سرور به یک شیء SubmitInspectionResponse استفاده میشود.
|
||||
factory SubmitInspectionResponse.fromJson(Map<String, dynamic> json) {
|
||||
return SubmitInspectionResponse(
|
||||
lat: json['lat'].toString(),
|
||||
@@ -88,7 +132,11 @@ class SubmitInspectionResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/// اطلاعات مربوط به شرایط عمومی سالن مرغداری
|
||||
///
|
||||
/// این کلاس شامل اطلاعاتی در مورد وضعیت سلامت، تهویه، بستر، دما و آب آشامیدنی سالن است.
|
||||
class GeneralConditionHall {
|
||||
/// سازنده کلاس GeneralConditionHall
|
||||
GeneralConditionHall({
|
||||
this.images,
|
||||
this.healthStatus,
|
||||
@@ -99,12 +147,25 @@ class GeneralConditionHall {
|
||||
this.drinkingWaterQuality,
|
||||
});
|
||||
|
||||
/// لیست آدرس تصاویر مربوط به شرایط سالن
|
||||
List<String>? images;
|
||||
|
||||
/// وضعیت سلامت سالن
|
||||
String? healthStatus;
|
||||
|
||||
/// وضعیت سیستم تهویه
|
||||
String? ventilationStatus;
|
||||
|
||||
/// وضعیت بستر سالن
|
||||
String? bedCondition;
|
||||
|
||||
/// دمای سالن
|
||||
String? temperature;
|
||||
|
||||
/// منبع آب آشامیدنی
|
||||
String? drinkingWaterSource;
|
||||
|
||||
/// کیفیت آب آشامیدنی
|
||||
String? drinkingWaterQuality;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
@@ -134,7 +195,12 @@ class GeneralConditionHall {
|
||||
}
|
||||
}
|
||||
|
||||
/// اطلاعات مربوط به تلفات و خسارات
|
||||
///
|
||||
/// این کلاس شامل اطلاعاتی در مورد تلفات عادی و غیرعادی، منبع جوجهریزی،
|
||||
/// علت تلفات غیرعادی، نوع بیماری و نمونهبرداری است.
|
||||
class Casualties {
|
||||
/// سازنده کلاس Casualties
|
||||
Casualties({
|
||||
this.normalLosses,
|
||||
this.abnormalLosses,
|
||||
@@ -146,13 +212,28 @@ class Casualties {
|
||||
this.images,
|
||||
});
|
||||
|
||||
/// تعداد تلفات عادی
|
||||
int? normalLosses;
|
||||
|
||||
/// تعداد تلفات غیرعادی
|
||||
int? abnormalLosses;
|
||||
|
||||
/// منبع جوجهریزی
|
||||
String? sourceOfHatching;
|
||||
|
||||
/// علت تلفات غیرعادی
|
||||
String? causeAbnormalLosses;
|
||||
|
||||
/// نوع بیماری (در صورت وجود)
|
||||
String? typeDisease;
|
||||
|
||||
/// آیا نمونهبرداری انجام شده است؟
|
||||
bool? samplingDone;
|
||||
|
||||
/// نوع نمونهبرداری انجام شده
|
||||
String? typeSampling;
|
||||
|
||||
/// لیست آدرس تصاویر مربوط به تلفات
|
||||
List<String>? images;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
@@ -184,13 +265,20 @@ class Casualties {
|
||||
}
|
||||
}
|
||||
|
||||
/// اطلاعات مربوط به کارشناسان فنی
|
||||
///
|
||||
/// این کلاس شامل اطلاعات کارشناس بهداشت و کارشناس فنی مهندسی است.
|
||||
class TechnicalOfficer {
|
||||
/// سازنده کلاس TechnicalOfficer
|
||||
TechnicalOfficer({
|
||||
this.technicalHealthOfficer,
|
||||
this.technicalEngineeringOfficer,
|
||||
});
|
||||
|
||||
/// نام یا اطلاعات کارشناس بهداشت
|
||||
String? technicalHealthOfficer;
|
||||
|
||||
/// نام یا اطلاعات کارشناس فنی مهندسی
|
||||
String? technicalEngineeringOfficer;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
@@ -209,7 +297,12 @@ class TechnicalOfficer {
|
||||
}
|
||||
}
|
||||
|
||||
/// اطلاعات مربوط به وضعیت نهادهها
|
||||
///
|
||||
/// این کلاس شامل اطلاعاتی در مورد نهادههای مصرفی مرغداری شامل:
|
||||
/// وضعیت نهاده، نام شرکت، کد رهگیری، نوع دان، موجودی انبار و درجه دان است.
|
||||
class InputStatus {
|
||||
/// سازنده کلاس InputStatus
|
||||
InputStatus({
|
||||
this.inputStatus,
|
||||
this.companyName,
|
||||
@@ -221,13 +314,28 @@ class InputStatus {
|
||||
this.images,
|
||||
});
|
||||
|
||||
/// وضعیت نهادهها
|
||||
String? inputStatus;
|
||||
|
||||
/// نام شرکت تامینکننده نهاده
|
||||
String? companyName;
|
||||
|
||||
/// کد رهگیری نهاده
|
||||
String? trackingCode;
|
||||
|
||||
/// نوع دان مصرفی
|
||||
String? typeOfGrain;
|
||||
|
||||
/// موجودی نهاده در انبار
|
||||
String? inventoryInWarehouse;
|
||||
|
||||
/// موجودی نهاده تا زمان بازدید
|
||||
String? inventoryUntilVisit;
|
||||
|
||||
/// درجه دان
|
||||
String? gradeGrain;
|
||||
|
||||
/// لیست آدرس تصاویر مربوط به نهادهها
|
||||
List<String>? images;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
@@ -259,7 +367,12 @@ class InputStatus {
|
||||
}
|
||||
}
|
||||
|
||||
/// اطلاعات مربوط به زیرساخت و انرژی
|
||||
///
|
||||
/// این کلاس شامل اطلاعاتی در مورد ژنراتور، سوخت، قطعی برق و سایر
|
||||
/// اطلاعات مربوط به زیرساخت انرژی مرغداری است.
|
||||
class InfrastructureEnergy {
|
||||
/// سازنده کلاس InfrastructureEnergy
|
||||
InfrastructureEnergy({
|
||||
this.generatorType,
|
||||
this.generatorModel,
|
||||
@@ -274,16 +387,37 @@ class InfrastructureEnergy {
|
||||
this.additionalNotes,
|
||||
});
|
||||
|
||||
/// نوع ژنراتور
|
||||
String? generatorType;
|
||||
|
||||
/// مدل ژنراتور
|
||||
String? generatorModel;
|
||||
|
||||
/// تعداد ژنراتورها
|
||||
String? generatorCount;
|
||||
|
||||
/// ظرفیت ژنراتور
|
||||
String? generatorCapacity;
|
||||
|
||||
/// نوع سوخت ژنراتور
|
||||
String? fuelType;
|
||||
|
||||
/// عملکرد ژنراتور
|
||||
String? generatorPerformance;
|
||||
|
||||
/// موجودی سوخت اضطراری
|
||||
String? emergencyFuelInventory;
|
||||
|
||||
/// آیا سابقه قطعی برق وجود دارد؟
|
||||
bool? hasPowerCutHistory;
|
||||
|
||||
/// مدت زمان قطعی برق
|
||||
String? powerCutDuration;
|
||||
|
||||
/// ساعت قطعی برق
|
||||
String? powerCutHour;
|
||||
|
||||
/// یادداشتهای اضافی
|
||||
String? additionalNotes;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
@@ -319,7 +453,12 @@ class InfrastructureEnergy {
|
||||
}
|
||||
}
|
||||
|
||||
/// اطلاعات مربوط به نیروی انسانی
|
||||
///
|
||||
/// این کلاس شامل اطلاعاتی در مورد تعداد کارکنان، وضعیت بومی/غیربومی بودن
|
||||
/// کارکنان، وضعیت قرارداد و آموزش کارکنان است.
|
||||
class Hr {
|
||||
/// سازنده کلاس Hr
|
||||
Hr({
|
||||
this.numberEmployed,
|
||||
this.numberIndigenous,
|
||||
@@ -328,10 +467,19 @@ class Hr {
|
||||
this.trained,
|
||||
});
|
||||
|
||||
/// تعداد کل کارکنان
|
||||
int? numberEmployed;
|
||||
|
||||
/// تعداد کارکنان بومی
|
||||
int? numberIndigenous;
|
||||
|
||||
/// تعداد کارکنان غیربومی
|
||||
int? numberNonIndigenous;
|
||||
|
||||
/// وضعیت قرارداد کارکنان
|
||||
String? contractStatus;
|
||||
|
||||
/// آیا کارکنان آموزش دیدهاند؟
|
||||
bool? trained;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
@@ -355,7 +503,12 @@ class Hr {
|
||||
}
|
||||
}
|
||||
|
||||
/// اطلاعات مربوط به تسهیلات
|
||||
///
|
||||
/// این کلاس شامل اطلاعاتی در مورد تسهیلات دریافتی مرغداری شامل:
|
||||
/// وجود تسهیلات، نوع تسهیلات، مبلغ، تاریخ و وضعیت بازپرداخت است.
|
||||
class Facilities {
|
||||
/// سازنده کلاس Facilities
|
||||
Facilities({
|
||||
this.hasFacilities,
|
||||
this.typeOfFacility,
|
||||
@@ -365,11 +518,22 @@ class Facilities {
|
||||
this.requestFacilities,
|
||||
});
|
||||
|
||||
/// آیا تسهیلات دریافت شده است؟
|
||||
bool? hasFacilities;
|
||||
|
||||
/// نوع تسهیلات
|
||||
String? typeOfFacility;
|
||||
|
||||
/// مبلغ تسهیلات
|
||||
int? amount;
|
||||
|
||||
/// تاریخ دریافت تسهیلات
|
||||
String? date;
|
||||
|
||||
/// وضعیت بازپرداخت تسهیلات
|
||||
String? repaymentStatus;
|
||||
|
||||
/// درخواست تسهیلات
|
||||
String? requestFacilities;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
||||
@@ -0,0 +1,424 @@
|
||||
{
|
||||
"description": "ساختار و توضیحات کامل مدل SubmitInspectionResponse برای ارسال اطلاعات بازرسی مرغداری",
|
||||
"endpoint": "/poultry_science_report/",
|
||||
"method": "POST",
|
||||
"schema": {
|
||||
"lat": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "عرض جغرافیایی (Latitude) محل بازرسی",
|
||||
"example": "35.6892"
|
||||
},
|
||||
"log": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "طول جغرافیایی (Longitude) محل بازرسی",
|
||||
"example": "51.3890"
|
||||
},
|
||||
"hatching_id": {
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"description": "شناسه یکتای جوجهریزی که بازرسی برای آن انجام میشود",
|
||||
"example": 12345
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نقش کاربری که بازرسی را انجام میدهد",
|
||||
"example": "inspector"
|
||||
},
|
||||
"report_information": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "اطلاعات کامل بازرسی در بخشهای مختلف",
|
||||
"properties": {
|
||||
"general_condition_hall": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "اطلاعات مربوط به شرایط عمومی سالن مرغداری",
|
||||
"properties": {
|
||||
"images": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": false,
|
||||
"description": "لیست آدرس تصاویر مربوط به شرایط سالن"
|
||||
},
|
||||
"health_status": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "وضعیت سلامت سالن"
|
||||
},
|
||||
"ventilation_status": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "وضعیت سیستم تهویه"
|
||||
},
|
||||
"bed_condition": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "وضعیت بستر سالن"
|
||||
},
|
||||
"temperature": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "دمای سالن"
|
||||
},
|
||||
"drinking_water_source": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "منبع آب آشامیدنی"
|
||||
},
|
||||
"drinking_water_quality": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "کیفیت آب آشامیدنی"
|
||||
}
|
||||
}
|
||||
},
|
||||
"casualties": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "اطلاعات مربوط به تلفات و خسارات",
|
||||
"properties": {
|
||||
"normal_losses": {
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"description": "تعداد تلفات عادی",
|
||||
"example": 50
|
||||
},
|
||||
"abnormal_losses": {
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"description": "تعداد تلفات غیرعادی",
|
||||
"example": 10
|
||||
},
|
||||
"source_of_hatching": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "منبع جوجهریزی"
|
||||
},
|
||||
"cause_abnormal_losses": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "علت تلفات غیرعادی"
|
||||
},
|
||||
"type_disease": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نوع بیماری (در صورت وجود)"
|
||||
},
|
||||
"sampling_done": {
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"description": "آیا نمونهبرداری انجام شده است؟",
|
||||
"example": true
|
||||
},
|
||||
"type_sampling": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نوع نمونهبرداری انجام شده"
|
||||
},
|
||||
"images": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": false,
|
||||
"description": "لیست آدرس تصاویر مربوط به تلفات"
|
||||
}
|
||||
}
|
||||
},
|
||||
"technical_officer": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "اطلاعات مربوط به کارشناسان فنی",
|
||||
"properties": {
|
||||
"technical_health_officer": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نام یا اطلاعات کارشناس بهداشت"
|
||||
},
|
||||
"technical_engineering_officer": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نام یا اطلاعات کارشناس فنی مهندسی"
|
||||
}
|
||||
}
|
||||
},
|
||||
"input_status": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "اطلاعات مربوط به وضعیت نهادهها",
|
||||
"properties": {
|
||||
"input_status": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "وضعیت نهادهها"
|
||||
},
|
||||
"company_name": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نام شرکت تامینکننده نهاده"
|
||||
},
|
||||
"tracking_code": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "کد رهگیری نهاده"
|
||||
},
|
||||
"type_of_grain": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نوع دان مصرفی"
|
||||
},
|
||||
"inventory_in_warehouse": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "موجودی نهاده در انبار"
|
||||
},
|
||||
"inventory_until_visit": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "موجودی نهاده تا زمان بازدید"
|
||||
},
|
||||
"grade_grain": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "درجه دان"
|
||||
},
|
||||
"images": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": false,
|
||||
"description": "لیست آدرس تصاویر مربوط به نهادهها"
|
||||
}
|
||||
}
|
||||
},
|
||||
"infrastructure_energy": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "اطلاعات مربوط به زیرساخت و انرژی",
|
||||
"properties": {
|
||||
"generator_type": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نوع ژنراتور"
|
||||
},
|
||||
"generator_model": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "مدل ژنراتور"
|
||||
},
|
||||
"generator_count": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "تعداد ژنراتورها"
|
||||
},
|
||||
"generator_capacity": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "ظرفیت ژنراتور"
|
||||
},
|
||||
"fuel_type": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نوع سوخت ژنراتور"
|
||||
},
|
||||
"generator_performance": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "عملکرد ژنراتور"
|
||||
},
|
||||
"emergency_fuel_inventory": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "موجودی سوخت اضطراری"
|
||||
},
|
||||
"has_power_cut_history": {
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"description": "آیا سابقه قطعی برق وجود دارد؟",
|
||||
"example": true
|
||||
},
|
||||
"power_cut_duration": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "مدت زمان قطعی برق"
|
||||
},
|
||||
"power_cut_hour": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "ساعت قطعی برق"
|
||||
},
|
||||
"additional_notes": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "یادداشتهای اضافی"
|
||||
}
|
||||
}
|
||||
},
|
||||
"hr": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "اطلاعات مربوط به نیروی انسانی",
|
||||
"properties": {
|
||||
"number_employed": {
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"description": "تعداد کل کارکنان",
|
||||
"example": 15
|
||||
},
|
||||
"number_indigenous": {
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"description": "تعداد کارکنان بومی",
|
||||
"example": 10
|
||||
},
|
||||
"number_non_indigenous": {
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"description": "تعداد کارکنان غیربومی",
|
||||
"example": 5
|
||||
},
|
||||
"contract_status": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "وضعیت قرارداد کارکنان"
|
||||
},
|
||||
"trained": {
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"description": "آیا کارکنان آموزش دیدهاند؟",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"facilities": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "اطلاعات مربوط به تسهیلات",
|
||||
"properties": {
|
||||
"has_facilities": {
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"description": "آیا تسهیلات دریافت شده است؟",
|
||||
"example": true
|
||||
},
|
||||
"type_of_facility": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "نوع تسهیلات"
|
||||
},
|
||||
"amount": {
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"description": "مبلغ تسهیلات",
|
||||
"example": 500000000
|
||||
},
|
||||
"date": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "تاریخ دریافت تسهیلات"
|
||||
},
|
||||
"repayment_status": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "وضعیت بازپرداخت تسهیلات"
|
||||
},
|
||||
"request_facilities": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "درخواست تسهیلات"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inspection_status": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "وضعیت بازرسی (مثلاً: انجام شده، در حال انجام، لغو شده)"
|
||||
},
|
||||
"inspection_notes": {
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"description": "یادداشتها و توضیحات بازرس"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"example_request": {
|
||||
"lat": "35.6892",
|
||||
"log": "51.3890",
|
||||
"hatching_id": 12345,
|
||||
"role": "inspector",
|
||||
"report_information": {
|
||||
"general_condition_hall": {
|
||||
"images": [
|
||||
"https://example.com/image1.jpg"
|
||||
],
|
||||
"health_status": "خوب",
|
||||
"ventilation_status": "مناسب",
|
||||
"bed_condition": "تمیز",
|
||||
"temperature": "25",
|
||||
"drinking_water_source": "چاه",
|
||||
"drinking_water_quality": "عالی"
|
||||
},
|
||||
"casualties": {
|
||||
"normal_losses": 50,
|
||||
"abnormal_losses": 10,
|
||||
"source_of_hatching": "مرکز جوجهکشی",
|
||||
"cause_abnormal_losses": "بیماری",
|
||||
"type_disease": "نیوکاسل",
|
||||
"sampling_done": true,
|
||||
"type_sampling": "خون",
|
||||
"images": []
|
||||
},
|
||||
"technical_officer": {
|
||||
"technical_health_officer": "احمد محمدی",
|
||||
"technical_engineering_officer": "علی رضایی"
|
||||
},
|
||||
"input_status": {
|
||||
"input_status": "کافی",
|
||||
"company_name": "شرکت دان",
|
||||
"tracking_code": "TR123456",
|
||||
"type_of_grain": "استارتر",
|
||||
"inventory_in_warehouse": "5000 کیلوگرم",
|
||||
"inventory_until_visit": "4500 کیلوگرم",
|
||||
"grade_grain": "A",
|
||||
"images": []
|
||||
},
|
||||
"infrastructure_energy": {
|
||||
"generator_type": "دیزلی",
|
||||
"generator_model": "کامینز",
|
||||
"generator_count": "2",
|
||||
"generator_capacity": "100 کیلووات",
|
||||
"fuel_type": "گازوئیل",
|
||||
"generator_performance": "عالی",
|
||||
"emergency_fuel_inventory": "5000 لیتر",
|
||||
"has_power_cut_history": true,
|
||||
"power_cut_duration": "2 ساعت",
|
||||
"power_cut_hour": "14:00",
|
||||
"additional_notes": "ژنراتورها به درستی نگهداری میشوند"
|
||||
},
|
||||
"hr": {
|
||||
"number_employed": 15,
|
||||
"number_indigenous": 10,
|
||||
"number_non_indigenous": 5,
|
||||
"contract_status": "قراردادی",
|
||||
"trained": true
|
||||
},
|
||||
"facilities": {
|
||||
"has_facilities": true,
|
||||
"type_of_facility": "وام",
|
||||
"amount": 500000000,
|
||||
"date": "1403/01/15",
|
||||
"repayment_status": "در حال بازپرداخت",
|
||||
"request_facilities": "درخواست تسهیلات جدید"
|
||||
},
|
||||
"inspection_status": "انجام شده",
|
||||
"inspection_notes": "بازرسی با موفقیت انجام شد"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class ProvinceInspectorRemoteDataSource {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/datasources/remote/province_inspector_remote_data_source.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceInspectorRemoteDataSourceImpl
|
||||
implements ProvinceInspectorRemoteDataSource {
|
||||
final DioRemote _httpClient;
|
||||
|
||||
ProvinceInspectorRemoteDataSourceImpl(this._httpClient);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
var res = await _httpClient.get(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
queryParameters: queryParameters,
|
||||
fromJson: (json) => PaginationModel<PoultryScienceReport>.fromJson(
|
||||
json,
|
||||
(json) => PoultryScienceReport.fromJson(json as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
await _httpClient.post(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
data: request.toJson(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/datasources/remote/province_inspector_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/datasources/remote/province_inspector_remote_data_source_impl.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/repositories/province_inspector_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/repositories/province_inspector_repository_impl.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
/// Setup dependency injection for province_inspector feature
|
||||
Future<void> setupProvinceInspectorDI(GetIt di, DioRemote dioRemote) async {
|
||||
di.registerLazySingleton<ProvinceInspectorRemoteDataSource>(
|
||||
() => ProvinceInspectorRemoteDataSourceImpl(dioRemote),
|
||||
);
|
||||
|
||||
di.registerLazySingleton<ProvinceInspectorRepository>(
|
||||
() => ProvinceInspectorRepositoryImpl(di.get<ProvinceInspectorRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Re-register province_inspector dependencies (used when base URL changes)
|
||||
Future<void> reRegisterProvinceInspectorDI(GetIt di, DioRemote dioRemote) async {
|
||||
await reRegister(di, () => ProvinceInspectorRemoteDataSourceImpl(dioRemote));
|
||||
await reRegister(
|
||||
di,
|
||||
() => ProvinceInspectorRepositoryImpl(di.get<ProvinceInspectorRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper function to re-register a dependency
|
||||
Future<void> reRegister<T extends Object>(
|
||||
GetIt di,
|
||||
T Function() factory,
|
||||
) async {
|
||||
if (di.isRegistered<T>()) {
|
||||
await di.unregister<T>();
|
||||
}
|
||||
di.registerLazySingleton<T>(factory);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class ProvinceInspectorRepository {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/datasources/remote/province_inspector_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/repositories/province_inspector_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceInspectorRepositoryImpl implements ProvinceInspectorRepository {
|
||||
final ProvinceInspectorRemoteDataSource _remote;
|
||||
|
||||
ProvinceInspectorRepositoryImpl(this._remote);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
return await _remote.getSubmitInspectionList(
|
||||
token: token,
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
return await _remote.submitInspection(token: token, request: request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.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_chicken/features/province_inspector/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingLogic extends GetxController {
|
||||
ProvinceInspectorRootLogic rootLogic = Get.find<ProvinceInspectorRootLogic>();
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
late PoultryScienceRepository poultryScienceRepository;
|
||||
Rx<Resource<PaginationModel<HatchingModel>>> activeHatchingList =
|
||||
Resource<PaginationModel<HatchingModel>>.loading().obs;
|
||||
|
||||
final RxBool isLoadingMoreList = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
List<String> routesName = ['اقدام', 'جوجه ریزی فعال'];
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
poultryScienceRepository = diChicken.get<PoultryScienceRepository>();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHatchingList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getHatchingList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreList.value = true;
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await poultryScienceRepository.getHatchingPoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'hatching'},
|
||||
role: 'ProvinceInspector',
|
||||
pageSize: 50,
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.empty();
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.success(
|
||||
PaginationModel<HatchingModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [
|
||||
...(activeHatchingList.value.data?.results ?? []),
|
||||
...(res?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getHatchingList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
|
||||
const ActiveHatchingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasSearch: true,
|
||||
hasFilter: false,
|
||||
backId: provinceInspectorActionKey,
|
||||
routes: controller.routesName,
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getHatchingList();
|
||||
},
|
||||
child: hatchingWidget(),
|
||||
/*widgets: [
|
||||
hatchingWidget()
|
||||
],*/
|
||||
);
|
||||
}
|
||||
|
||||
Widget hatchingWidget() {
|
||||
return ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
var item = data.value.data!.results![index];
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: val.value.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.activeFramSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingList(true),
|
||||
);
|
||||
}, controller.activeHatchingList);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(HatchingModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 32,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: ShapeDecoration(
|
||||
color: AppColor.blueLight,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: AppColor.blueLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'نژاد:${item.breed?.first.breed ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
' سن${item.age} (روز)',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'شماره مجوز جوجه ریزی',
|
||||
value: item.licenceNumber ?? 'N/A',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.quantity.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.leftOver.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'تلفات',
|
||||
value: item.losses.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value:
|
||||
'${item.vetFarm?.vetFarmFullName}(${item.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false
|
||||
? 'ارسال تصویر جوجه ریزی فارم '
|
||||
: 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
),
|
||||
|
||||
RElevated(
|
||||
height: 40.h,
|
||||
isFullWidth: true,
|
||||
onPressed: () {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().setHatchingModel(
|
||||
item,
|
||||
);
|
||||
Get.bottomSheet(
|
||||
CreateInspectionBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).then((value) {
|
||||
if (Get.isRegistered<CreateInspectionBottomSheetLogic>()) {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().clearForm();
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text('ثبت بازرسی'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(HatchingModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceInspectorActionItem {
|
||||
final String title;
|
||||
final String route;
|
||||
final String icon;
|
||||
|
||||
ProvinceInspectorActionItem({
|
||||
required this.title,
|
||||
required this.route,
|
||||
required this.icon,
|
||||
});
|
||||
}
|
||||
|
||||
class ProvinceInspectorHomeLogic extends GetxController {
|
||||
RxList<ProvinceInspectorActionItem> items = [
|
||||
ProvinceInspectorActionItem(
|
||||
title: "جوجه ریزی فعال",
|
||||
route: ProvinceInspectorRoutes.activeHatchingProvinceInspector,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
ProvinceInspectorActionItem(
|
||||
title: "بازرسی مزارع طیور",
|
||||
route: ProvinceInspectorRoutes.newInspectionProvinceInspector,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
].obs;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class ProvinceInspectorHomePage extends GetView<ProvinceInspectorHomeLogic> {
|
||||
ProvinceInspectorHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
hasNews: true,
|
||||
hasNotification: true,
|
||||
child: gridWidget(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget gridWidget() {
|
||||
return ObxValue((data) {
|
||||
return GridView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.symmetric(vertical: 18.h, horizontal: 32.w),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 24.h,
|
||||
crossAxisSpacing: 24.w,
|
||||
),
|
||||
itemCount: data.length,
|
||||
hitTestBehavior: HitTestBehavior.opaque,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = data[index];
|
||||
return GlassMorphismCardIcon(
|
||||
title: item.title,
|
||||
vecIcon: item.icon,
|
||||
onTap: () async {
|
||||
Get.toNamed(item.route, id: provinceInspectorActionKey);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}, controller.items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class NewInspectionLogic extends GetxController {
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<PoultryScienceReport>>> submitInspectionList =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.loading().obs;
|
||||
|
||||
ProvinceInspectorRootLogic rootLogic = Get.find<ProvinceInspectorRootLogic>();
|
||||
|
||||
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<PoultryScienceReport>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async =>
|
||||
await rootLogic.provinceInspectorRepository.getSubmitInspectionList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
role: 'ProvinceInspector',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.empty();
|
||||
} else {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.success(
|
||||
PaginationModel<PoultryScienceReport>(
|
||||
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(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return 'در حال بررسی';
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Color getStatusColor(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return AppColor.yellowNormal;
|
||||
}
|
||||
// میتوانید منطق رنگ را بر اساس inspectionStatus تنظیم کنید
|
||||
return AppColor.greenNormal;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/data/repositories/province_inspector_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/common/presentation/page/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/routes/pages.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class ProvinceInspectorRootLogic extends GetxController {
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
late ProvinceInspectorRepository provinceInspectorRepository;
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> homeExpandedList = RxMap();
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
RxInt currentPage = 0.obs;
|
||||
|
||||
final pages = [
|
||||
Navigator(
|
||||
key: Get.nestedKey(provinceInspectorActionKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ProvinceInspectorPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ProvinceInspectorPages.pages.firstWhere(
|
||||
(e) => e.name == ProvinceInspectorRoutes.homeProvinceInspector,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
provinceInspectorRepository = diChicken.get<ProvinceInspectorRepository>();
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (homeExpandedList.keys.contains(index)) {
|
||||
homeExpandedList.remove(index);
|
||||
} else {
|
||||
homeExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
void popBackTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class ProvinceInspectorRootPage extends GetView<ProvinceInspectorRootLogic> {
|
||||
const ProvinceInspectorRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
onPopScopTaped: controller.popBackTaped,
|
||||
child: ObxValue((data) {
|
||||
return Stack(
|
||||
children: [
|
||||
IndexedStack(children: controller.pages, index: data.value),
|
||||
Positioned(
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
items: [
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
provinceInspectorActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
provinceInspectorActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.currentPage),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/root/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/active_hatching/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/new_inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/pages/new_inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_inspector/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/global_binding.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceInspectorPages {
|
||||
ProvinceInspectorPages._();
|
||||
|
||||
static List<GetPage> get pages => [
|
||||
GetPage(
|
||||
name: ProvinceInspectorRoutes.initProvinceInspector,
|
||||
page: () => ProvinceInspectorRootPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ChickenBaseLogic(), fenix: true);
|
||||
Get.lazyPut(() => ProvinceInspectorRootLogic());
|
||||
Get.lazyPut(() => ProvinceInspectorHomeLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceInspectorRoutes.homeProvinceInspector,
|
||||
page: () => ProvinceInspectorHomePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
binding: BindingsBuilder(() {
|
||||
Get.put(ProvinceInspectorHomeLogic());
|
||||
Get.lazyPut(() => ChickenBaseLogic());
|
||||
}),
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceInspectorRoutes.activeHatchingProvinceInspector,
|
||||
page: () => ActiveHatchingPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ActiveHatchingLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceInspectorRoutes.newInspectionProvinceInspector,
|
||||
page: () => NewInspectionPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => NewInspectionLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
sealed class ProvinceInspectorRoutes {
|
||||
ProvinceInspectorRoutes._();
|
||||
|
||||
static const _base = '/chicken/provinceInspector';
|
||||
static const initProvinceInspector = '$_base/';
|
||||
static const homeProvinceInspector = '$_base/home';
|
||||
static const actionProvinceInspector = '$_base/action';
|
||||
static const activeHatchingProvinceInspector = '$_base/activeHatching';
|
||||
static const newInspectionProvinceInspector = '$_base/newInspection';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export 'data/di/province_inspector_di.dart';
|
||||
export 'presentation/routes/routes.dart';
|
||||
export 'presentation/routes/pages.dart';
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class ProvinceOperatorRemoteDataSource {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/datasources/remote/province_operator_remote_data_source.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceOperatorRemoteDataSourceImpl
|
||||
implements ProvinceOperatorRemoteDataSource {
|
||||
final DioRemote _httpClient;
|
||||
|
||||
ProvinceOperatorRemoteDataSourceImpl(this._httpClient);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
var res = await _httpClient.get(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
queryParameters: queryParameters,
|
||||
fromJson: (json) => PaginationModel<PoultryScienceReport>.fromJson(
|
||||
json,
|
||||
(json) => PoultryScienceReport.fromJson(json as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
await _httpClient.post(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
data: request.toJson(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/datasources/remote/province_operator_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/datasources/remote/province_operator_remote_data_source_impl.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/repositories/province_operator_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/repositories/province_operator_repository_impl.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/repositories/poultry_science_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
/// Setup dependency injection for province_operator feature
|
||||
Future<void> setupProvinceOperatorDI(GetIt di, DioRemote dioRemote) async {
|
||||
di.registerLazySingleton<ProvinceOperatorRemoteDataSource>(
|
||||
() => ProvinceOperatorRemoteDataSourceImpl(dioRemote),
|
||||
);
|
||||
|
||||
di.registerLazySingleton<ProvinceOperatorRepository>(
|
||||
() => ProvinceOperatorRepositoryImpl(
|
||||
di.get<ProvinceOperatorRemoteDataSource>(),
|
||||
),
|
||||
);
|
||||
|
||||
// Use PoultryScienceRepository for shared functionality
|
||||
if (!di.isRegistered<PoultryScienceRepository>()) {
|
||||
// PoultryScienceRepository should already be registered, but just in case
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-register province_operator dependencies (used when base URL changes)
|
||||
Future<void> reRegisterProvinceOperatorDI(GetIt di, DioRemote dioRemote) async {
|
||||
await reRegister(di, () => ProvinceOperatorRemoteDataSourceImpl(dioRemote));
|
||||
await reRegister(
|
||||
di,
|
||||
() => ProvinceOperatorRepositoryImpl(
|
||||
di.get<ProvinceOperatorRemoteDataSource>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper function to re-register a dependency
|
||||
Future<void> reRegister<T extends Object>(
|
||||
GetIt di,
|
||||
T Function() factory,
|
||||
) async {
|
||||
if (di.isRegistered<T>()) {
|
||||
await di.unregister<T>();
|
||||
}
|
||||
di.registerLazySingleton<T>(factory);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class ProvinceOperatorRepository {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/datasources/remote/province_operator_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/repositories/province_operator_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceOperatorRepositoryImpl implements ProvinceOperatorRepository {
|
||||
final ProvinceOperatorRemoteDataSource _remote;
|
||||
|
||||
ProvinceOperatorRepositoryImpl(this._remote);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
return await _remote.getSubmitInspectionList(
|
||||
token: token,
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
return await _remote.submitInspection(token: token, request: request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.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_chicken/features/province_operator/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingLogic extends GetxController {
|
||||
ProvinceOperatorRootLogic rootLogic = Get.find<ProvinceOperatorRootLogic>();
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
late PoultryScienceRepository poultryScienceRepository;
|
||||
Rx<Resource<PaginationModel<HatchingModel>>> activeHatchingList =
|
||||
Resource<PaginationModel<HatchingModel>>.loading().obs;
|
||||
|
||||
final RxBool isLoadingMoreList = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
List<String> routesName = ['اقدام', 'جوجه ریزی فعال'];
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
poultryScienceRepository = diChicken.get<PoultryScienceRepository>();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHatchingList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getHatchingList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreList.value = true;
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await poultryScienceRepository.getHatchingPoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'hatching'},
|
||||
role: 'ProvinceOperator',
|
||||
pageSize: 50,
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.empty();
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.success(
|
||||
PaginationModel<HatchingModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [
|
||||
...(activeHatchingList.value.data?.results ?? []),
|
||||
...(res?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getHatchingList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
|
||||
const ActiveHatchingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasSearch: true,
|
||||
hasFilter: false,
|
||||
backId: provinceOperatorActionKey,
|
||||
routes: controller.routesName,
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getHatchingList();
|
||||
},
|
||||
child: hatchingWidget(),
|
||||
/*widgets: [
|
||||
hatchingWidget()
|
||||
],*/
|
||||
);
|
||||
}
|
||||
|
||||
Widget hatchingWidget() {
|
||||
return ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
var item = data.value.data!.results![index];
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: val.value.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.activeFramSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingList(true),
|
||||
);
|
||||
}, controller.activeHatchingList);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(HatchingModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 32,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: ShapeDecoration(
|
||||
color: AppColor.blueLight,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: AppColor.blueLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'نژاد:${item.breed?.first.breed ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
' سن${item.age} (روز)',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'شماره مجوز جوجه ریزی',
|
||||
value: item.licenceNumber ?? 'N/A',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.quantity.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.leftOver.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'تلفات',
|
||||
value: item.losses.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value:
|
||||
'${item.vetFarm?.vetFarmFullName}(${item.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false
|
||||
? 'ارسال تصویر جوجه ریزی فارم '
|
||||
: 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
),
|
||||
|
||||
RElevated(
|
||||
height: 40.h,
|
||||
isFullWidth: true,
|
||||
onPressed: () {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().setHatchingModel(
|
||||
item,
|
||||
);
|
||||
Get.bottomSheet(
|
||||
CreateInspectionBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).then((value) {
|
||||
if (Get.isRegistered<CreateInspectionBottomSheetLogic>()) {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().clearForm();
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text('ثبت بازرسی'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(HatchingModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceOperatorHomeItem {
|
||||
final String title;
|
||||
final String route;
|
||||
final String icon;
|
||||
|
||||
ProvinceOperatorHomeItem({
|
||||
required this.title,
|
||||
required this.route,
|
||||
required this.icon,
|
||||
});
|
||||
}
|
||||
|
||||
class ProvinceOperatorHomeLogic extends GetxController {
|
||||
RxList<ProvinceOperatorHomeItem> items = [
|
||||
ProvinceOperatorHomeItem(
|
||||
title: "جوجه ریزی فعال",
|
||||
route: ProvinceOperatorRoutes.activeHatchingProvinceOperator,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
ProvinceOperatorHomeItem(
|
||||
title: "بازرسی مزارع طیور",
|
||||
route: ProvinceOperatorRoutes.newInspectionProvinceOperator,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
].obs;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class ProvinceOperatorHomePage extends GetView<ProvinceOperatorHomeLogic> {
|
||||
ProvinceOperatorHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
hasNews: true,
|
||||
hasNotification: true,
|
||||
child: gridWidget(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget gridWidget() {
|
||||
return ObxValue((data) {
|
||||
return GridView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.symmetric(vertical: 18.h, horizontal: 32.w),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 24.h,
|
||||
crossAxisSpacing: 24.w,
|
||||
),
|
||||
itemCount: data.length,
|
||||
hitTestBehavior: HitTestBehavior.opaque,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = data[index];
|
||||
return GlassMorphismCardIcon(
|
||||
title: item.title,
|
||||
vecIcon: item.icon,
|
||||
onTap: () async {
|
||||
Get.toNamed(item.route, id: provinceOperatorActionKey);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}, controller.items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class NewInspectionLogic extends GetxController {
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<PoultryScienceReport>>> submitInspectionList =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.loading().obs;
|
||||
|
||||
ProvinceOperatorRootLogic rootLogic = Get.find<ProvinceOperatorRootLogic>();
|
||||
|
||||
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<PoultryScienceReport>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async =>
|
||||
await rootLogic.provinceOperatorRepository.getSubmitInspectionList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
role: 'ProvinceOperator',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.empty();
|
||||
} else {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.success(
|
||||
PaginationModel<PoultryScienceReport>(
|
||||
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(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return 'در حال بررسی';
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Color getStatusColor(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return AppColor.yellowNormal;
|
||||
}
|
||||
// میتوانید منطق رنگ را بر اساس inspectionStatus تنظیم کنید
|
||||
return AppColor.greenNormal;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,83 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/data/repositories/province_operator_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/common/presentation/page/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/routes/pages.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class ProvinceOperatorRootLogic extends GetxController {
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
late ProvinceOperatorRepository provinceOperatorRepository;
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> homeExpandedList = RxMap();
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
RxInt currentPage = 0.obs;
|
||||
|
||||
final pages = [
|
||||
Navigator(
|
||||
key: Get.nestedKey(provinceOperatorActionKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ProvinceOperatorPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ProvinceOperatorPages.pages.firstWhere(
|
||||
(e) => e.name == ProvinceOperatorRoutes.homeProvinceOperator,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
provinceOperatorRepository = diChicken.get<ProvinceOperatorRepository>();
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (homeExpandedList.keys.contains(index)) {
|
||||
homeExpandedList.remove(index);
|
||||
} else {
|
||||
homeExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
void popBackTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class ProvinceOperatorRootPage extends GetView<ProvinceOperatorRootLogic> {
|
||||
const ProvinceOperatorRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
onPopScopTaped: controller.popBackTaped,
|
||||
child: ObxValue((data) {
|
||||
return Stack(
|
||||
children: [
|
||||
IndexedStack(children: controller.pages, index: data.value),
|
||||
Positioned(
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
items: [
|
||||
|
||||
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
provinceOperatorActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
provinceOperatorActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.currentPage),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/root/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/active_hatching/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/new_inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/new_inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/global_binding.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceOperatorPages {
|
||||
ProvinceOperatorPages._();
|
||||
|
||||
static List<GetPage> get pages => [
|
||||
GetPage(
|
||||
name: ProvinceOperatorRoutes.initProvinceOperator,
|
||||
page: () => ProvinceOperatorRootPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ChickenBaseLogic(), fenix: true);
|
||||
Get.lazyPut(() => ProvinceOperatorRootLogic());
|
||||
Get.lazyPut(() => ProvinceOperatorHomeLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceOperatorRoutes.homeProvinceOperator,
|
||||
page: () => ProvinceOperatorHomePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
binding: BindingsBuilder(() {
|
||||
Get.put(ProvinceOperatorHomeLogic());
|
||||
Get.lazyPut(() => ChickenBaseLogic());
|
||||
}),
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceOperatorRoutes.actionProvinceOperator,
|
||||
page: () => ProvinceOperatorHomePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ProvinceOperatorHomeLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceOperatorRoutes.activeHatchingProvinceOperator,
|
||||
page: () => ActiveHatchingPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ActiveHatchingLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceOperatorRoutes.newInspectionProvinceOperator,
|
||||
page: () => NewInspectionPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => NewInspectionLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
sealed class ProvinceOperatorRoutes {
|
||||
ProvinceOperatorRoutes._();
|
||||
|
||||
static const _base = '/chicken/provinceOperator';
|
||||
static const initProvinceOperator = '$_base/';
|
||||
static const homeProvinceOperator = '$_base/home';
|
||||
static const actionProvinceOperator = '$_base/action';
|
||||
static const activeHatchingProvinceOperator = '$_base/activeHatching';
|
||||
static const newInspectionProvinceOperator = '$_base/newInspection';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export 'data/di/province_operator_di.dart';
|
||||
export 'presentation/routes/routes.dart';
|
||||
export 'presentation/routes/pages.dart';
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class ProvinceSupervisorRemoteDataSource {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/datasources/remote/province_supervisor_remote_data_source.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceSupervisorRemoteDataSourceImpl
|
||||
implements ProvinceSupervisorRemoteDataSource {
|
||||
final DioRemote _httpClient;
|
||||
|
||||
ProvinceSupervisorRemoteDataSourceImpl(this._httpClient);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
var res = await _httpClient.get(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
queryParameters: queryParameters,
|
||||
fromJson: (json) => PaginationModel<PoultryScienceReport>.fromJson(
|
||||
json,
|
||||
(json) => PoultryScienceReport.fromJson(json as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
await _httpClient.post(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
data: request.toJson(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/datasources/remote/province_supervisor_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/datasources/remote/province_supervisor_remote_data_source_impl.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/repositories/province_supervisor_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/repositories/province_supervisor_repository_impl.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
/// Setup dependency injection for province_supervisor feature
|
||||
Future<void> setupProvinceSupervisorDI(GetIt di, DioRemote dioRemote) async {
|
||||
di.registerLazySingleton<ProvinceSupervisorRemoteDataSource>(
|
||||
() => ProvinceSupervisorRemoteDataSourceImpl(dioRemote),
|
||||
);
|
||||
|
||||
di.registerLazySingleton<ProvinceSupervisorRepository>(
|
||||
() => ProvinceSupervisorRepositoryImpl(
|
||||
di.get<ProvinceSupervisorRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Re-register province_supervisor dependencies (used when base URL changes)
|
||||
Future<void> reRegisterProvinceSupervisorDI(
|
||||
GetIt di, DioRemote dioRemote) async {
|
||||
await reRegister(
|
||||
di, () => ProvinceSupervisorRemoteDataSourceImpl(dioRemote));
|
||||
await reRegister(
|
||||
di,
|
||||
() => ProvinceSupervisorRepositoryImpl(
|
||||
di.get<ProvinceSupervisorRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper function to re-register a dependency
|
||||
Future<void> reRegister<T extends Object>(
|
||||
GetIt di,
|
||||
T Function() factory,
|
||||
) async {
|
||||
if (di.isRegistered<T>()) {
|
||||
await di.unregister<T>();
|
||||
}
|
||||
di.registerLazySingleton<T>(factory);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class ProvinceSupervisorRepository {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/datasources/remote/province_supervisor_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/repositories/province_supervisor_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceSupervisorRepositoryImpl implements ProvinceSupervisorRepository {
|
||||
final ProvinceSupervisorRemoteDataSource _remote;
|
||||
|
||||
ProvinceSupervisorRepositoryImpl(this._remote);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
return await _remote.getSubmitInspectionList(
|
||||
token: token,
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
return await _remote.submitInspection(token: token, request: request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.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_chicken/features/province_operator/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingLogic extends GetxController {
|
||||
ProvinceOperatorRootLogic rootLogic = Get.find<ProvinceOperatorRootLogic>();
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
late PoultryScienceRepository poultryScienceRepository;
|
||||
Rx<Resource<PaginationModel<HatchingModel>>> activeHatchingList =
|
||||
Resource<PaginationModel<HatchingModel>>.loading().obs;
|
||||
|
||||
final RxBool isLoadingMoreList = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
List<String> routesName = ['اقدام', 'جوجه ریزی فعال'];
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
poultryScienceRepository = diChicken.get<PoultryScienceRepository>();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHatchingList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getHatchingList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreList.value = true;
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await poultryScienceRepository.getHatchingPoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'hatching'},
|
||||
role: 'ProvinceOperator',
|
||||
pageSize: 50,
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.empty();
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.success(
|
||||
PaginationModel<HatchingModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [
|
||||
...(activeHatchingList.value.data?.results ?? []),
|
||||
...(res?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getHatchingList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/features/province_operator/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
|
||||
const ActiveHatchingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasSearch: true,
|
||||
hasFilter: false,
|
||||
backId: provinceOperatorActionKey,
|
||||
routes: controller.routesName,
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getHatchingList();
|
||||
},
|
||||
child: hatchingWidget(),
|
||||
/*widgets: [
|
||||
hatchingWidget()
|
||||
],*/
|
||||
);
|
||||
}
|
||||
|
||||
Widget hatchingWidget() {
|
||||
return ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
var item = data.value.data!.results![index];
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: val.value.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.activeFramSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingList(true),
|
||||
);
|
||||
}, controller.activeHatchingList);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(HatchingModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 32,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: ShapeDecoration(
|
||||
color: AppColor.blueLight,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: AppColor.blueLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'نژاد:${item.breed?.first.breed ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
' سن${item.age} (روز)',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'شماره مجوز جوجه ریزی',
|
||||
value: item.licenceNumber ?? 'N/A',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.quantity.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.leftOver.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'تلفات',
|
||||
value: item.losses.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value:
|
||||
'${item.vetFarm?.vetFarmFullName}(${item.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false
|
||||
? 'ارسال تصویر جوجه ریزی فارم '
|
||||
: 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
),
|
||||
|
||||
RElevated(
|
||||
height: 40.h,
|
||||
isFullWidth: true,
|
||||
onPressed: () {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().setHatchingModel(
|
||||
item,
|
||||
);
|
||||
Get.bottomSheet(
|
||||
CreateInspectionBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).then((value) {
|
||||
if (Get.isRegistered<CreateInspectionBottomSheetLogic>()) {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().clearForm();
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text('ثبت بازرسی'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(HatchingModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceSupervisorActionItem {
|
||||
final String title;
|
||||
final String route;
|
||||
final String icon;
|
||||
|
||||
ProvinceSupervisorActionItem({
|
||||
required this.title,
|
||||
required this.route,
|
||||
required this.icon,
|
||||
});
|
||||
}
|
||||
|
||||
class ProvinceSupervisorHomeLogic extends GetxController {
|
||||
RxList<ProvinceSupervisorActionItem> items = [
|
||||
ProvinceSupervisorActionItem(
|
||||
title: "جوجه ریزی فعال",
|
||||
route: ProvinceSupervisorRoutes.activeHatchingProvinceSupervisor,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
ProvinceSupervisorActionItem(
|
||||
title: "بازرسی مزارع طیور",
|
||||
route: ProvinceSupervisorRoutes.newInspectionProvinceSupervisor,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
].obs;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class ProvinceSupervisorHomePage extends GetView<ProvinceSupervisorHomeLogic> {
|
||||
ProvinceSupervisorHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
hasNews: true,
|
||||
hasNotification: true,
|
||||
child: gridWidget(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget gridWidget() {
|
||||
return ObxValue((data) {
|
||||
return GridView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.symmetric(vertical: 18.h, horizontal: 32.w),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 24.h,
|
||||
crossAxisSpacing: 24.w,
|
||||
),
|
||||
itemCount: data.length,
|
||||
hitTestBehavior: HitTestBehavior.opaque,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = data[index];
|
||||
return GlassMorphismCardIcon(
|
||||
title: item.title,
|
||||
vecIcon: item.icon,
|
||||
onTap: () async {
|
||||
Get.toNamed(item.route, id: provinceSupervisorActionKey);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}, controller.items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class NewInspectionLogic extends GetxController {
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<PoultryScienceReport>>> submitInspectionList =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.loading().obs;
|
||||
|
||||
ProvinceSupervisorRootLogic rootLogic =
|
||||
Get.find<ProvinceSupervisorRootLogic>();
|
||||
|
||||
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<PoultryScienceReport>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async =>
|
||||
await rootLogic.provinceSupervisorRepository.getSubmitInspectionList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
role: 'ProvinceSupervisor',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.empty();
|
||||
} else {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.success(
|
||||
PaginationModel<PoultryScienceReport>(
|
||||
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(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return 'در حال بررسی';
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Color getStatusColor(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return AppColor.yellowNormal;
|
||||
}
|
||||
// میتوانید منطق رنگ را بر اساس inspectionStatus تنظیم کنید
|
||||
return AppColor.greenNormal;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/data/repositories/province_supervisor_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/common/presentation/page/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/routes/pages.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class ProvinceSupervisorRootLogic extends GetxController {
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
late ProvinceSupervisorRepository provinceSupervisorRepository;
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> homeExpandedList = RxMap();
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
RxInt currentPage = 0.obs;
|
||||
|
||||
final pages = [
|
||||
Navigator(
|
||||
key: Get.nestedKey(provinceSupervisorActionKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = ProvinceSupervisorPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => ProvinceSupervisorPages.pages.firstWhere(
|
||||
(e) => e.name == ProvinceSupervisorRoutes.homeProvinceSupervisor,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
provinceSupervisorRepository = diChicken
|
||||
.get<ProvinceSupervisorRepository>();
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (homeExpandedList.keys.contains(index)) {
|
||||
homeExpandedList.remove(index);
|
||||
} else {
|
||||
homeExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
void popBackTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class ProvinceSupervisorRootPage extends GetView<ProvinceSupervisorRootLogic> {
|
||||
const ProvinceSupervisorRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
onPopScopTaped: controller.popBackTaped,
|
||||
child: ObxValue((data) {
|
||||
return Stack(
|
||||
children: [
|
||||
IndexedStack(children: controller.pages, index: data.value),
|
||||
Positioned(
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
items: [
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
provinceSupervisorActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
provinceSupervisorActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.currentPage),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/root/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/new_inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/new_inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/pages/active_hatching/view.dart';
|
||||
import 'package:rasadyar_chicken/features/province_supervisor/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/global_binding.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ProvinceSupervisorPages {
|
||||
ProvinceSupervisorPages._();
|
||||
|
||||
static List<GetPage> get pages => [
|
||||
GetPage(
|
||||
name: ProvinceSupervisorRoutes.initProvinceSupervisor,
|
||||
page: () => ProvinceSupervisorRootPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ChickenBaseLogic(), fenix: true);
|
||||
Get.lazyPut(() => ProvinceSupervisorRootLogic());
|
||||
Get.lazyPut(() => ProvinceSupervisorHomeLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceSupervisorRoutes.homeProvinceSupervisor,
|
||||
page: () => ProvinceSupervisorHomePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
binding: BindingsBuilder(() {
|
||||
Get.put(ProvinceSupervisorHomeLogic());
|
||||
Get.lazyPut(() => ChickenBaseLogic());
|
||||
}),
|
||||
),
|
||||
|
||||
GetPage(
|
||||
name: ProvinceSupervisorRoutes.activeHatchingProvinceSupervisor,
|
||||
page: () => ActiveHatchingPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ActiveHatchingLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: ProvinceSupervisorRoutes.newInspectionProvinceSupervisor,
|
||||
page: () => NewInspectionPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => NewInspectionLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
sealed class ProvinceSupervisorRoutes {
|
||||
ProvinceSupervisorRoutes._();
|
||||
|
||||
static const _base = '/chicken/provinceSupervisor';
|
||||
static const initProvinceSupervisor = '$_base/';
|
||||
static const homeProvinceSupervisor = '$_base/home';
|
||||
static const actionProvinceSupervisor = '$_base/action';
|
||||
static const activeHatchingProvinceSupervisor = '$_base/activeHatching';
|
||||
static const newInspectionProvinceSupervisor = '$_base/newInspection';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export 'data/di/province_supervisor_di.dart';
|
||||
export 'presentation/routes/routes.dart';
|
||||
export 'presentation/routes/pages.dart';
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class SuperAdminRemoteDataSource {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/datasources/remote/super_admin_remote_data_source.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SuperAdminRemoteDataSourceImpl implements SuperAdminRemoteDataSource {
|
||||
final DioRemote _httpClient;
|
||||
|
||||
SuperAdminRemoteDataSourceImpl(this._httpClient);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
var res = await _httpClient.get(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
queryParameters: queryParameters,
|
||||
fromJson: (json) => PaginationModel<PoultryScienceReport>.fromJson(
|
||||
json,
|
||||
(json) => PoultryScienceReport.fromJson(json as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
await _httpClient.post(
|
||||
'/poultry_science_report/',
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
data: request.toJson(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/datasources/remote/super_admin_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/datasources/remote/super_admin_remote_data_source_impl.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/repositories/super_admin_repository.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/repositories/super_admin_repository_impl.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
/// Setup dependency injection for super_admin feature
|
||||
Future<void> setupSuperAdminDI(GetIt di, DioRemote dioRemote) async {
|
||||
di.registerLazySingleton<SuperAdminRemoteDataSource>(
|
||||
() => SuperAdminRemoteDataSourceImpl(dioRemote),
|
||||
);
|
||||
|
||||
di.registerLazySingleton<SuperAdminRepository>(
|
||||
() => SuperAdminRepositoryImpl(di.get<SuperAdminRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Re-register super_admin dependencies (used when base URL changes)
|
||||
Future<void> reRegisterSuperAdminDI(GetIt di, DioRemote dioRemote) async {
|
||||
await reRegister(di, () => SuperAdminRemoteDataSourceImpl(dioRemote));
|
||||
await reRegister(
|
||||
di,
|
||||
() => SuperAdminRepositoryImpl(di.get<SuperAdminRemoteDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper function to re-register a dependency
|
||||
Future<void> reRegister<T extends Object>(
|
||||
GetIt di,
|
||||
T Function() factory,
|
||||
) async {
|
||||
if (di.isRegistered<T>()) {
|
||||
await di.unregister<T>();
|
||||
}
|
||||
di.registerLazySingleton<T>(factory);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
abstract class SuperAdminRepository {
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
});
|
||||
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/datasources/remote/super_admin_remote_data_source.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/repositories/super_admin_repository.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SuperAdminRepositoryImpl implements SuperAdminRepository {
|
||||
final SuperAdminRemoteDataSource _remote;
|
||||
|
||||
SuperAdminRepositoryImpl(this._remote);
|
||||
|
||||
@override
|
||||
Future<PaginationModel<PoultryScienceReport>?> getSubmitInspectionList({
|
||||
required String token,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
return await _remote.getSubmitInspectionList(
|
||||
token: token,
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitInspection({
|
||||
required String token,
|
||||
required SubmitInspectionResponse request,
|
||||
}) async {
|
||||
return await _remote.submitInspection(token: token, request: request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.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_chicken/features/super_admin/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingLogic extends GetxController {
|
||||
SuperAdminRootLogic rootLogic = Get.find<SuperAdminRootLogic>();
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
late PoultryScienceRepository poultryScienceRepository;
|
||||
Rx<Resource<PaginationModel<HatchingModel>>> activeHatchingList =
|
||||
Resource<PaginationModel<HatchingModel>>.loading().obs;
|
||||
|
||||
final RxBool isLoadingMoreList = false.obs;
|
||||
RxInt currentPage = 1.obs;
|
||||
RxInt expandedIndex = RxInt(-1);
|
||||
List<String> routesName = ['اقدام', 'جوجه ریزی فعال'];
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
RxnString searchedValue = RxnString();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
poultryScienceRepository = diChicken.get<PoultryScienceRepository>();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
getHatchingList();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
baseLogic.clearSearch();
|
||||
}
|
||||
|
||||
Future<void> getHatchingList([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreList.value = true;
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await poultryScienceRepository.getHatchingPoultry(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
queryParams: {'type': 'hatching'},
|
||||
role: 'SuperAdmin',
|
||||
pageSize: 50,
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.empty();
|
||||
} else {
|
||||
activeHatchingList.value =
|
||||
Resource<PaginationModel<HatchingModel>>.success(
|
||||
PaginationModel<HatchingModel>(
|
||||
count: res?.count ?? 0,
|
||||
next: res?.next,
|
||||
previous: res?.previous,
|
||||
results: [
|
||||
...(activeHatchingList.value.data?.results ?? []),
|
||||
...(res?.results ?? []),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
expandedIndex.value = expandedIndex.value == index ? -1 : index;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
currentPage.value = 1;
|
||||
await getHatchingList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/hatching/hatching_models.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/create_inspection_bottom_sheet_logic.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ActiveHatchingPage extends GetView<ActiveHatchingLogic> {
|
||||
const ActiveHatchingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
hasSearch: true,
|
||||
hasFilter: false,
|
||||
backId: superAdminActionKey,
|
||||
routes: controller.routesName,
|
||||
onSearchChanged: (data) {
|
||||
controller.searchedValue.value = data;
|
||||
controller.getHatchingList();
|
||||
},
|
||||
child: hatchingWidget(),
|
||||
/*widgets: [
|
||||
hatchingWidget()
|
||||
],*/
|
||||
);
|
||||
}
|
||||
|
||||
Widget hatchingWidget() {
|
||||
return ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||
itemBuilder: (context, index) {
|
||||
var item = data.value.data!.results![index];
|
||||
return ObxValue((val) {
|
||||
return ExpandableListItem2(
|
||||
selected: val.value.isEqual(index),
|
||||
onTap: () => controller.toggleExpanded(index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.activeFramSvg.path,
|
||||
);
|
||||
}, controller.expandedIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
onLoadMore: () async => controller.getHatchingList(true),
|
||||
);
|
||||
}, controller.activeHatchingList);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(HatchingModel item) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
|
||||
Visibility(
|
||||
child: Text(
|
||||
item.violation == true ? 'پیگیری' : 'عادی',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.redDark),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 32,
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: ShapeDecoration(
|
||||
color: AppColor.blueLight,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: AppColor.blueLightHover),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'نژاد:${item.breed?.first.breed ?? 'N/A'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
Text(
|
||||
' سن${item.age} (روز)',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
' دوره جوجه ریزی:${item.period}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'شماره مجوز جوجه ریزی',
|
||||
value: item.licenceNumber ?? 'N/A',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'حجم جوجه ریزی',
|
||||
value: item.quantity.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'مانده در سالن',
|
||||
value: item.leftOver.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildUnitRow(
|
||||
title: 'تلفات',
|
||||
value: item.losses.separatedByCommaFa,
|
||||
unit: '(قطعه)',
|
||||
),
|
||||
buildRow(
|
||||
title: 'دامپزشک فارم',
|
||||
value:
|
||||
'${item.vetFarm?.vetFarmFullName}(${item.vetFarm?.vetFarmMobile})',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شرح بازرسی',
|
||||
value: item.reportInfo?.image == false
|
||||
? 'ارسال تصویر جوجه ریزی فارم '
|
||||
: 'تکمیل شده',
|
||||
titleStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
valueStyle: AppFonts.yekan14.copyWith(
|
||||
color: (item.reportInfo?.image ?? false)
|
||||
? AppColor.greenNormal
|
||||
: AppColor.redDark,
|
||||
),
|
||||
),
|
||||
|
||||
RElevated(
|
||||
height: 40.h,
|
||||
isFullWidth: true,
|
||||
onPressed: () {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().setHatchingModel(
|
||||
item,
|
||||
);
|
||||
Get.bottomSheet(
|
||||
CreateInspectionBottomSheet(),
|
||||
isScrollControlled: true,
|
||||
ignoreSafeArea: false,
|
||||
).then((value) {
|
||||
if (Get.isRegistered<CreateInspectionBottomSheetLogic>()) {
|
||||
Get.find<CreateInspectionBottomSheetLogic>().clearForm();
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text('ثبت بازرسی'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget itemListWidget(HatchingModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 3,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.user?.fullname ?? 'N/A',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.user?.mobile ?? 'N/A',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.poultry?.unitName ?? 'N/Aaq',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||
),
|
||||
Text(
|
||||
item.poultry?.licenceNumber ?? 'N/A',
|
||||
textAlign: TextAlign.left,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Assets.vec.scanSvg.svg(
|
||||
width: 32.w,
|
||||
height: 32.h,
|
||||
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SuperAdminHomeItem {
|
||||
final String title;
|
||||
final String route;
|
||||
final String icon;
|
||||
|
||||
SuperAdminHomeItem({required this.title, required this.route, required this.icon});
|
||||
}
|
||||
|
||||
class SuperAdminHomeLogic extends GetxController {
|
||||
RxList<SuperAdminHomeItem> items = [
|
||||
SuperAdminHomeItem(
|
||||
title: "جوجه ریزی فعال",
|
||||
route: SuperAdminRoutes.activeHatchingSuperAdmin,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
SuperAdminHomeItem(
|
||||
title: "بازرسی مزارع طیور",
|
||||
route: SuperAdminRoutes.newInspectionSuperAdmin,
|
||||
icon: Assets.vec.activeFramSvg.path,
|
||||
),
|
||||
].obs;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class SuperAdminHomePage extends GetView<SuperAdminHomeLogic> {
|
||||
SuperAdminHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isBase: true,
|
||||
hasNews: true,
|
||||
hasNotification: true,
|
||||
child: gridWidget(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget gridWidget() {
|
||||
return ObxValue((data) {
|
||||
return GridView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.symmetric(vertical: 18.h, horizontal: 32.w),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 24.h,
|
||||
crossAxisSpacing: 24.w,
|
||||
),
|
||||
itemCount: data.length,
|
||||
hitTestBehavior: HitTestBehavior.opaque,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = data[index];
|
||||
return GlassMorphismCardIcon(
|
||||
title: item.title,
|
||||
vecIcon: item.icon,
|
||||
onTap: () async {
|
||||
Get.toNamed(item.route, id: superAdminActionKey);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}, controller.items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class NewInspectionLogic extends GetxController {
|
||||
BaseLogic baseLogic = Get.find<BaseLogic>();
|
||||
|
||||
Rx<Resource<PaginationModel<PoultryScienceReport>>> submitInspectionList =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.loading().obs;
|
||||
|
||||
SuperAdminRootLogic rootLogic = Get.find<SuperAdminRootLogic>();
|
||||
|
||||
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<PoultryScienceReport>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async =>
|
||||
await rootLogic.superAdminRepository.getSubmitInspectionList(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
role: 'SuperAdmin',
|
||||
pageSize: 50,
|
||||
search: 'filter',
|
||||
|
||||
page: currentPage.value,
|
||||
),
|
||||
),
|
||||
onSuccess: (res) {
|
||||
if ((res?.count ?? 0) == 0) {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.empty();
|
||||
} else {
|
||||
submitInspectionList.value =
|
||||
Resource<PaginationModel<PoultryScienceReport>>.success(
|
||||
PaginationModel<PoultryScienceReport>(
|
||||
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(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return 'در حال بررسی';
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Color getStatusColor(PoultryScienceReport item) {
|
||||
final status = item.reportInformation?.inspectionStatus ?? item.state;
|
||||
if (status == null || status.isEmpty) {
|
||||
return AppColor.yellowNormal;
|
||||
}
|
||||
// میتوانید منطق رنگ را بر اساس inspectionStatus تنظیم کنید
|
||||
return AppColor.greenNormal;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/data/repositories/super_admin_repository.dart';
|
||||
|
||||
import 'package:rasadyar_chicken/features/common/presentation/page/profile/view.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/routes/pages.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
|
||||
|
||||
class SuperAdminRootLogic extends GetxController {
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
late SuperAdminRepository superAdminRepository;
|
||||
|
||||
RxList<ErrorLocationType> errorLocationType = RxList();
|
||||
RxMap<int, dynamic> homeExpandedList = RxMap();
|
||||
DateTime? _lastBackPressed;
|
||||
|
||||
RxInt currentPage = 0.obs;
|
||||
|
||||
final pages = [
|
||||
Navigator(
|
||||
key: Get.nestedKey(superAdminActionKey),
|
||||
onGenerateRoute: (settings) {
|
||||
final page = SuperAdminPages.pages.firstWhere(
|
||||
(e) => e.name == settings.name,
|
||||
orElse: () => SuperAdminPages.pages.firstWhere(
|
||||
(e) => e.name == SuperAdminRoutes.homeSuperAdmin,
|
||||
),
|
||||
);
|
||||
|
||||
return buildRouteFromGetPage(page);
|
||||
},
|
||||
),
|
||||
|
||||
ProfilePage(),
|
||||
];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
superAdminRepository = diChicken.get<SuperAdminRepository>();
|
||||
}
|
||||
|
||||
void toggleExpanded(int index) {
|
||||
if (homeExpandedList.keys.contains(index)) {
|
||||
homeExpandedList.remove(index);
|
||||
} else {
|
||||
homeExpandedList[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void rootErrorHandler(DioException error) {
|
||||
handleGeneric(error, () {
|
||||
tokenService.deleteModuleTokens(Module.chicken);
|
||||
});
|
||||
}
|
||||
|
||||
void changePage(int index) {
|
||||
currentPage.value = index;
|
||||
}
|
||||
|
||||
void popBackTaped() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastBackPressed == null ||
|
||||
now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
|
||||
_lastBackPressed = now;
|
||||
Get.snackbar(
|
||||
'خروج از برنامه',
|
||||
'برای خروج دوباره بازگشت را بزنید',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: AppColor.warning,
|
||||
);
|
||||
} else {
|
||||
await SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class SuperAdminRootPage extends GetView<SuperAdminRootLogic> {
|
||||
const SuperAdminRootPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
isFullScreen: true,
|
||||
onPopScopTaped: controller.popBackTaped,
|
||||
child: ObxValue((data) {
|
||||
return Stack(
|
||||
children: [
|
||||
IndexedStack(children: controller.pages, index: data.value),
|
||||
Positioned(
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: RBottomNavigation(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
items: [
|
||||
|
||||
RBottomNavigationItem(
|
||||
label: 'خانه',
|
||||
icon: Assets.vec.homeSvg.path,
|
||||
isSelected: controller.currentPage.value == 0,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
superAdminActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(0);
|
||||
},
|
||||
),
|
||||
RBottomNavigationItem(
|
||||
label: 'پروفایل',
|
||||
icon: Assets.vec.profileCircleSvg.path,
|
||||
isSelected: controller.currentPage.value == 1,
|
||||
onTap: () {
|
||||
Get.nestedKey(
|
||||
superAdminActionKey,
|
||||
)?.currentState?.popUntil((route) => route.isFirst);
|
||||
controller.changePage(1);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}, controller.currentPage),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/home/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/home/view.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/root/view.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/active_hatching/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/active_hatching/view.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/new_inspection/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/pages/new_inspection/view.dart';
|
||||
import 'package:rasadyar_chicken/features/super_admin/presentation/routes/routes.dart';
|
||||
import 'package:rasadyar_chicken/presentation/routes/global_binding.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SuperAdminPages {
|
||||
SuperAdminPages._();
|
||||
|
||||
static List<GetPage> get pages => [
|
||||
GetPage(
|
||||
name: SuperAdminRoutes.initSuperAdmin,
|
||||
page: () => SuperAdminRootPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ChickenBaseLogic(), fenix: true);
|
||||
Get.lazyPut(() => SuperAdminRootLogic());
|
||||
Get.lazyPut(() => SuperAdminHomeLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: SuperAdminRoutes.homeSuperAdmin,
|
||||
page: () => SuperAdminHomePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
binding: BindingsBuilder(() {
|
||||
Get.put(SuperAdminHomeLogic());
|
||||
Get.lazyPut(() => ChickenBaseLogic());
|
||||
}),
|
||||
),
|
||||
GetPage(
|
||||
name: SuperAdminRoutes.actionSuperAdmin,
|
||||
page: () => SuperAdminHomePage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => SuperAdminHomeLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: SuperAdminRoutes.activeHatchingSuperAdmin,
|
||||
page: () => ActiveHatchingPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => ActiveHatchingLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
GetPage(
|
||||
name: SuperAdminRoutes.newInspectionSuperAdmin,
|
||||
page: () => NewInspectionPage(),
|
||||
middlewares: [AuthMiddleware()],
|
||||
bindings: [
|
||||
GlobalBinding(),
|
||||
BindingsBuilder(() {
|
||||
Get.lazyPut(() => NewInspectionLogic());
|
||||
}),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user