import 'dart:async'; import 'package:ebroker/Ui/screens/home/Widgets/property_horizontal_card.dart'; import 'package:ebroker/Ui/screens/widgets/shimmerLoadingContainer.dart'; import 'package:ebroker/data/Repositories/map.dart'; import 'package:ebroker/data/Repositories/property_repository.dart'; import 'package:ebroker/data/helper/widgets.dart'; import 'package:ebroker/data/model/data_output.dart'; import 'package:ebroker/data/model/property_model.dart'; import 'package:ebroker/utils/Extensions/extensions.dart'; import 'package:ebroker/utils/constant.dart'; import 'package:ebroker/utils/helper_utils.dart'; import 'package:ebroker/utils/hive_utils.dart'; import 'package:ebroker/utils/responsiveSize.dart'; import 'package:ebroker/utils/string_extenstion.dart'; import 'package:ebroker/utils/ui_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:label_marker/label_marker.dart'; import '../../../app/routes.dart'; import '../../../data/Repositories/location_repository.dart'; import '../../../data/model/google_place_model.dart'; import '../../../settings.dart'; import '../../../utils/AppIcon.dart'; import '../widgets/AnimatedRoutes/blur_page_route.dart'; class PropertyMapScreen extends StatefulWidget { const PropertyMapScreen({super.key}); static Route route(RouteSettings settings) { // Map? arguments = settings.arguments as Map?; return BlurredRouter(builder: (context) { return const PropertyMapScreen(); }); } @override State createState() => _PropertyMapScreenState(); } class _PropertyMapScreenState extends State { final TextEditingController _searchController = TextEditingController(); String previouseSearchQuery = ""; LatLng? citylatLong; Timer? _timer; Set marker = {}; Map map = {}; GoogleMapController? _googleMapController; Completer completer = Completer(); final FocusNode _searchFocus = FocusNode(); List? cities; int selectedMarker = 999999999999999; int? propertyId; ValueNotifier isLoadingProperty = ValueNotifier(false); PropertyModel? activePropertyModal; ValueNotifier loadintCitiesInProgress = ValueNotifier(false); bool showSellRentLables = false; bool showGoogleMap = true; Future searchDelayTimer() async { if (_timer?.isActive ?? false) { _timer?.cancel(); } _timer = Timer( const Duration(milliseconds: 500), () async { if (_searchController.text.isNotEmpty) { if (previouseSearchQuery != _searchController.text) { try { loadintCitiesInProgress.value = true; cities = await GooglePlaceRepository().serchCities( _searchController.text, ); loadintCitiesInProgress.value = false; } catch (e) { loadintCitiesInProgress.value = false; } setState(() {}); previouseSearchQuery = _searchController.text; } } else { cities = null; } }, ); setState(() {}); } @override void initState() { loadDefaultCity(); Fluttertoast.showToast( msg: "Please search city", toastLength: Toast.LENGTH_LONG, gravity: ToastGravity.TOP, timeInSecForIosWeb: 1, backgroundColor: Colors.red, textColor: Colors.white, fontSize: 16.0); _searchController.addListener(() { searchDelayTimer(); }); super.initState(); } LatLng cameraPosition = const LatLng( 42.42345651793833, 23.906250000000004, ); Future loadDefaultCity() async { if (HiveUtils.getCityName() == null) return; List pointList = await GMap.getNearByProperty( HiveUtils.getCityName() ?? "", HiveUtils.getStateName() ?? ""); if (pointList.isEmpty) { marker = {}; setState(() {}); } LatLng? latLng = await getCityLatLong(HiveUtils.getCityPlaceId()); //Animate camera to location (await completer.future).animateCamera(CameraUpdate.newCameraPosition( CameraPosition(target: latLng, zoom: 7))); loopMarker(pointList); } Future onTapCity(int index) async { Widgets.showLoader(context); List pointList = await GMap.getNearByProperty( cities?.elementAt(index).city ?? "", cities?.elementAt(index).state ?? ""); if (pointList.isEmpty) { marker = {}; setState(() {}); } LatLng? latLng = await getCityLatLongByIndex(index); //Animate camera to location (await completer.future).animateCamera( CameraUpdate.newCameraPosition( CameraPosition(target: latLng!, zoom: 7), ), ); loopMarker(pointList); // for (var i = 0; i < pointList.length; i++) { // var element = pointList[i]; // //Add markers inside marker list // marker // .addLabelMarker(LabelMarker( // label: r"$" + (element.price).toString().priceFormate(), // markerId: MarkerId("$i"), // onTap: () async { // selectedMarker = i; // setState(() {}); // }, // position: LatLng( // double.parse(element.latitude), double.parse(element.longitude)), // backgroundColor: selectedMarker == i // ? Colors.red // : (element.propertyType == "sell" ? Colors.green : Colors.orange), // )) // .then( // (value) { // setState(() {}); // }, // ); // } _searchFocus.unfocus(); HelperUtils.unfocus(); Future.delayed( Duration.zero, () { Widgets.hideLoder(context); }, ); cities = null; setState(() {}); } void loopMarker(List pointList) { for (var i = 0; i < pointList.length; i++) { var element = pointList[i]; print("element.propertyType ${element.propertyType}"); marker .addLabelMarker(LabelMarker( label: Constant.currencySymbol + (element.price).toString().priceFormate(), markerId: MarkerId("$i"), onTap: () async { selectedMarker = i; propertyId = element.propertyId; marker.clear(); loopMarker(pointList); setState(() {}); fetchProperty(element.propertyId); }, position: LatLng( double.parse(element.latitude), double.parse(element.longitude)), backgroundColor: selectedMarker == i ? Colors.red : (element.propertyType.toLowerCase() == "sell" ? Colors.green : Colors.orange), )) .then( (value) { setState(() {}); }, ); } } Future fetchProperty(int id) async { try { isLoadingProperty.value = true; DataOutput result = await PropertyRepository().fetchPropertyFromPropertyId(id); if (result.modelList.isNotEmpty) { activePropertyModal = result.modelList.first; } setState(() {}); isLoadingProperty.value = false; } catch (e) { isLoadingProperty.value = false; HelperUtils.showSnackBarMessage(context, "$e".translate(context)); } } Future? getCityLatLongByIndex(index) async { // var rawCityLatLong = await GooglePlaceRepository() // .getPlaceDetailsFromPlaceId(cities?.elementAt(index).placeId ?? ""); LatLng latLng = await getCityLatLong(cities?.elementAt(index).placeId ?? ""); return latLng; } Future getCityLatLong(String placeId) async { var rawCityLatLong = await GooglePlaceRepository().getPlaceDetailsFromPlaceId(placeId); var citylatLong = LatLng(rawCityLatLong['lat'], rawCityLatLong['lng']); return citylatLong; } @override void dispose() async { _googleMapController?.dispose(); _searchController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { Widget buildSearchIcon() { return Padding( padding: const EdgeInsets.all(8.0), child: UiUtils.getSvg(AppIcons.search, color: context.color.tertiaryColor)); } return WillPopScope( onWillPop: () async { _googleMapController?.dispose(); (await completer.future).dispose(); showGoogleMap = false; setState(() {}); return true; }, child: SafeArea( child: Scaffold( backgroundColor: context.color.backgroundColor, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, automaticallyImplyLeading: false, centerTitle: true, titleSpacing: 0, actions: [ FittedBox( fit: BoxFit.none, child: SizedBox( width: 24, height: 24, child: ValueListenableBuilder( valueListenable: loadintCitiesInProgress, builder: (context, va, c) { if (va == false) { return const SizedBox.shrink(); } return CircularProgressIndicator( color: context.color.tertiaryColor, strokeWidth: 1.5, ); }), )) ], leading: cities != null ? IconButton( onPressed: () { cities = null; _searchController.text = ""; setState(() {}); }, icon: Icon( Icons.close, color: context.color.tertiaryColor, )) : Material( clipBehavior: Clip.antiAlias, color: Colors.transparent, type: MaterialType.circle, child: InkWell( onTap: () { Navigator.pop(context); }, child: Padding( padding: const EdgeInsets.all(18.0), child: UiUtils.getSvg(AppIcons.arrowLeft, fit: BoxFit.none, color: context.color.tertiaryColor), ), ), ), title: Container( width: 270.rw(context), height: 50.rh(context), alignment: Alignment.center, decoration: BoxDecoration( border: Border.all( width: 1.5, color: context.color.borderColor), borderRadius: const BorderRadius.all(Radius.circular(10)), color: context.color.secondaryColor), child: TextFormField( focusNode: _searchFocus, controller: _searchController, decoration: InputDecoration( border: InputBorder.none, //OutlineInputBorder() fillColor: Theme.of(context).colorScheme.secondaryColor, hintText: UiUtils.translate(context, "searchHintLbl"), prefixIcon: buildSearchIcon(), prefixIconConstraints: const BoxConstraints(minHeight: 5, minWidth: 5), ), enableSuggestions: true, onEditingComplete: () { FocusScope.of(context).unfocus(); }, onTap: () { //change prefix icon color to primary })), ), body: Stack( children: [ if (showGoogleMap) GoogleMap( markers: marker, onMapCreated: (controller) { completer.complete(controller); showSellRentLables = true; setState(() {}); }, onTap: (argument) { activePropertyModal = null; selectedMarker = 99999999999999; setState(() {}); }, mapType: AppSettings.googleMapType, compassEnabled: false, mapToolbarEnabled: false, trafficEnabled: true, myLocationButtonEnabled: false, zoomControlsEnabled: false, myLocationEnabled: true, initialCameraPosition: CameraPosition( target: cameraPosition, ), ), sellRentLable(context), if (cities != null) Container( color: context.color.backgroundColor, child: ListView.builder( itemCount: cities?.length ?? 0, itemBuilder: (context, index) { return ListTile( onTap: () async { activePropertyModal = null; setState(() {}); onTapCity(index); }, leading: SvgPicture.asset( AppIcons.location, color: context.color.textColorDark, ), title: Text(cities?.elementAt(index).city ?? ""), subtitle: Text( "${cities?.elementAt(index).state ?? ""},${cities?.elementAt(index).country ?? ""}"), ); }, ), ), PositionedDirectional( bottom: 0, child: ValueListenableBuilder( valueListenable: isLoadingProperty, builder: (context, val, child) { if (cities != null) { return const SizedBox.shrink(); } if (val == true) { return SizedBox( width: MediaQuery.of(context).size.width, child: const Padding( padding: EdgeInsets.all(20.0), child: Row( children: [ CustomShimmer( width: 100, height: 110, ), SizedBox( width: 5, ), Expanded( child: CustomShimmer( height: 110, ), ), ], ), ), ); } else { if (activePropertyModal != null) { return SizedBox( width: MediaQuery.of(context).size.width, child: Padding( padding: const EdgeInsets.all(20), child: GestureDetector( onTap: () { Navigator.pushNamed( context, Routes.propertyDetails, arguments: { 'propertyData': activePropertyModal, 'fromMyProperty': true, }); }, child: PropertyHorizontalCard( showLikeButton: false, property: activePropertyModal!), ), ), ); } else { return Container(); } } })) ], ), ), ), ); } Padding sellRentLable(BuildContext context) { return Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Container( width: 20, height: 20, color: Colors.green, ), const SizedBox( width: 3, ), const Text("Sell").color(context.color.buttonColor), const SizedBox( width: 10, ), Container( width: 20, height: 20, color: Colors.orange, ), const SizedBox( width: 3, ), const Text("Rent").color(context.color.buttonColor), ], ), ); } }