Rumahjo-Android-APP/lib/Ui/screens/proprties/property_details.dart

2586 lines
118 KiB
Dart
Raw Normal View History

2024-09-07 00:58:50 +00:00
// ignore_for_file: public_member_api_docs, sort_constructors_first, use_build_context_synchronously
import 'dart:async';
import 'dart:convert';
import 'dart:ui';
import 'package:ebroker/Ui/screens/chat/chat_screen.dart';
import 'package:ebroker/Ui/screens/proprties/Property%20tab/sell_rent_screen.dart';
import 'package:ebroker/Ui/screens/proprties/widgets/report_property_widget.dart';
import 'package:ebroker/Ui/screens/widgets/blurred_dialoge_box.dart';
import 'package:ebroker/Ui/screens/widgets/like_button_widget.dart';
import 'package:ebroker/Ui/screens/widgets/panaroma_image_view.dart';
import 'package:ebroker/Ui/screens/widgets/read_more_text.dart';
import 'package:ebroker/app/routes.dart';
import 'package:ebroker/data/Repositories/interest_repository.dart';
import 'package:ebroker/data/Repositories/subscription_repository.dart';
import 'package:ebroker/data/cubits/Report/property_report_cubit.dart';
import 'package:ebroker/data/cubits/category/fetch_category_cubit.dart';
import 'package:ebroker/data/cubits/chatCubits/delete_message_cubit.dart';
import 'package:ebroker/data/cubits/chatCubits/load_chat_messages.dart';
import 'package:ebroker/data/cubits/enquiry/store_enqury_id.dart';
import 'package:ebroker/data/cubits/favorite/add_to_favorite_cubit.dart';
import 'package:ebroker/data/cubits/property/Interest/change_interest_in_property_cubit.dart';
import 'package:ebroker/data/cubits/property/delete_property_cubit.dart';
import 'package:ebroker/data/cubits/property/fetch_my_properties_cubit.dart';
import 'package:ebroker/data/cubits/property/set_property_view_cubit.dart';
import 'package:ebroker/data/cubits/property/update_property_status.dart';
import 'package:ebroker/data/cubits/subscription/get_subsctiption_package_limits_cubit.dart';
import 'package:ebroker/data/model/data_output.dart';
import 'package:ebroker/data/model/interested_user_model.dart';
import 'package:ebroker/data/model/property_model.dart';
import 'package:ebroker/utils/AppIcon.dart';
import 'package:ebroker/utils/Extensions/extensions.dart';
import 'package:ebroker/utils/api.dart';
import 'package:ebroker/utils/constant.dart';
import 'package:ebroker/utils/hive_utils.dart';
import 'package:ebroker/utils/responsiveSize.dart';
import 'package:ebroker/utils/string_extenstion.dart';
import 'package:flick_video_player/flick_video_player.dart';
import 'package:flutter/foundation.dart' as f;
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:url_launcher/url_launcher.dart' as urllauncher;
import 'package:url_launcher/url_launcher.dart';
import 'package:video_player/video_player.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import '../../../data/cubits/Interested/get_interested_user_cubit.dart';
import '../../../data/cubits/chatCubits/send_message.dart';
import '../../../data/cubits/outdoorfacility/fetch_outdoor_facility_list.dart';
import '../../../data/cubits/system/fetch_system_settings_cubit.dart';
import '../../../data/helper/widgets.dart';
import '../../../data/model/category.dart';
import '../../../settings.dart';
import '../../../utils/AdMob/interstitialAdManager.dart';
import '../../../utils/guestChecker.dart';
import '../../../utils/helper_utils.dart';
import '../../../utils/ui_utils.dart';
import '../analytics/analytics_screen.dart';
import '../widgets/AnimatedRoutes/blur_page_route.dart';
import '../widgets/all_gallary_image.dart';
import '../widgets/video_view_screen.dart';
import '../widgets/my_maps.dart';
Map<String, String> rentDurationMap = {
"Quarterly": "Quarter",
"Monthly": "Month",
"Yearly": "Year",
"Daily": "Daily",
"Day": "Day"
};
class PropertyDetails extends StatefulWidget {
final PropertyModel? property;
final bool? fromMyProperty;
final bool? fromCompleteEnquiry;
final bool fromSlider;
final bool? fromPropertyAddSuccess;
const PropertyDetails(
{Key? key,
this.fromPropertyAddSuccess,
required this.property,
this.fromSlider = false,
this.fromMyProperty,
this.fromCompleteEnquiry})
: super(key: key);
@override
PropertyDetailsState createState() => PropertyDetailsState();
static Route route(RouteSettings routeSettings) {
try {
Map? arguments = routeSettings.arguments as Map?;
return BlurredRouter(
builder: (_) => MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => ChangeInterestInPropertyCubit(),
),
BlocProvider(
create: (context) => UpdatePropertyStatusCubit(),
),
BlocProvider(
create: (context) => DeletePropertyCubit(),
),
BlocProvider(
create: (context) => PropertyReportCubit(),
),
BlocProvider(
create: (context) => GetInterestedUserCubit(),
),
],
child: PropertyDetails(
property: arguments?['propertyData'],
fromMyProperty: arguments?['fromMyProperty'] ?? false,
fromSlider: arguments?['fromSlider'] ?? false,
fromCompleteEnquiry: arguments?['fromCompleteEnquiry'] ?? false,
fromPropertyAddSuccess: arguments?['fromSuccess'] ?? false,
),
),
);
} catch (e) {
rethrow;
}
}
}
class PropertyDetailsState extends State<PropertyDetails>
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
FlickManager? flickManager;
ValueNotifier<bool> shouldShowSubscriptionOverlay = ValueNotifier(false);
// late Property propertyData;
bool favoriteInProgress = false;
bool isPlayingYoutubeVideo = false;
bool fromMyProperty = false; //get its value from Widget
bool fromCompleteEnquiry = false; //get its value from Widget
List promotedProeprtiesIds = [];
bool toggleEnqButton = false;
PropertyModel? property;
bool isPromoted = false;
bool showGoogleMap = false;
bool isEnquiryFromChat = false;
BannerAd? _bannerAd;
@override
bool get wantKeepAlive => true;
GlobalKey appBarKey = GlobalKey();
final Completer<GoogleMapController> _controller =
Completer<GoogleMapController>();
List<Gallery>? gallary;
String youtubeVideoThumbnail = "";
bool? _isLoaded;
InterstitialAdManager interstitialAdManager = InterstitialAdManager();
bool isPremiumProperty = true;
bool isPremiumUser = false;
bool isReported = false;
bool shouldRestrictPropertyAccess() {
if (isPremiumProperty && !isPremiumUser) {
return true;
}
return false;
}
@override
void initState() {
super.initState();
context
.read<GetSubsctiptionPackageLimitsCubit>()
.getLimits(SubscriptionLimitType.property);
isPremiumProperty = widget.property?.allPropData['is_premium'] ?? false;
isPremiumUser = context
.read<FetchSystemSettingsCubit>()
.getRawSettings()['is_premium'] ??
false;
isReported = widget.property?.allPropData?['is_reported'] ?? false;
loadAd();
// Future.delayed(
// Duration(milliseconds: 50),
// () {
// Map<String, double> widgetInfo =
// UiUtils.getWidgetInfo(context, appBarKey);
// bottomAppBarHeight = widgetInfo['height'] ?? 0;
// setState(() {});
// },
// );
interstitialAdManager.load();
// customListenerForConstant();
//add title image along with gallery images
context.read<FetchOutdoorFacilityListCubit>().fetch();
context.read<GetInterestedUserCubit>().fetch("${widget.property?.id}");
Future.delayed(
const Duration(seconds: 3),
() {
showGoogleMap = true;
if (mounted) setState(() {});
},
);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
gallary = List.from(widget.property!.gallery!);
if (widget.property?.video != "") {
injectVideoInGallery();
setState(() {});
}
});
if (widget.fromSlider) {
getProperty();
} else {
property = widget.property;
setData();
}
setViewdProperty();
if (widget.property?.video != "" &&
widget.property?.video != null &&
!HelperUtils.isYoutubeVideo(widget.property?.video ?? "")) {
flickManager = FlickManager(
videoPlayerController: VideoPlayerController.network(
property!.video!,
),
);
flickManager?.onVideoEnd = () {};
}
if (widget.property?.video != "" &&
widget.property?.video != null &&
HelperUtils.isYoutubeVideo(widget.property?.video ?? "")) {
String? videoId = YoutubePlayer.convertUrlToId(property!.video!);
String thumbnail = YoutubePlayer.getThumbnail(videoId: videoId!);
youtubeVideoThumbnail = thumbnail;
setState(() {});
}
}
void loadAd() {
_bannerAd = BannerAd(
adUnitId: Constant.admobBannerAndroid,
request: const AdRequest(),
size: AdSize.largeBanner,
listener: BannerAdListener(
// Called when an ad is successfully received.
onAdLoaded: (ad) {
debugPrint('$ad loaded.');
setState(() {
_isLoaded = true;
});
},
// Called when an ad request failed.
onAdFailedToLoad: (ad, err) {
// Dispose the ad here to free resources.
ad.dispose();
},
),
)..load();
}
Future<void> getProperty() async {
var response = await HelperUtils.sendApiRequest(
Api.apiGetProprty,
{
Api.id: widget.property!.id,
},
true,
context,
passUserid: false);
if (response != null) {
var getdata = json.decode(response);
if (!getdata[Api.error]) {
getdata['data'];
setData();
setState(() {});
}
}
}
void setData() {
fromMyProperty = widget.fromMyProperty!;
fromCompleteEnquiry = widget.fromCompleteEnquiry!;
}
void setViewdProperty() {
if (property!.addedBy.toString() != HiveUtils.getUserId()) {
context.read<SetPropertyViewCubit>().set(property!.id!.toString());
}
}
late final CameraPosition _kInitialPlace = CameraPosition(
target: LatLng(
double.parse(
(property?.latitude ?? "0"),
),
double.parse(
(property?.longitude ?? "0"),
),
),
zoom: 14.4746,
);
@override
void dispose() {
flickManager?.dispose();
super.dispose();
}
void injectVideoInGallery() {
///This will inject video in image list just like another platforms
if ((gallary?.length ?? 0) < 2) {
if (widget.property?.video != null) {
gallary?.add(Gallery(
id: 99999999999,
image: property!.video ?? "",
imageUrl: "",
isVideo: true));
}
} else {
gallary?.insert(
0,
Gallery(
id: 99999999999,
image: property!.video!,
imageUrl: "",
isVideo: true));
}
setState(() {});
}
String? _statusFilter(String value) {
if (value == "Sell" || value == "sell") {
return "sold".translate(context);
}
if (value == "Rent" || value == "rent") {
return "Rented".translate(context);
}
return null;
}
int? _getStatus(type) {
int? value;
if (type == "Sell" || type == "sell") {
value = 2;
} else if (type == "Rent" || type == "rent") {
value = 3;
} else if (type == "Rented" || type == "rented") {
value = 1;
}
return value;
}
//main build
@override
Widget build(BuildContext context) {
super.build(context);
print("ISRENTED ${isPremiumProperty} nd ${isPremiumUser}");
String rentPrice = (property!.price!
.priceFormate(
disabled: false,
)
.toString()
.formatAmount(prefix: true));
if (property?.rentduration != "" && property?.rentduration != null) {
rentPrice =
("$rentPrice / ") + (rentDurationMap[property!.rentduration] ?? "");
}
String Lat = property!.latitude.toString();
String Long = property!.longitude.toString();
return SafeArea(
child: WillPopScope(
onWillPop: () async {
await interstitialAdManager.show();
if (widget.fromPropertyAddSuccess ?? false) {
Navigator.popUntil(context, (route) => route.isFirst);
return false;
}
showGoogleMap = false;
setState(() {});
return true;
},
child: AnnotatedRegion(
value: UiUtils.getSystemUiOverlayStyle(
context: context,
),
child: SafeArea(
child: BlocListener<GetSubsctiptionPackageLimitsCubit,
GetSubsctiptionPackageLimitsState>(
listener: (context, state) {
if (state is GetSubsctiptionPackageLimitsSuccess) {
isPremiumUser = state.packageLimit.isPremium;
setState(() {});
}
},
child: Stack(
children: [
Scaffold(
appBar: UiUtils.buildAppBar(context,
hideTopBorder: true,
showBackButton: true,
actions: [
if (!HiveUtils.isGuest()) ...[
if (int.parse(HiveUtils.getUserId() ?? "0") ==
property?.addedBy)
IconButton(
onPressed: () async {
DataOutput<InterestedUserModel> interestUser =
await InterestRepository()
.getInterestUser(
property!.id!.toString(),
offset: 0);
GetInterestedUserCubit
interestedUserCubitReference =
context.read<GetInterestedUserCubit>();
showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(20)),
backgroundColor: context
.color.secondaryColor
.withOpacity(0.86),
constraints: BoxConstraints(
minWidth: double.infinity,
maxHeight: context.screenHeight * 0.7,
minHeight: context.screenHeight * 0.3),
builder: (context) {
return InterestedUserListWidget(
totalCount:
"${widget.property?.totalInterestedUsers}",
interestedUserCubitReference:
interestedUserCubitReference);
},
);
return;
Navigator.push(context, BlurredRouter(
builder: (context) {
return AnalyticsScreen(
interestUserCount: widget
.property!.totalInterestedUsers
.toString(),
);
},
));
},
icon: Icon(
Icons.analytics,
color: context.color.tertiaryColor,
)),
],
IconButton(
onPressed: () {
HelperUtils.share(
context, property!.id!, property?.slugId ?? "");
},
icon: Icon(
Icons.share,
color: context.color.tertiaryColor,
),
),
if (property?.addedBy.toString() ==
HiveUtils.getUserId() &&
property!.properyType != "Sold" &&
property?.status == 1)
PopupMenuButton<String>(
onSelected: (value) async {
var action = await UiUtils.showBlurredDialoge(
context,
dialoge: BlurredDialogBuilderBox(
title: "changePropertyStatus"
.translate(context),
acceptButtonName:
"change".translate(context),
contentBuilder: (context, s) {
return FittedBox(
fit: BoxFit.none,
child: Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: context
.color.tertiaryColor,
borderRadius:
BorderRadius.circular(
10)),
width: s.maxWidth / 4,
height: 50,
child: Center(
child: Text(property!
.properyType!
.translate(context))
.color(context
.color.buttonColor)),
),
Text(
"toArrow".translate(context),
),
Container(
width: s.maxWidth / 4,
decoration: BoxDecoration(
color: context
.color.tertiaryColor
.withOpacity(0.4),
borderRadius:
BorderRadius.circular(
10)),
height: 50,
child: Center(
child: Text(_statusFilter(
property!
.properyType!) ??
"")
.color(context
.color.buttonColor)),
),
],
),
);
}),
);
if (action == true) {
Future.delayed(Duration.zero, () {
context
.read<UpdatePropertyStatusCubit>()
.update(
propertyId: property!.id,
status:
_getStatus(property!.properyType),
);
});
}
},
color: context.color.secondaryColor,
itemBuilder: (BuildContext context) {
return {
'changeStatus'.translate(context),
}.map((String choice) {
return PopupMenuItem<String>(
value: choice,
textStyle: TextStyle(
color: context.color.textColorDark),
child: Text(choice),
);
}).toList();
},
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 4.0),
child: Icon(
Icons.more_vert_rounded,
color: context.color.tertiaryColor,
),
),
),
const SizedBox(
width: 10,
)
]),
backgroundColor: context.color.backgroundColor,
floatingActionButton: (property == null ||
property!.addedBy.toString() == HiveUtils.getUserId())
? const SizedBox.shrink()
: Container(),
bottomNavigationBar: isPlayingYoutubeVideo == false
? BottomAppBar(
key: appBarKey,
padding: const EdgeInsets.symmetric(horizontal: 0),
color: context.color.secondaryColor,
child: bottomNavBar())
: null,
floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat,
body: BlocListener<DeletePropertyCubit, DeletePropertyState>(
listener: (context, state) {
if (state is DeletePropertyInProgress) {
Widgets.showLoader(context);
}
if (state is DeletePropertySuccess) {
Widgets.hideLoder(context);
Future.delayed(
const Duration(milliseconds: 1000),
() {
Navigator.pop(context, true);
},
);
}
if (state is DeletePropertyFailure) {
Widgets.showLoader(context);
}
},
child: SafeArea(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: BlocListener<UpdatePropertyStatusCubit,
UpdatePropertyStatusState>(
listener: (context, state) {
if (state is UpdatePropertyStatusInProgress) {
Widgets.showLoader(context);
}
if (state is UpdatePropertyStatusSuccess) {
Widgets.hideLoder(context);
Fluttertoast.showToast(
msg: "statusUpdated".translate(context),
backgroundColor: successMessageColor,
gravity: ToastGravity.TOP,
toastLength: Toast.LENGTH_LONG);
(cubitReference as FetchMyPropertiesCubit)
.updateStatus(
property!.id!, property!.properyType!);
setState(() {});
}
if (state is UpdatePropertyStatusFail) {
Widgets.hideLoder(context);
}
},
child: Padding(
padding: EdgeInsets.symmetric(
horizontal:
isPlayingYoutubeVideo == false ? 20.0 : 0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
),
if (!isPlayingYoutubeVideo)
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(20),
child: SizedBox(
height: 227.rh(context),
child: Stack(
children: [
GestureDetector(
onTap: () {
// google map doesn't allow blur so we hide it:)
showGoogleMap = false;
setState(() {});
UiUtils.showFullScreenImage(
context,
provider: NetworkImage(
property!.titleImage!,
),
then: () {
showGoogleMap = true;
setState(() {});
},
);
},
child: UiUtils.getImage(
property!.titleImage!,
fit: BoxFit.cover,
width: double.infinity,
height: 227.rh(context),
showFullScreenImage: true,
),
),
PositionedDirectional(
top: 20,
end: 20,
child: LikeButtonWidget(
onStateChange:
(AddToFavoriteCubitState
state) {
if (state
is AddToFavoriteCubitInProgress) {
favoriteInProgress = true;
setState(
() {},
);
} else {
favoriteInProgress =
false;
setState(
() {},
);
}
},
property: property!,
),
),
PositionedDirectional(
bottom: 5,
end: 18,
child: Visibility(
visible:
property?.threeDImage !=
"",
child: GestureDetector(
onTap: () {
Navigator.push(
context,
BlurredRouter(
builder: (context) =>
PanaromaImageScreen(
imageUrl: property!
.threeDImage!,
),
),
);
},
child: Container(
decoration: BoxDecoration(
color: context.color
.secondaryColor,
shape: BoxShape.circle,
),
height: 40.rh(context),
width: 40.rw(context),
child: Padding(
padding:
const EdgeInsets
.all(5.0),
child: UiUtils.getSvg(
AppIcons.v360Degree,
color: context.color
.tertiaryColor),
),
),
),
),
),
advertismentLable()
],
),
),
),
const SizedBox(
height: 15,
),
Row(children: [
UiUtils.imageType(
property?.category!.image ?? "",
width: 18,
height: 18,
color: Constant.adaptThemeColorSvg
? context.color.tertiaryColor
: null),
const SizedBox(
width: 10,
),
SizedBox(
width: 158.rw(context),
child: Text(
property!.category!.category!)
.setMaxLines(lines: 1)
.size(
context.font.normal,
)
.bold(
weight: FontWeight.w400,
)
.color(UiUtils.makeColorLight(
context.color.textColorDark)),
),
const Spacer(),
Container(
width: 50,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(3.5),
color:
context.color.tertiaryColor),
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Center(
child: Text(
property!.properyType
.toString()
.toLowerCase()
.translate(context),
).size(context.font.small).color(
context.color.buttonColor)),
),
)
]),
const SizedBox(
height: 15,
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(property!.title!
.firstUpperCase())
.color(
context.color.textColorDark)
.size(18)
.bold(weight: FontWeight.w600),
),
Text(property?.postCreated ?? "")
.color(context.color.textColorDark
.withOpacity(0.6)),
],
),
const SizedBox(height: 13),
Row(
children: [
if (property!.properyType
.toString()
.toLowerCase() ==
"rent") ...[
Text(rentPrice)
.color(
context.color.tertiaryColor)
.size(18)
.bold(weight: FontWeight.w700),
] else ...[
Text(property!.price!
.priceFormate(
disabled: false)
.formatAmount(prefix: true))
.color(
context.color.tertiaryColor)
.size(18)
.bold(weight: FontWeight.w700),
],
if (Constant.isNumberWithSuffix) ...[
if (property!.properyType
.toString()
.toLowerCase() !=
"rent") ...[
const SizedBox(
width: 5,
),
Text("(${property!.price!})")
.color(context
.color.tertiaryColor)
.size(18)
.bold(
weight: FontWeight.w500),
]
]
],
),
const SizedBox(
height: 20,
),
Wrap(
direction: Axis.horizontal,
crossAxisAlignment:
WrapCrossAlignment.start,
runAlignment: WrapAlignment.start,
alignment: WrapAlignment.start,
children: List.generate(
property?.parameters?.length ?? 0,
(index) {
Parameter? parameter =
property?.parameters![index];
bool isParameterValueEmpty =
(parameter?.value == "" ||
parameter?.value == "0" ||
parameter?.value == null ||
parameter?.value == "null");
///If it has no value
if (isParameterValueEmpty) {
return const SizedBox.shrink();
}
return ConstrainedBox(
constraints: BoxConstraints(
minWidth:
(context.screenWidth / 2) -
40),
child: Padding(
padding:
const EdgeInsets.fromLTRB(
0, 8, 8, 8),
child: SizedBox(
// height: 37,
child: Row(
crossAxisAlignment:
CrossAxisAlignment
.start,
mainAxisSize:
MainAxisSize.min,
children: [
Container(
width: 36.rw(context),
height: 36.rh(context),
alignment:
Alignment.center,
decoration: BoxDecoration(
color: context.color
.tertiaryColor
.withOpacity(
0.2),
borderRadius:
BorderRadius
.circular(
10)),
child: SizedBox(
height:
20.rh(context),
width: 20.rw(context),
child: FittedBox(
child: UiUtils
.imageType(
parameter
?.image ??
"",
fit: BoxFit.cover,
color: Constant
.adaptThemeColorSvg
? context
.color
.tertiaryColor
: null,
),
),
),
),
SizedBox(
width: 10.rw(context),
),
Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
mainAxisSize:
MainAxisSize.min,
children: [
Text(parameter
?.name ??
"")
.size(12)
.color(context
.color
.textColorDark
.withOpacity(
0.8)),
if (parameter
?.typeOfParameter ==
"file") ...{
InkWell(
onTap: () async {
await urllauncher.launchUrl(
Uri.parse(
parameter!
.value),
mode: LaunchMode
.externalApplication);
},
child: Text(
UiUtils.translate(
context,
"viewFile"),
)
.underline()
.color(context
.color
.tertiaryColor),
),
} else if (parameter
?.value
is List) ...{
Text((parameter
?.value
as List)
.join(","))
} else ...[
if (parameter
?.typeOfParameter ==
"textarea") ...[
SizedBox(
width: MediaQuery.of(
context)
.size
.width *
0.7,
child: Text(
"${parameter?.value}")
.size(14)
.bold(
weight: FontWeight
.w600,
),
)
] else ...[
Text("${parameter?.value}")
.size(14)
.bold(
weight:
FontWeight
.w600,
)
]
]
],
)
]),
),
),
);
}),
),
const SizedBox(
height: 14,
),
UiUtils.getDivider(),
const SizedBox(
height: 14,
),
Text(UiUtils.translate(
context, "aboutThisPropLbl"))
.color(context.color.textColorDark)
.size(16)
.bold(weight: FontWeight.w600),
const SizedBox(
height: 15,
),
ReadMoreText(
text: property?.description ?? "",
style: TextStyle(
color: context.color.textColorDark
.withOpacity(0.7)),
readMoreButtonStyle: TextStyle(
color:
context.color.tertiaryColor)),
const SizedBox(
height: 20,
),
//TODO:
if (_bannerAd != null &&
Constant.isAdmobAdsEnabled)
SizedBox(
width: _bannerAd?.size.width
.toDouble(),
height: _bannerAd?.size.height
.toDouble(),
child: AdWidget(ad: _bannerAd!)),
const SizedBox(
height: 20,
),
if (widget
.property
?.assignedOutdoorFacility
?.isNotEmpty ??
false) ...[
Text(UiUtils.translate(
context, "outdoorFacilities"))
.color(context.color.textColorDark)
.size(16)
.bold(weight: FontWeight.w600),
const SizedBox(height: 10),
],
OutdoorFacilityListWidget(
outdoorFacilityList: widget.property
?.assignedOutdoorFacility ??
[]),
Text(UiUtils.translate(
context, "listedBy"))
.color(context.color.textColorDark)
.size(16)
.bold(weight: FontWeight.w600),
const SizedBox(
height: 14,
),
GestureDetector(
onTap: () {},
child: AgentProfileWidget(
hideDetails:
shouldRestrictPropertyAccess(),
widget: widget,
),
),
const SizedBox(
height: 10,
),
if (gallary?.isNotEmpty ?? false) ...[
Text(UiUtils.translate(
context, "gallery"))
.color(context.color.textColorDark)
.size(16)
.bold(weight: FontWeight.w600),
SizedBox(
height: 10.rh(context),
),
],
if (gallary?.isNotEmpty ?? false) ...[
Row(
children: List.generate(
(gallary?.length.clamp(0, 4)) ?? 0,
(index) {
return Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 3),
child: ClipRRect(
borderRadius:
BorderRadius.circular(18),
child: Stack(
children: [
GestureDetector(
onTap: () {
if (gallary?[index]
.isVideo ==
true) return;
//google map doesn't allow blur so we hide it:)
showGoogleMap = false;
setState(() {});
var images = gallary
?.map((e) =>
e.imageUrl)
.toList();
UiUtils
.imageGallaryView(
context,
images: images!,
initalIndex: index,
then: () {
showGoogleMap =
true;
setState(() {});
},
);
},
child: SizedBox(
width: 76.rw(context),
height: 76.rh(context),
child: gallary?[index]
.isVideo ==
true
? Container(
child: UiUtils.getImage(
youtubeVideoThumbnail,
fit: BoxFit
.cover),
)
: UiUtils.getImage(
gallary?[index]
.imageUrl ??
"",
fit: BoxFit
.cover),
),
),
if (gallary?[index]
.isVideo ==
true)
Positioned.fill(
child:
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return VideoViewScreen(
videoUrl: gallary?[
index]
.image ??
"",
flickManager:
flickManager,
);
},
));
},
child: Container(
color: Colors.black
.withOpacity(0.3),
child: FittedBox(
fit: BoxFit.none,
child: Container(
decoration: BoxDecoration(
shape: BoxShape
.circle,
color: context
.color
.tertiaryColor
.withOpacity(
0.8)),
width: 30,
height: 30,
child: const Icon(
Icons
.play_arrow,
color: Colors
.white,
),
),
),
),
)),
if (index == 3)
Positioned.fill(
child:
GestureDetector(
onTap: () {
Navigator.push(
context,
BlurredRouter(
builder: (context) {
return AllGallaryImages(
youtubeThumbnail:
youtubeVideoThumbnail,
images: property
?.gallery ??
[]);
},
));
},
child: Container(
alignment:
Alignment.center,
color: Colors.black
.withOpacity(0.3),
child: Text(
"+${(property?.gallery?.length ?? 0) - 3}")
.color(
Colors.white,
)
.size(context
.font.large)
.bold(),
),
))
],
),
),
);
},
))
],
const SizedBox(
height: 15,
),
Text(UiUtils.translate(
context, "locationLbl"))
.color(context.color.textColorDark)
.size(context.font.large)
.bold(weight: FontWeight.w600),
SizedBox(
height: 10.rh(context),
),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text("${UiUtils.translate(context, "addressLbl")} :")
.size(context.font.normal)
.color(
context.color.textColorDark),
// .bold(weight: FontWeight.w600),
SizedBox(
height: 5.rh(context),
),
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
UiUtils.getSvg(AppIcons.location,
color: context
.color.tertiaryColor),
SizedBox(
width: 5.rw(context),
),
Expanded(
child: HideDetailsBlur(
hide:
shouldRestrictPropertyAccess(),
child: Text(
"${property?.address!}"),
),
)
],
),
],
),
SizedBox(
height: 10.rh(context),
),
SizedBox(
height: 175,
child: ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: Stack(
fit: StackFit.expand,
children: [
Image.asset(
"assets/map.png",
fit: BoxFit.cover,
),
BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 4.0,
sigmaY: 4.0,
),
child: Center(
child: MaterialButton(
onPressed: () {
if (shouldRestrictPropertyAccess()) {
GuestChecker.check(
onNotGuest: () {
shouldShowSubscriptionOverlay
.value = true;
return;
},
);
return;
}
Navigator.push(context,
BlurredRouter(
builder: (context) {
return Scaffold(
extendBodyBehindAppBar:
true,
appBar: AppBar(
elevation: 0,
iconTheme: IconThemeData(
color: context
.color
.tertiaryColor),
backgroundColor:
Colors
.transparent,
),
body: MyMaps(
latitudeString: Lat,
longitudeString: Long,
),
);
},
));
},
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius
.circular(
5)),
color: context
.color.tertiaryColor,
elevation: 0,
child:
shouldRestrictPropertyAccess()
? Icon(
Icons
.lock_open_outlined,
color: context
.color
.secondaryColor
.withOpacity(
0.8),
)
: Text(("viewMap"
.translate(
context)))
.color(
context.color
.buttonColor,
),
),
),
),
],
),
),
),
const SizedBox(
height: 18,
),
if (!HiveUtils.isGuest()) ...[
if (int.parse(
HiveUtils.getUserId() ?? "0") !=
property?.addedBy)
Row(
children: [
// sendEnquiryButtonWithState(),
setInterest(),
],
),
],
const SizedBox(
height: 18,
),
if (!reportedProperties
.contains(widget.property!.id) &&
widget.property!.addedBy.toString() !=
HiveUtils.getUserId() &&
!isReported)
ReportPropertyButton(
propertyId: property!.id!,
onSuccess: () {
setState(
() {},
);
},
)
],
),
//here
SizedBox(
height: 20.rh(context),
),
],
),
),
),
),
),
),
),
ValueListenableBuilder(
valueListenable: shouldShowSubscriptionOverlay,
builder: (context, value, child) {
return SizedBox(
height: context.screenHeight,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 300),
opacity: value == true ? 1 : 0,
child: IgnorePointer(
ignoring: !value,
child: GestureDetector(
onTap: () {
shouldShowSubscriptionOverlay.value = false;
},
child: Padding(
padding: EdgeInsets.only(
bottom:
getBottomNavigationBarHeight(context)),
child: Container(
// height: context.screenHeight - .rh(context),
child: ClipRRect(
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaY: 5, sigmaX: 4),
child: Container(
color: Colors.black.withOpacity(0.5),
width: double.infinity,
child: Stack(
fit: StackFit.expand,
children: [
Align(
alignment:
Alignment.bottomCenter,
child: Column(
mainAxisSize:
MainAxisSize.min,
children: [
Material(
color: Colors.transparent,
child: Text(
"toAccessSubscribe"
.translate(context),
style: const TextStyle(
shadows: <Shadow>[
Shadow(
offset: Offset(
1.0, 1.0),
blurRadius: 3.0,
color: Color
.fromARGB(
255,
0,
0,
0),
),
]),
)
.size(context
.font.larger)
.bold()
.centerAlign()
.color(context.color
.secondaryColor),
),
const SizedBox(
height: 15,
),
MaterialButton(
height: 48,
minWidth:
context.screenWidth *
0.5,
onPressed: () {
Navigator.pushNamed(
context,
Routes
.subscriptionPackageListRoute,
arguments: {
"from": Routes
.propertyDetails
}).then((value) {
context
.read<
GetSubsctiptionPackageLimitsCubit>()
.getLimits(
SubscriptionLimitType
.property);
shouldShowSubscriptionOverlay
.value = false;
});
},
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius
.circular(
15)),
color: context
.color.secondaryColor,
elevation: 0,
child: Text("Subscribe")
.color(context.color
.tertiaryColor),
),
SizedBox(
height: 15,
),
// bottomNavBar()
],
),
),
],
)),
),
),
),
),
),
),
),
);
// return SizedBox.shrink();
})
],
),
)),
),
),
);
}
Widget advertismentLable() {
// if (property?.promoted == false || property?.promoted == null) {
// return const SizedBox.shrink();
// }
return PositionedDirectional(
start: 20,
top: 20,
child: SizedBox(
height: 32,
child: Row(
children: [
if ((property?.promoted == true &&
property?.promoted != null)) ...[
Container(
width: 83,
height: 32,
alignment: Alignment.center,
decoration: BoxDecoration(
color: context.color.tertiaryColor,
borderRadius: BorderRadius.circular(4)),
child: Text(UiUtils.translate(context, 'featured'))
.color(context.color.buttonColor)
.size(context.font.small),
),
const SizedBox(
width: 4,
)
],
if (property != null &&
property?.allPropData['is_premium'] == true) ...[
Container(
height: 32,
width: 32,
// margin: EdgeInsets.symmetric(horizontal: 0),
decoration: BoxDecoration(
color: context.color.tertiaryColor,
borderRadius: BorderRadius.circular(6)),
child: FittedBox(
fit: BoxFit.none,
child: SvgPicture.asset(AppIcons.promoted)),
),
]
],
),
));
}
double getBottomNavigationBarHeight(BuildContext context) {
try {
final RenderBox? renderBox =
appBarKey.currentContext?.findRenderObject() as RenderBox?;
return renderBox?.size.height ?? 0.0;
} catch (e) {
return 0;
}
}
Widget bottomNavBar() {
/// IF property is added by current user then it will show promote button
if (!HiveUtils.isGuest()) {
if (int.parse(HiveUtils.getUserId() ?? "0") == property?.addedBy) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: SizedBox(
height: 65.rh(context),
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 10.0, horizontal: 0),
child:
BlocBuilder<FetchMyPropertiesCubit, FetchMyPropertiesState>(
builder: (context, state) {
PropertyModel? model;
if (state is FetchMyPropertiesSuccess) {
model = state.myProperty
.where((element) => element.id == property?.id)
.first;
}
model ??= widget.property;
var isPromoted = (model?.promoted);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
if (!HiveUtils.isGuest()) ...[
if (isPromoted == false &&
(property?.status.toString() != "0")) ...[
Expanded(
child: UiUtils.buildButton(
context,
disabled: (property?.status.toString() == "0"),
// padding: const EdgeInsets.symmetric(horizontal: 1),
outerPadding: const EdgeInsets.all(
1,
),
onPressed: () {
Navigator.pushNamed(
context,
Routes.createAdvertismentScreenRoute,
arguments: {
"model": property,
},
).then(
(value) {
setState(() {});
},
);
},
prefixWidget: Padding(
padding: const EdgeInsets.only(right: 6),
child: SvgPicture.asset(
AppIcons.promoted,
width: 14,
height: 14,
),
),
fontSize: context.font.normal,
width: context.screenWidth / 3,
buttonTitle: UiUtils.translate(context, "feature"),
)),
const SizedBox(
width: 8,
),
],
],
Expanded(
child: UiUtils.buildButton(context,
// padding: const EdgeInsets.symmetric(horizontal: 1),
outerPadding: const EdgeInsets.all(1),
onPressed: () async {
Category category = await context
.read<FetchCategoryCubit>()
.get(property!.category!.id!);
// Extract parameter IDs from category
List<dynamic>? parameterIds =
category.parameterTypes?['parameters'];
// Map parameters
List<dynamic>? mappedParameters =
parameterIds?.map((dynamic id) {
// Find index of parameter in property parameters list
int index = property?.parameters?.indexWhere(
(element) => element.id == id['id']) ??
-1;
// If parameter found, return it; otherwise, return the original value
return index != -1
? property!.parameters![index]
: id;
}).toList();
Constant.addProperty.addAll({
"category": Category(
category: property?.category!.category,
id: property?.category?.id!.toString(),
image: property?.category?.image,
parameterTypes: {"parameters": mappedParameters},
)
});
// log(" oiasdjalwd j$map");
Navigator.pushNamed(
context, Routes.addPropertyDetailsScreen,
arguments: {
"details": {
"id": property?.id,
"catId": property?.category?.id,
"propType": property?.properyType,
"name": property?.title,
"desc": property?.description,
"city": property?.city,
"state": property?.state,
"country": property?.country,
"latitude": property?.latitude,
"longitude": property?.longitude,
"address": property?.address,
"client": property?.clientAddress,
"price": property?.price,
'parms': property?.parameters,
"allPropData": property?.allPropData,
"images": property?.gallery
?.map((e) => e.imageUrl)
.toList(),
"gallary_with_id": property?.gallery,
"rentduration": property?.rentduration,
"assign_facilities":
property?.assignedOutdoorFacility,
"titleImage": property?.titleImage
}
});
},
fontSize: context.font.normal,
width: context.screenWidth / 3,
prefixWidget: Padding(
padding: const EdgeInsets.only(right: 6.0),
child: SvgPicture.asset(AppIcons.edit),
),
buttonTitle: UiUtils.translate(context, "edit")),
),
const SizedBox(
width: 8,
),
Expanded(
child: UiUtils.buildButton(context,
padding: const EdgeInsets.symmetric(horizontal: 1),
outerPadding: const EdgeInsets.all(1),
prefixWidget: Padding(
padding: const EdgeInsets.only(right: 6.0),
child: SvgPicture.asset(
AppIcons.delete,
color: context.color.buttonColor,
width: 14,
height: 14,
),
), onPressed: () async {
// //THIS IS FOR DEMO MODE
bool isPropertyActive =
property?.status.toString() == "1";
bool isDemoNumber = HiveUtils.getUserDetails()
.mobile ==
"${Constant.demoCountryCode}${Constant.demoMobileNumber}";
if (Constant.isDemoModeOn &&
isPropertyActive &&
isDemoNumber) {
HelperUtils.showSnackBarMessage(context,
"Active property cannot be deleted in demo app.");
return;
}
var delete = await UiUtils.showBlurredDialoge(
context,
dialoge: BlurredDialogBox(
title: UiUtils.translate(
context,
"deleteBtnLbl",
),
content: Text(
UiUtils.translate(
context, "deletepropertywarning"),
),
),
);
if (delete == true) {
Future.delayed(
Duration.zero,
() {
// if (Constant.isDemoModeOn) {
// HelperUtils.showSnackBarMessage(
// context,
// UiUtils.getTranslatedLabel(
// context, "thisActionNotValidDemo"));
// } else {
context
.read<DeletePropertyCubit>()
.delete(property!.id!);
// }
},
);
}
},
fontSize: context.font.normal,
width: context.screenWidth / 3.2,
buttonTitle:
UiUtils.translate(context, "deleteBtnLbl")),
),
],
);
},
),
),
),
);
}
}
return SizedBox(
height: 65.rh(context),
child: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20),
child: Row(
children: <Widget>[
Expanded(child: callButton()),
const SizedBox(
width: 8,
),
Expanded(child: messageButton()),
const SizedBox(
width: 8,
),
Expanded(child: chatButton()),
],
),
),
// ClipRRect(
// child: BackdropFilter(
// filter: ImageFilter.blur(sigmaY: 3, sigmaX: 3),
// child: Container(
// color: Colors.black.withOpacity(0.2),
// child: MaterialButton(
// minWidth: double.infinity,
// height: double.infinity,
// onPressed: () {},
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Icon(
// Icons.lock,
// color: context.color.secondaryColor,
// ),
// Text("Subscribe")
// .bold(weight: FontWeight.w700)
// .size(context.font.larger)
// .color(Colors.white),
// ],
// ),
// ),
// ),
// ),
// )
],
),
);
}
String statusText(String text) {
if (text == "1") {
return UiUtils.translate(context, "active");
} else if (text == "0") {
return UiUtils.translate(context, "deactive");
}
return "";
}
Widget setInterest() {
// check if list has this id or not
bool interestedProperty =
Constant.interestedPropertyIds.contains(widget.property?.id);
/// default icon
dynamic icon = AppIcons.interested;
/// first priority is Constant list .
if (interestedProperty == true || widget.property?.isInterested == 1) {
/// If list has id or our property is interested so we are gonna show icon of No Interest
icon = Icons.not_interested_outlined;
}
return BlocConsumer<ChangeInterestInPropertyCubit,
ChangeInterestInPropertyState>(
listener: (context, state) {},
builder: (context, state) {
if (state is ChangeInterestInPropertySuccess) {
if (state.interest == PropertyInterest.interested) {
//If interested show no interested icon
icon = Icons.not_interested_outlined;
} else {
icon = AppIcons.interested;
}
}
return Expanded(
flex: 1,
child: UiUtils.buildButton(
context,
height: 48,
outerPadding: const EdgeInsets.all(1),
isInProgress: state is ChangeInterestInPropertyInProgress,
onPressed: () {
PropertyInterest interest;
bool contains =
Constant.interestedPropertyIds.contains(widget.property!.id!);
if (contains == true || widget.property!.isInterested == 1) {
//change to not interested
interest = PropertyInterest.notInterested;
} else {
//change to not unterested
interest = PropertyInterest.interested;
}
context.read<ChangeInterestInPropertyCubit>().changeInterest(
propertyId: widget.property!.id!.toString(),
interest: interest);
},
buttonTitle: (icon == Icons.not_interested_outlined
? UiUtils.translate(context, "interested")
: UiUtils.translate(context, "interest")),
fontSize: context.font.large,
prefixWidget: Padding(
padding: const EdgeInsetsDirectional.only(end: 14),
child: (icon is String)
? SvgPicture.asset(
icon,
width: 22,
height: 22,
)
: Icon(
icon,
color: Theme.of(context).colorScheme.buttonColor,
size: 22,
),
),
),
);
},
);
}
bool isDisabledEnquireButton(state, id) {
if (state is EnquiryIdsLocalState) {
if (state.ids?.contains(id.toString()) ?? false) {
return true;
} else {
return false;
}
}
return false;
}
bool showIcon(state, id) {
if (state is EnquiryIdsLocalState) {
if (state.ids?.contains(id.toString()) ?? false) {
return false;
} else {
return true;
}
}
return true;
}
String setLable(state, id) {
if (state is EnquiryIdsLocalState) {
if (state.ids?.contains(id.toString()) ?? false) {
return UiUtils.translate(
context,
"sent",
);
} else {
return UiUtils.translate(
context,
"sendEnqBtnLbl",
);
}
}
return "";
}
Widget callButton() {
return UiUtils.buildButton(context,
fontSize: context.font.large,
outerPadding: const EdgeInsets.all(1),
buttonTitle: UiUtils.translate(context, "call"),
width: 35,
onPressed: _onTapCall,
prefixWidget: Padding(
padding: const EdgeInsets.only(right: 3.0),
child: SizedBox(
width: 16,
height: 16,
child: UiUtils.getSvg(AppIcons.call, color: Colors.white)),
));
}
Widget messageButton() {
return UiUtils.buildButton(context,
fontSize: context.font.large,
outerPadding: const EdgeInsets.all(1),
buttonTitle: UiUtils.translate(context, "sms"),
width: 35,
onPressed: _onTapMessage,
prefixWidget: SizedBox(
width: 16,
height: 16,
child: Padding(
padding: const EdgeInsets.only(right: 3.0),
child: UiUtils.getSvg(AppIcons.whatsapp,
color: context.color.buttonColor),
),
));
}
Widget chatButton() {
return UiUtils.buildButton(context,
fontSize: context.font.large,
outerPadding: const EdgeInsets.all(1),
buttonTitle: UiUtils.translate(context, "chat"),
width: 35,
onPressed: _onTapChat,
prefixWidget: SizedBox(
width: 16,
height: 16,
child: Padding(
padding: const EdgeInsets.only(right: 3.0),
child:
UiUtils.getSvg(AppIcons.chat, color: context.color.buttonColor),
),
));
}
_onTapCall() async {
print("AAA $isPremiumUser");
if (isPremiumProperty && !isPremiumUser) {
GuestChecker.check(onNotGuest: () {
shouldShowSubscriptionOverlay.value = true;
return;
});
return;
}
var contactNumber = widget.property?.customerNumber;
var url = Uri.parse("tel: $contactNumber"); //{contactNumber.data}
if (await canLaunchUrl(url)) {
await launchUrl(url);
} else {
throw 'Could not launch $url';
}
}
_onTapMessage() async {
if (isPremiumProperty && !isPremiumUser) {
GuestChecker.check(
onNotGuest: () {
shouldShowSubscriptionOverlay.value = true;
return;
},
);
return;
}
var contactNumber = widget.property?.customerNumber;
var url = Uri.parse("sms:$contactNumber"); //{contactNumber.data}
if (await canLaunchUrl(url)) {
await launchUrl(url);
} else {
throw 'Could not launch $url';
}
}
_onTapChat() {
GuestChecker.check(onNotGuest: () {
if (isPremiumProperty && !isPremiumUser) {
shouldShowSubscriptionOverlay.value = true;
return;
}
Navigator.push(context, BlurredRouter(
builder: (context) {
return MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => SendMessageCubit(),
),
BlocProvider(
create: (context) => LoadChatMessagesCubit(),
),
BlocProvider(
create: (context) => DeleteMessageCubit(),
),
],
child: ChatScreen(
profilePicture: property?.customerProfile ?? "",
userName: property?.customerName ?? "",
propertyImage: property?.titleImage ?? "",
proeprtyTitle: property?.title ?? "",
userId: (property?.addedBy).toString(),
from: "property",
propertyId: (property?.id).toString(),
),
);
},
));
});
}
}
class InterestedUserListWidget extends StatefulWidget {
const InterestedUserListWidget({
super.key,
required this.totalCount,
required this.interestedUserCubitReference,
});
final String totalCount;
final GetInterestedUserCubit interestedUserCubitReference;
@override
State<InterestedUserListWidget> createState() =>
_InterestedUserListWidgetState();
}
class _InterestedUserListWidgetState extends State<InterestedUserListWidget> {
final ScrollController _bottomSheetScrollController = ScrollController();
@override
void initState() {
_bottomSheetScrollController.addListener(() {
if (_bottomSheetScrollController.isEndReached()) {
if (widget.interestedUserCubitReference.hasMoreData()) {
widget.interestedUserCubitReference.fetchMore();
}
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
return ClipRRect(
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.circular(10),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 3,
sigmaY: 10,
),
child: ScrollConfiguration(
behavior: RemoveGlow(),
child: SingleChildScrollView(
controller: _bottomSheetScrollController,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(14.0),
child: const Text("Interested Users")
.size(context.font.larger)
.bold(),
),
// SizedBox(
// height: 10,
// ),
// SizedBox(
// child: Container(
// width: context.screenWidth,
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Text("Interested User Count")
// .size(context.font.large)
// .bold(),
// Text("${widget.totalCount}")
// ]),
// // color: Colors.red,
// ),
// ),
// const SizedBox(
// height: 10,
// ),
BlocBuilder<GetInterestedUserCubit, GetInterestedUserState>(
bloc: widget.interestedUserCubitReference,
builder: (context, state) {
if (state is GetInterestedUserInProgress) {
return Center(child: UiUtils.progress());
}
if (state is GetInterestedUserSuccess) {
if (state.list.isEmpty) {
return const Center(
child: Text("No data found"),
);
}
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
InterestedUserModel interestedUser =
state.list[index];
return InterestedUserCard(
interestedUser: interestedUser);
},
itemCount: state.list.length,
shrinkWrap: true,
);
}
return Container();
},
),
],
),
),
),
),
);
}
}
class InterestedUserCard extends StatelessWidget {
const InterestedUserCard({
super.key,
required this.interestedUser,
});
final InterestedUserModel interestedUser;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(14.0),
child: Container(
child: Row(
children: [
// CircleAvatar(radius: 25, backgroundImage: SvgPro),
Container(
width: 50,
height: 50,
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(
shape: BoxShape.circle,
// color: Colors.red,
),
child: UiUtils.getImage(interestedUser.image ?? ""),
),
const SizedBox(
width: 10,
),
Expanded(
flex: 3,
child: Text(interestedUser.name ?? "").setMaxLines(lines: 1),
),
const SizedBox(
width: 10,
),
const Spacer(),
Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () async {
await launchUrl(
Uri.parse("mailto:${interestedUser.email}"),
mode: LaunchMode.externalApplication);
},
icon: Icon(
Icons.email,
color: context.color.tertiaryColor,
)),
IconButton(
onPressed: () async {
await launchUrl(Uri.parse("tel:${interestedUser.mobile}"),
mode: LaunchMode.externalApplication);
},
color: context.color.tertiaryColor,
icon: const Icon(Icons.call)),
],
)
],
),
),
);
}
}
class GoogleMapScreen extends StatefulWidget {
final double latitude;
final double longitude;
const GoogleMapScreen({
super.key,
required this.latitude,
required this.longitude,
required CameraPosition kInitialPlace,
required Completer<GoogleMapController> controller,
}) : _kInitialPlace = kInitialPlace,
_controller = controller;
final CameraPosition _kInitialPlace;
final Completer<GoogleMapController> _controller;
@override
State<GoogleMapScreen> createState() => _GoogleMapScreenState();
}
class _GoogleMapScreenState extends State<GoogleMapScreen> {
bool isGoogleMapVisible = false;
@override
void initState() {
Future.delayed(const Duration(milliseconds: 500), () {
isGoogleMapVisible = true;
setState(() {});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
isGoogleMapVisible = false;
setState(() {});
await Future.delayed(const Duration(milliseconds: 500));
Future.delayed(
Duration.zero,
() {
Navigator.pop(context);
},
);
return false;
},
child: Builder(builder: (context) {
if (!isGoogleMapVisible) {
return Center(child: UiUtils.progress());
}
return GoogleMap(
myLocationButtonEnabled: false,
gestureRecognizers: <f.Factory<OneSequenceGestureRecognizer>>{
f.Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
},
markers: {
Marker(
markerId: const MarkerId("1"),
position: LatLng(widget.latitude, widget.longitude))
},
mapType: AppSettings.googleMapType,
initialCameraPosition: widget._kInitialPlace,
onMapCreated: (GoogleMapController controller) {
if (!widget._controller.isCompleted) {
widget._controller.complete(controller);
}
},
);
}),
);
}
}
class AgentProfileWidget extends StatelessWidget {
final bool hideDetails;
const AgentProfileWidget({
super.key,
required this.hideDetails,
required this.widget,
});
final PropertyDetails widget;
@override
Widget build(BuildContext context) {
return HideDetailsBlur(
hide: hideDetails,
sigmaX: 4,
sigmaY: 4,
child: Row(
children: [
GestureDetector(
onTap: () {
if (hideDetails) return;
UiUtils.showFullScreenImage(context,
provider:
NetworkImage(widget.property?.customerProfile ?? ""));
},
child: Container(
width: 70,
height: 70,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(10)),
child: UiUtils.getImage(widget.property?.customerProfile ?? "",
fit: BoxFit.cover)
// CachedNetworkImage(
// imageUrl: widget.propertyData?.customerProfile ?? "",
// fit: BoxFit.cover,
// ),
),
),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(widget.property?.customerName ?? "")
.size(context.font.large)
.bold(),
Text(widget.property?.customerEmail ?? ""),
],
),
)
],
),
);
}
}
class OutdoorFacilityListWidget extends StatelessWidget {
final List<AssignedOutdoorFacility> outdoorFacilityList;
const OutdoorFacilityListWidget({Key? key, required this.outdoorFacilityList})
: super(key: key);
@override
Widget build(BuildContext context) {
CrossAxisAlignment getCrossAxisAlignment(int columnIndex) {
if (columnIndex == 1) {
return CrossAxisAlignment.center;
} else if (columnIndex == 2) {
return CrossAxisAlignment.end;
} else {
return CrossAxisAlignment.start;
}
}
return GridView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemCount: outdoorFacilityList.length,
itemBuilder: (context, index) {
AssignedOutdoorFacility facility = outdoorFacilityList[index];
return Column(
//crossAxisAlignment: getCrossAxisAlignment(columnIndex),
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
// width: 60,
// height: 60,
decoration: BoxDecoration(
// shape: BoxShape.circle,
borderRadius: BorderRadius.circular(15),
color: context.color.tertiaryColor.withOpacity(0.2)),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: SizedBox(
width: 36,
height: 36,
child: UiUtils.imageType(
facility.image ?? "",
color: Constant.adaptThemeColorSvg
? context.color.tertiaryColor
: null,
// fit: BoxFit.cover,
width: 20,
height: 20,
),
),
),
),
const SizedBox(height: 8),
Text(facility.name ?? "")
.centerAlign()
.size(context.font.normal)
.color(context.color.textColorDark)
.setMaxLines(lines: 2),
const SizedBox(height: 2),
Text("${facility.distance} KM")
.centerAlign()
.size(context.font.small)
.color(context.color.textLightColor)
.setMaxLines(lines: 1)
],
),
],
);
},
);
}
}
class HideDetailsBlur extends StatelessWidget {
final Widget child;
final bool hide;
final double? sigmaX;
final double? sigmaY;
const HideDetailsBlur(
{super.key,
required this.child,
required this.hide,
this.sigmaX,
this.sigmaY});
@override
Widget build(BuildContext context) {
return ClipRRect(
child: Stack(
// fit: StackFit.expand,
children: [
child,
if (hide)
BackdropFilter(
filter: ImageFilter.blur(sigmaY: sigmaY ?? 3, sigmaX: sigmaX ?? 4),
child: Container(),
)
],
));
}
}