import React, { useContext, useEffect } from "react"; import { useState } from "react"; import { Link, Navigate, useLocation, useNavigate, useParams, } from "react-router-dom"; import FaqAccordion from "@/components/frontend/FaqAccordion"; import ReviewCard from "@/components/frontend/ReviewCard"; import StarIcon from "@/components/frontend/icons/StarIcon"; import MkdSDK from "@/utils/MkdSDK"; import { callCustomAPI } from "@/utils/callCustomAPI"; import DateTimePicker from "@/components/frontend/DateTimePicker"; import { useForm } from "react-hook-form"; import { useBookingContext } from "./bookingContext"; import CustomSelect from "@/components/frontend/CustomSelect"; import { GlobalContext } from "@/globalContext"; import FavoriteButton from "@/components/frontend/FavoriteButton"; import Counter from "@/components/frontend/Counter"; import { Tooltip } from "react-tooltip"; import { usePropertyAddons, usePropertySpace, usePropertySpaceImages, usePublicUserData, usePropertySpaceAmenities, usePropertySpaceFaqs, usePropertySpaceReviews, } from "@/hooks/api"; import PropertyImageSlider from "@/components/frontend/PropertyImageSlider"; import PropertySpaceMapImage from "@/components/frontend/PropertySpaceMapImage"; import AllReviewsModal from "@/components/frontend/AllReviewsModal"; import { AuthContext } from "@/authContext"; import CircleCheckIcon from "@/components/frontend/icons/CircleCheckIcon"; let sdk = new MkdSDK(); const PropertyPage = () => { const { dispatch: globalDispatch, state: globalState } = useContext(GlobalContext); const { state: authState, dispatch: authDispatch } = useContext(AuthContext); const { state: spaceData } = useLocation(); const { bookingData, dispatch } = useBookingContext(); const [galleryOpen, setGalleryOpen] = useState(false); const [reviewsPopup, setReviewsPopup] = useState(false); const [fetching, setFetching] = useState(true); const navigate = useNavigate(); const { id } = useParams(); const bookingDetails = bookingData?.from === "" ? bookingData : JSON.parse(localStorage.getItem("booking_details")); const [reviewDirection, setReviewDirection] = useState("DESC"); const [bookedSlots, setBookedSlots] = useState([]); const [scheduleTemplate, setScheduleTemplate] = useState({}); const [render, forceRender] = useState(false); const { handleSubmit, register, setValue } = useForm({ defaultValues: bookingDetails, }); const [showCalendar, setShowCalendar] = useState(false); const { propertySpace, notFound } = usePropertySpace(id, render); const hostData = usePublicUserData(propertySpace.host_id); const spaceImages = usePropertySpaceImages( propertySpace.id, true, setFetching ); const spaceAddons = usePropertyAddons(propertySpace.property_id); const spaceAmenities = usePropertySpaceAmenities(propertySpace.id); const faqs = usePropertySpaceFaqs(propertySpace.id); const reviews = usePropertySpaceReviews(propertySpace.id); const [showMap, setShowMap] = useState(false); const { pathname } = useLocation(); if (!fetching && spaceImages.length === 0) { navigate("*"); } async function fetchBookedSlots(id) { try { const result = await callCustomAPI( "customer/schedule", "post", { property_spaces_id: id }, "", null, "v3" ); if (Array.isArray(result.list)) { setBookedSlots(result.list); } } catch (err) { globalDispatch({ type: "SHOW_ERROR", payload: { heading: "Operation failed", message: err.message, }, }); } } async function fetchScheduleTemplate(id) { try { const result = await callCustomAPI( "property_spaces_schedule_template", "post", { page: 1, limit: 1, where: [`property_spaces_id = ${id}`], }, "PAGINATE" ); if (Array.isArray(result.list) && result.list.length > 0) { setScheduleTemplate({ custom_slots: result.list[0].custom_slots }); } if (result.list[0]?.schedule_template_id) { const templateResult = await callCustomAPI( "schedule_template", "post", { page: 1, limit: 1, where: [`id = ${result.list[0].schedule_template_id}`], }, "PAGINATE" ); if ( Array.isArray(templateResult.list) && (templateResult.list[0] ?? {}) ) { setScheduleTemplate((prev) => { let updated = { ...prev, ...templateResult.list[0] }; return updated; }); } } } catch (err) { globalDispatch({ type: "SHOW_ERROR", payload: { heading: "Operation failed", message: err.message, }, }); } } function switchToCustomer() { authDispatch({ type: "SWITCH_TO_CUSTOMER" }); globalDispatch({ type: "SHOW_CONFIRMATION", payload: { heading: "Success", message: `You are now signed in as a customer`, btn: "Ok got it", }, }); } const onSubmit = async (data) => { if (!authState.isAuthenticated) { navigate(`/login?redirect_uri=${pathname}`); return; } if (authState.user == propertySpace.host_id) { globalDispatch({ type: "SHOW_ERROR", payload: { heading: "error", message: "Owners can't book their own spaces", }, }); return; } if (globalState.user.verificationStatus != 1) { globalDispatch({ type: "OPEN_NOT_VERIFIED_MODAL" }); return; } dispatch({ type: "SET_BOOKING_DETAILS", payload: { ...data, ...propertySpace }, }); navigate("booking-preview"); }; useEffect(() => { if (isNaN(id)) return; fetchBookedSlots(id); fetchScheduleTemplate(id); // if (spaceImages.length === 0) { // navigate("*") // } }, []); const sortByPostDate = (a, b) => { if (reviewDirection == "DESC") { return new Date(b.post_date) - new Date(a.post_date); } return new Date(a.post_date) - new Date(b.post_date); }; if (notFound || isNaN(id)) return ; return (
{ setShowCalendar(false); }} >

{propertySpace.name ?? spaceData?.name}

{( Number( propertySpace.average_space_rating ?? spaceData?.average_space_rating ) || 0 ).toFixed(1)} ( {propertySpace.space_rating_count ?? spaceData?.space_rating_count} )

Save
{spaceImages[0]?.photo_url && ( )} {spaceImages[1]?.photo_url && ( )}
{spaceImages[2]?.photo_url && ( )} {spaceImages[3]?.photo_url && ( )}
{spaceImages[4]?.photo_url && ( )}

Description

{propertySpace.description ?? spaceData?.description}


Amenities

    {spaceAmenities.map((am, idx) => (
  • {am.amenity_name}
  • ))}

Add ons

    {spaceAddons.map((addon) => (
  • {" "}
    {addon.add_on_name}
    {" "}
    {" "} ${addon.cost}/h
  • ))}

About the host

{authState.role == "customer" && propertySpace?.id && ( Contact the host )}

{propertySpace.first_name}

{propertySpace.about ?? spaceData?.about}

{authState.role == "customer" && propertySpace?.id && ( Contact the host )}

{propertySpace.about ?? spaceData?.about}


Reviews

{reviews.length == 0 &&

No reviews yet

} {reviews .sort(sortByPostDate) .slice(0, 10) .map((rw) => ( ))}
{reviews.length > 10 ? ( ) : null}

FAQs

{faqs.map((faq) => ( ))}

Property rules

{propertySpace.rule ?? spaceData?.rule}

Price and availability

Max capacity {" "} {propertySpace.max_capacity ?? spaceData?.max_capacity} {" "} people
Pricing from from:{" "} ${propertySpace.rate ?? spaceData?.rate} /h
Number of guests

{authState.role != "customer" && authState.isAuthenticated ? ( ) : ( )}

Price and availability

Max capacity {" "} {propertySpace.max_capacity ?? spaceData?.max_capacity} {" "} people
Pricing from from:{" "} ${propertySpace.rate ?? spaceData?.rate} /h
Number of guests

{authState.role != "customer" && authState.isAuthenticated ? ( ) : ( )}
setGalleryOpen(false)} /> setReviewsPopup(false)} reviews={reviews} onDirectionChange={setReviewDirection} /> setShowMap(false)} />
); }; export default PropertyPage;