diff --git a/packages/inspection/lib/presentation/pages/inspection_map/logic.dart b/packages/inspection/lib/presentation/pages/inspection_map/logic.dart index 39ba16a..efbaeec 100644 --- a/packages/inspection/lib/presentation/pages/inspection_map/logic.dart +++ b/packages/inspection/lib/presentation/pages/inspection_map/logic.dart @@ -18,7 +18,7 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin Resource>.loading().obs; RxList markers = [].obs; - + RxList markers2 = [].obs; Timer? _debounceTimer; RxBool isLoading = false.obs; @@ -133,46 +133,8 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin radius * 1000, ); - final visibleBounds = animatedMapController.mapController.camera.visibleBounds; - final isZoomedIn = zoom > 17; + markers2.addAll(filtered); - final updatedMarkers = filtered.map((location) { - final point = LatLng(location.lat ?? 0, location.long ?? 0); - final isVisible = visibleBounds.contains(point); - - return Marker( - point: point, - width: isZoomedIn && isVisible ? 180.w : 40.h, - height: isZoomedIn && isVisible ? 50.h : 50.h, - child: isZoomedIn && isVisible - ? Container( - height: 30.h, - padding: EdgeInsets.all(5.r), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15.r), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.1), - blurRadius: 5, - offset: const Offset(0, 2), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 8, - children: [ - Assets.vec.chickenMapMarkerSvg.svg(width: 24.w, height: 24.h), - Text(location.user?.fullname ?? '',style: AppFonts.yekan12,), - ], - ), - ) - : Assets.vec.chickenMapMarkerSvg.svg(width: 24.w, height: 24.h), - ); - }).toList(); - - markers.value = updatedMarkers; }); } diff --git a/packages/inspection/lib/presentation/pages/inspection_map/map_widget.dart b/packages/inspection/lib/presentation/pages/inspection_map/map_widget.dart new file mode 100644 index 0000000..5b981f4 --- /dev/null +++ b/packages/inspection/lib/presentation/pages/inspection_map/map_widget.dart @@ -0,0 +1,108 @@ +// widgets/map_widgets.dart +import 'package:flutter/material.dart'; +import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_inspection/presentation/pages/inspection_map/logic.dart'; +import 'package:rasadyar_inspection/presentation/widget/search.dart'; + +class MapView extends GetView { + const MapView({super.key}); + + @override + Widget build(BuildContext context) { + return Expanded( + child: Stack( + fit: StackFit.expand, + children: [ + _buildFlutterMap(), + _buildSearchOverlay(), + ], + ), + ); + } + + Widget _buildFlutterMap() { + return ObxValue( + (currentLocation) => FlutterMap( + mapController: controller.animatedMapController.mapController, + options: MapOptions( + initialCenter: currentLocation.value, + interactionOptions: const InteractionOptions( + flags: InteractiveFlag.all & ~InteractiveFlag.rotate, + ), + initialZoom: 15, + onPositionChanged: _handlePositionChanged, + ), + children: [ + _buildTileLayer(), + _buildMarkerClusterLayer(), + ], + ), + controller.currentLocation, + ); + } + + Widget _buildTileLayer() { + return TileLayer( + urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + userAgentPackageName: 'ir.mnpc.rasadyar', + ); + } + + Widget _buildMarkerClusterLayer() { + return ObxValue( + (markers) => MarkerClusterLayerWidget( + options: MarkerClusterLayerOptions( + maxClusterRadius: 80, + size: const Size(40, 40), + alignment: Alignment.center, + padding: const EdgeInsets.all(50), + maxZoom: 15, + markers: markers.value, + builder: _buildClusterMarker, + ), + ), + controller.markers, + ); + } + + Widget _buildClusterMarker(BuildContext context, List clusterMarkers) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.blue, + ), + child: Center( + child: Text( + clusterMarkers.length.toString(), + style: const TextStyle(color: Colors.white), + ), + ), + ); + } + + Widget _buildSearchOverlay() { + return Positioned( + top: 10, + left: 20, + right: 20, + child: ObxValue( + (isSearchSelected) => isSearchSelected.value + ? SearchWidget( + onSearchChanged: (data) { + controller.baseLogic.searchValue.value = data; + }, + ) + : const SizedBox.shrink(), + controller.baseLogic.isSearchSelected, + ), + ); + } + + void _handlePositionChanged(MapCamera camera, bool hasGesture) { + wLog(camera.zoom); + controller.debouncedUpdateVisibleMarkers( + center: camera.center, + zoom: camera.zoom, + ); + } +} diff --git a/packages/inspection/lib/presentation/pages/inspection_map/view.dart b/packages/inspection/lib/presentation/pages/inspection_map/view.dart index 9c5a75e..f662605 100644 --- a/packages/inspection/lib/presentation/pages/inspection_map/view.dart +++ b/packages/inspection/lib/presentation/pages/inspection_map/view.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart'; import 'package:rasadyar_inspection/presentation/routes/app_routes.dart'; import 'package:rasadyar_inspection/presentation/widget/base_page/view.dart'; import 'package:rasadyar_inspection/presentation/widget/custom_chips.dart'; @@ -16,18 +17,18 @@ class InspectionMapPage extends GetView { hasSearch: true, hasFilter: true, hasBack: false, - defaultSearch: false, filteringWidget: filterWidget(showIndex: 3.obs, filterIndex: 5.obs), - onSearchTap: () { - controller.baseLogic.isSearchSelected.value = !controller.baseLogic.isSearchSelected.value; - }, - + onSearchTap: _handleSearchTap, widgets: [_buildMap()], floatingActionButton: _buildGpsButton(), ); } + void _handleSearchTap() { + controller.baseLogic.isSearchSelected.value = !controller.baseLogic.isSearchSelected.value; + } + Widget _buildMap() { return Expanded( child: Stack( @@ -43,7 +44,6 @@ class InspectionMapPage extends GetView { ), initialZoom: 15, onPositionChanged: (camera, hasGesture) { - wLog(camera.zoom); controller.debouncedUpdateVisibleMarkers( center: camera.center, zoom: camera.zoom, @@ -57,35 +57,32 @@ class InspectionMapPage extends GetView { userAgentPackageName: 'ir.mnpc.rasadyar', ), - ObxValue( - (markers) { - return MarkerClusterLayerWidget( - options: MarkerClusterLayerOptions( - maxClusterRadius: 80, - size: const Size(40, 40), - alignment: Alignment.center, - padding: const EdgeInsets.all(50), - maxZoom: 15, - markers: markers.value, - builder: (context, clusterMarkers) { - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.blue, + ObxValue((markers) { + return MarkerClusterLayerWidget( + options: MarkerClusterLayerOptions( + maxClusterRadius: 80, + size: const Size(40, 40), + alignment: Alignment.center, + padding: const EdgeInsets.all(50), + maxZoom: 15, + markers: buildMarkers(markers), + builder: (context, clusterMarkers) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.blue, + ), + child: Center( + child: Text( + clusterMarkers.length.toString(), + style: const TextStyle(color: Colors.white), ), - child: Center( - child: Text( - clusterMarkers.length.toString(), - style: const TextStyle(color: Colors.white), - ), - ), - ); - }, - ), - ); - }, - controller.markers, - ), + ), + ); + }, + ), + ); + }, controller.markers2), ], ); }, controller.currentLocation), @@ -305,6 +302,263 @@ class InspectionMapPage extends GetView { ); }, controller.isSelectedDetailsLocation); } + + List buildMarkers(RxList markers) { + final visibleBounds = controller.animatedMapController.mapController.camera.visibleBounds; + final isZoomedIn = controller.currentZoom > 17; + + final updatedMarkers = markers.map((location) { + final point = LatLng(location.lat ?? 0, location.long ?? 0); + final isVisible = visibleBounds.contains(point); + + return Marker( + point: point, + width: isZoomedIn && isVisible ? 180.w : 40.h, + height: isZoomedIn && isVisible ? 50.h : 50.h, + child: isZoomedIn && isVisible + ? GestureDetector( + onTap: () { + Get.bottomSheet( + ObxValue((data) { + return BaseBottomSheet( + height: data.value ? 450.h : 150.h, + child: ListItemWithOutCounter( + secondChild: Column( + spacing: 8, + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: Column( + spacing: 8, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'داوود خرم پور', + textAlign: TextAlign.center, + style: AppFonts.yekan16.copyWith( + color: AppColor.greenDark, + ), + ), + ], + ), + Container( + height: 32.h, + padding: EdgeInsets.symmetric(horizontal: 8), + decoration: ShapeDecoration( + color: AppColor.blueLight, + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1.w, + color: AppColor.blueLightHover, + ), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + spacing: 3, + children: [ + Text( + 'تاریخ بازرسی', + style: AppFonts.yekan14.copyWith( + color: AppColor.textColor, + ), + ), + + Text( + '1403/12/12', + style: AppFonts.yekan14.copyWith( + color: AppColor.blueNormal, + ), + ), + ], + ), + ), + + buildRow( + title: 'تلفن خریدار', + value: '0326598653', + valueStyle: AppFonts.yekan14.copyWith( + color: AppColor.blueNormal, + ), + ), + buildRow(title: 'آخرین فعالیت', value: '1409/12/12'), + buildRow(title: 'موجودی', value: '5KG'), + buildRow(title: 'فروش رفته', value: '5KG'), + ], + ), + ), + Row( + children: [ + Expanded( + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + spacing: 7, + children: [ + RElevated( + width: 40.h, + height: 38.h, + backgroundColor: AppColor.greenNormal, + child: Assets.vec.messageAddSvg.svg( + width: 24.w, + height: 24.h, + colorFilter: ColorFilter.mode( + Colors.white, + BlendMode.srcIn, + ), + ), + onPressed: () {}, + ), + RElevated( + width: 150.w, + height: 40.h, + backgroundColor: AppColor.blueNormal, + onPressed: () { + /* controller.setEditData(item); + Get.bottomSheet( + addOrEditBottomSheet(true), + isScrollControlled: true, + backgroundColor: Colors.transparent, + ).whenComplete(() {});*/ + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + spacing: 8, + children: [ + Assets.vec.mapSvg.svg( + width: 24.w, + height: 24.h, + colorFilter: ColorFilter.mode( + Colors.white, + BlendMode.srcIn, + ), + ), + Text( + 'مسیریابی', + style: AppFonts.yekan14Bold.copyWith( + color: Colors.white, + ), + ), + ], + ), + ), + ROutlinedElevated( + width: 150.w, + height: 40.h, + onPressed: () { + buildDeleteDialog( + onConfirm: () async {}, + onRefresh: () async {}, + ); + }, + borderColor: AppColor.bgIcon, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 8, + children: [ + Assets.vec.securityTimeSvg.svg( + width: 24.w, + height: 24.h, + colorFilter: ColorFilter.mode( + AppColor.bgIcon, + BlendMode.srcIn, + ), + ), + Text( + 'سوابق بازرسی', + style: AppFonts.yekan14Bold.copyWith( + color: AppColor.bgIcon, + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ], + ), + labelColor: AppColor.blueLight, + labelIcon: Assets.vec.cowSvg.path, + labelIconColor: AppColor.bgIcon, + onTap: () => data.value = !data.value, + selected: data.value, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'داود خرم مهری پور', + style: AppFonts.yekan10.copyWith(color: AppColor.blueNormal), + ), + Text( + 'گوشت و مرغ', + style: AppFonts.yekan12.copyWith( + color: AppColor.darkGreyDarkHover, + ), + ), + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'باقی مانده', + style: AppFonts.yekan10.copyWith(color: AppColor.blueNormal), + ), + Text( + '0 کیلوگرم', + style: AppFonts.yekan12.copyWith( + color: AppColor.darkGreyDarkHover, + ), + ), + ], + ), + Assets.vec.scanBarcodeSvg.svg(), + ], + ), + ), + ); + }, controller.isSelectedDetailsLocation), + ); + }, + child: Container( + height: 30.h, + padding: EdgeInsets.all(5.r), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15.r), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.1), + blurRadius: 5, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 8, + children: [ + Assets.vec.chickenMapMarkerSvg.svg(width: 24.w, height: 24.h), + Text(location.user?.fullname ?? '', style: AppFonts.yekan12), + ], + ), + ), + ) + : Assets.vec.chickenMapMarkerSvg.svg(width: 24.w, height: 24.h), + ); + }).toList(); + + return updatedMarkers; + } } Marker markerWidget({required LatLng marker, required VoidCallback onTap}) {