Commit fd123e8b by jaymehta

filters final

1 parent 61d982d8
......@@ -15,13 +15,14 @@ const Detail = () => {
const dispatch = useDispatch();
const { allActivitiesData } = useSelector(state => state.allActivitiesData);
const { activityById } = useSelector(state => state.activityById);
const { loadedUser } = useSelector(state => state.loadedUser);
useEffect(() => {
// console.log("router", activityById.data.attributes.category?.data?.attributes.name);
dispatch(getActivitiesByFilters({ category: activityById.data.attributes.category?.data?.id }));
dispatch(getActivitiesByFilters({ category: activityById?.data.attributes.category?.data?.id }));
}, [activityById]);
console.log("activityById", activityById);
// console.log("allActivitiesData", allActivitiesData);
console.log("loadedUser", loadedUser);
return (
<Fragment>
<main>
......@@ -30,12 +31,12 @@ const Detail = () => {
<div className="row hide-on-mobile">
<div className="col-12">
<div className="breadcrum$eq: categoryb-container">
<Breadcrumb>
{/* <Breadcrumb>
<Breadcrumb.Item href="#">Home</Breadcrumb.Item>
<Breadcrumb.Item href="#">New York</Breadcrumb.Item>
<Breadcrumb.Item href="#">Adventure</Breadcrumb.Item>
<Breadcrumb.Item active>Mountain Climbing</Breadcrumb.Item>
</Breadcrumb>
</Breadcrumb> */}
</div>
</div>
</div>
......
......@@ -13,6 +13,8 @@ import { getCurrentEndUser } from "../../redux/actions/userActions.js";
import { Loader } from "react-bootstrap-typeahead";
import { useRouter } from "next/router.js";
import Link from "next/link.js";
import { checkWishlist, toggleWishlist } from "../../redux/actions/activityAction.js";
import WishlistComponent from "./WIshlistComponent.js";
const DetailInfo = ({ activityById }) => {
const router = useRouter();
......@@ -21,7 +23,7 @@ const DetailInfo = ({ activityById }) => {
dispatch(getCurrentEndUser());
}, []);
// const [session, setSession] = useState(null);
const [session, setSession] = useState(null);
const [enqDate, setenqDate] = useState();
const [loading, setloading] = useState(false);
const [quantity, setquantity] = useState();
......@@ -29,19 +31,16 @@ const DetailInfo = ({ activityById }) => {
const [enquiryModal, setenquiryModal] = useState(false);
const { loadedUser } = useSelector(state => state.loadedUser);
const { endUser } = useSelector(state => state.endUser);
// useEffect(() => {
// const fetchSession = async () => {
// setSession(await getSession());
// };
// fetchSession();
// // dispatch(getLoggedInVendor());
// }, []);
useEffect(() => {
const fetchSession = async () => {
setSession(await getSession());
};
fetchSession();
// dispatch(getLoggedInVendor());
}, []);
const [showInfo, setShowInfo] = useState(false);
const [isToggled, setIsToggled] = useState(false);
console.log("session", endUser);
const handleClick = () => {
setIsToggled(!isToggled);
};
console.log("endUser", endUser);
const handleMouseEnter = () => {
setShowInfo(true);
};
......@@ -49,6 +48,7 @@ const DetailInfo = ({ activityById }) => {
const handleMouseLeave = () => {
setShowInfo(false);
};
return (
<Fragment>
<div className="row">
......@@ -60,11 +60,7 @@ const DetailInfo = ({ activityById }) => {
<div className="most-booked">Most Booked</div>
<div className="wishlist-share">
<a href="#" className={`add-to-wishlist ${isToggled ? "active" : ""}`} onClick={handleClick}>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src={isToggled ? "/images/icons/wishlist-01-active.svg" : "/images/icons/wishlist-01.svg"} />
</span>
</a>
{endUser && <WishlistComponent activityId={activityById.data.id} userId={endUser.id} />}
<a href="#" className="add-to-forwardt">
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/forward.svg" />
......@@ -151,101 +147,105 @@ const DetailInfo = ({ activityById }) => {
</div>
)}
</div>
<div className="row hide-on-desktop">
<div className="col-12">
<ul className="availability-wrappper">
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/month.svg" />
</span>
From: {activityById.data.attributes.fromDate} To: {activityById.data.attributes.toDate}
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/time.svg" />
</span>
Time: 9:45 AM - 10:00 AM
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/duration.svg" />
</span>
Duration: 2-3 Hours
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/contact.svg" />
</span>
Contact: 1(332) 204-8500
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/date.svg" />
</span>
Date: All
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/age.svg" />
</span>
Age: 13+
<div className="info-div">
<a className="image-container info" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/info.svg" />
</a>
{showInfo && <div className="info-text">13+. Climbers aged 13-17 must be accompanied by an adult (18+)</div>}
</div>
</li>
</ul>
</div>
</div>
<Modal
show={enquiryModal}
onHide={() => {
setenquiryModal(false);
setquantity();
}}
>
<Modal.Header>Send Enquiry</Modal.Header>
<Modal.Body>
<div>Experience Name:</div>
<div className="" style={{ fontSize: "22px", fontWeight: "bold" }}>
{activityById.data.attributes.name}
</div>
<div className="mt-2">Full Name:</div>
<div className="" style={{ fontWeight: "bold" }}>
{endUser?.attributes.name}
</div>
<div className="mt-2">Email ID:</div>
<div className="" style={{ fontSize: "22px", fontWeight: "bold" }}>
{endUser?.attributes.email}
{activityById && (
<div className="row hide-on-desktop">
<div className="col-12">
<ul className="availability-wrappper">
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/month.svg" />
</span>
From: {activityById.data.attributes.fromDate} To: {activityById.data.attributes.toDate}
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/time.svg" />
</span>
Time: 9:45 AM - 10:00 AM
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/duration.svg" />
</span>
Duration: 2-3 Hours
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/contact.svg" />
</span>
Contact: 1(332) 204-8500
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/date.svg" />
</span>
Date: All
</li>
<li>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/availability/age.svg" />
</span>
Age: 13+
<div className="info-div">
<a className="image-container info" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/info.svg" />
</a>
{showInfo && <div className="info-text">13+. Climbers aged 13-17 must be accompanied by an adult (18+)</div>}
</div>
</li>
</ul>
</div>
<div className="mt-2">Quantity:</div>
<Input
type="number"
onChange={e => {
// console.log("e", e);
setquantity(e.target.value);
}}
></Input>
<Button
disabled={loading || !quantity}
className="mt-2"
onClick={async () => {
setloading(true);
console.log("hello");
let res = await sendEnquiry({ activityId: activityById.data.id, userId: endUser.id, vendorId: activityById.data.attributes.vendor.data.id, quantity });
console.log("res", res);
toast.success("Enquiry sent successfully, our team will get back to you shortly! Thank you!");
setloading(false);
setenquiryModal(false);
setquantity();
}}
>
{loading ? <Loader /> : "Submit"}
</Button>
</Modal.Body>
</Modal>
</div>
)}
{activityById && (
<Modal
show={enquiryModal}
onHide={() => {
setenquiryModal(false);
setquantity();
}}
>
<Modal.Header>Send Enquiry</Modal.Header>
<Modal.Body>
<div>Experience Name:</div>
<div className="" style={{ fontSize: "22px", fontWeight: "bold" }}>
{activityById.data.attributes.name}
</div>
<div className="mt-2">Full Name:</div>
<div className="" style={{ fontWeight: "bold" }}>
{endUser?.attributes.name}
</div>
<div className="mt-2">Email ID:</div>
<div className="" style={{ fontSize: "22px", fontWeight: "bold" }}>
{endUser?.attributes.email}
</div>
<div className="mt-2">Quantity:</div>
<Input
type="number"
onChange={e => {
// console.log("e", e);
setquantity(e.target.value);
}}
></Input>
<Button
disabled={loading || !quantity}
className="mt-2"
onClick={async () => {
setloading(true);
console.log("hello");
let res = await sendEnquiry({ activityId: activityById.data.id, userId: endUser.id, vendorId: activityById.data.attributes.vendor.data.id, quantity });
console.log("res", res);
toast.success("Enquiry sent successfully, our team will get back to you shortly! Thank you!");
setloading(false);
setenquiryModal(false);
setquantity();
}}
>
{loading ? <Loader /> : "Submit"}
</Button>
</Modal.Body>
</Modal>
)}
<Modal
show={loginModal}
centered
......
......@@ -13,9 +13,13 @@ import { fadeIn, zoomIn, slideFromLeft, slideFromRight } from "../animationvaria
import { motion } from "framer-motion";
import { cleanImage } from "../../services/imageHandling.js";
import { useRouter } from "next/router.js";
import WishlistComponent from "./WIshlistComponent.js";
import { useSelector } from "react-redux";
const SimilarExperiences = ({ allActivitiesData }) => {
const router = useRouter();
const [listingData, setListingData] = useState([]);
const { endUser } = useSelector(state => state.endUser);
let ListingData = [];
useEffect(() => {
console.log("allActivitiesData", allActivitiesData);
......@@ -37,58 +41,6 @@ const SimilarExperiences = ({ allActivitiesData }) => {
setListingData(ListingData);
}, [allActivitiesData]);
// ListingData = [
// {
// image: "/images/Browse-Experiences/01.png",
// topRated: "Top Rated",
// title: "City Climb",
// discription: "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
// price: "200",
// offPrice: "40%",
// days: "For 1 Night",
// taxes: "Includes taxes & Fees"
// },
// {
// image: "/images/Browse-Experiences/02.png",
// topRated: "Top Rated",
// title: "City Climb",
// discription: "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
// price: "200",
// offPrice: "40%",
// days: "For 1 Night",
// taxes: "Includes taxes & Fees"
// },
// {
// image: "/images/Browse-Experiences/03.png",
// topRated: "Top Rated",
// title: "City Climb",
// discription: "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
// price: "200",
// offPrice: "40%",
// days: "For 1 Night",
// taxes: "Includes taxes & Fees"
// },
// {
// image: "/images/Browse-Experiences/04.png",
// topRated: "Top Rated",
// title: "City Climb",
// discription: "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
// price: "200",
// offPrice: "40%",
// days: "For 1 Night",
// taxes: "Includes taxes & Fees"
// },
// {
// image: "/images/Browse-Experiences/01.png",
// topRated: "Top Rated",
// title: "City Climb",
// discription: "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
// price: "200",
// offPrice: "40%",
// days: "For 1 Night",
// taxes: "Includes taxes & Fees"
// }
// ];
const projects = {
responsive: {
0: {
......@@ -130,11 +82,6 @@ const SimilarExperiences = ({ allActivitiesData }) => {
<div className="browse-experiences-carousal position-relative">
<Swiper
slidesPerView={1}
// autoplay={{
// delay: 2500,
// disableOnInteraction: false
// }}
// spaceBetween={10}
navigation={{ nextEl: ".similar-experiences-arrow-left", prevEl: ".similar-experiences-arrow-right" }}
breakpoints={{
640: {
......@@ -175,11 +122,12 @@ const SimilarExperiences = ({ allActivitiesData }) => {
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/star.svg" />
</span>
</div>
<div className="wishlist">
{endUser && <WishlistComponent userId={endUser.id} activityId={data.id} />}
{/* <div className="wishlist">
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/wishlist.svg" />
</span>
</div>
</div> */}
</div>
</div>
<div className="discription">
......
import Image from "next/image";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { checkWishlist, deleteWishlist, getWishlists, toggleWishlist } from "../../redux/actions/activityAction";
const WishlistComponent = ({ activityId, userId }) => {
const { wishlists } = useSelector(state => state.wishlists);
const [isActive, setisActive] = useState(false);
const [wishlistId, setwishlistId] = useState();
const dispatch = useDispatch();
// console.log("wishlists", wishlists);
useEffect(() => {
wishlists &&
wishlists.length > 0 &&
wishlists.map(item => {
if (item.attributes.experience.data.id == activityId) {
setisActive(true);
setwishlistId(item.id);
}
});
}, [wishlists]);
return (
<div>
{activityId && userId && (
<div className="wishlist">
<span
onClick={async e => {
e.preventDefault();
if (isActive) {
setisActive(false);
const response = await deleteWishlist({ wishlistId });
dispatch(getWishlists({ endUser: userId }));
// console.log("delete", response);
} else {
setisActive(true);
const response = await toggleWishlist({ activityId, userId });
dispatch(getWishlists({ endUser: userId }));
}
// console.log("response wishlist ", response);
}}
className="image-container"
>
<Image layout="fill" alt="" className="image img-fluid" src={isActive ? "/images/icons/wishlist-01-active.svg" : "/images/icons/wishlist-01.svg"} />
</span>
</div>
)}
</div>
);
};
export default WishlistComponent;
......@@ -5,11 +5,14 @@ import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { cleanImage } from "../../services/imageHandling";
import { Button, Container, Form, Nav, Navbar } from "react-bootstrap";
import { loadUser } from "../../redux/actions/userActions";
import { getCurrentEndUser, loadUser } from "../../redux/actions/userActions";
import { useRouter } from "next/router";
import { getWishlists } from "../../redux/actions/activityAction";
const Header = () => {
const { loadedUser } = useSelector(state => state.loadedUser);
const { endUser } = useSelector(state => state.endUser);
const dispatch = useDispatch();
// console.log("user", loadedUser);
const [isSticky, setIsSticky] = useState(false);
......@@ -29,6 +32,13 @@ const Header = () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
useEffect(() => {
dispatch(getCurrentEndUser());
}, []);
useEffect(() => {
if (endUser) dispatch(getWishlists({ endUser: endUser.id }));
}, [endUser]);
return (
<header className={`header_wrap ${isSticky ? "stick" : ""}`}>
<Navbar expand="lg" className="bg-body-tertiary">
......@@ -69,8 +79,8 @@ const Header = () => {
<Button
onClick={async () => {
signOut({ redirect: false });
await router.push("/")
window.location.reload()
await router.push("/");
window.location.reload();
}}
className="me-3"
variant="primary"
......@@ -80,14 +90,22 @@ const Header = () => {
</div>
) : (
<div>
<Button onClick={()=> {
router.push("/signup/user")
}} className="me-3" variant="primary">
<Button
onClick={() => {
router.push("/signup/user");
}}
className="me-3"
variant="primary"
>
Sign Up
</Button>
<Button onClick={()=> {
router.push("/login/user")
}} className="" variant="primary">
<Button
onClick={() => {
router.push("/login/user");
}}
className=""
variant="primary"
>
Log In
</Button>
</div>
......
import Image from "next/image";
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { fadeIn, zoomIn, slideFromLeft, slideFromRight } from "../animationvariants.js";
import { Button } from "react-bootstrap";
......@@ -11,59 +11,38 @@ import { motion } from "framer-motion";
import "swiper/css";
import "swiper/css/pagination";
import "swiper/css/navigation";
const LetDiscover = () => {
import { cleanImage } from "../../services/imageHandling.js";
import { useRouter } from "next/router.js";
import { Loader } from "react-bootstrap-typeahead";
import { useDispatch, useSelector } from "react-redux";
import { getSubCategoriesByCategoryId } from "../../redux/actions/categoriesAction.js";
import { setActivityFilters } from "../../redux/actions/activityAction.js";
import SubCategoryChips from "./SubCategoryChips.js";
const LetDiscover = ({ categories }) => {
const { subCategories, loading } = useSelector(sate => sate.subCategories);
const { activityFilters } = useSelector(sate => sate.activityFilters);
const router = useRouter();
const dispatch = useDispatch();
const [activeIndex, setActiveIndex] = useState(null);
const handleTitleClick = index => {
// const [loading, setloading] = useState(null);
console.log("categories", categories);
console.log("subCategories", subCategories);
console.log("activityFilters", activityFilters);
const handleTitleClick = ({ index, data }) => {
// setloading(true);
// Check if the clicked index is already active
if (activeIndex === index) {
return; // Do nothing if it's already active
}
// Toggle the active index if it's different from the clicked index
setActiveIndex(index);
// setloading(false);
};
const letDiscoverData = [
{
image: "/images/discover/01.png",
title: "All"
},
{
image: "/images/discover/02.png",
title: "Art & History"
},
{
image: "/images/discover/03.png",
title: "Experiential Dining "
},
{
image: "/images/discover/04.png",
title: "Family"
},
{
image: "/images/discover/05.png",
title: "Fitness"
},
{
image: "/images/discover/06.png",
title: "Performing Arts"
},
{
image: "/images/discover/01.png",
title: "Pop Ups"
},
{
image: "/images/discover/02.png",
title: "Tour"
},
{
image: "/images/discover/03.png",
title: "Classes"
},
{
image: "/images/discover/04.png",
title: "Wellness"
}
];
// useEffect(() => {
// dispatch(getSubCategoriesByCategoryId(router.query.category));
// }, [router]);
const [showCloseIcon, setShowCloseIcon] = useState({});
const handleToggleCloseIcon = index => {
setShowCloseIcon(prevShowCloseIcon => ({
......@@ -71,32 +50,7 @@ const LetDiscover = () => {
[index]: !prevShowCloseIcon[index]
}));
};
const subCategoriesData = [
{
name: "Boat"
},
{
name: "Games"
},
{
name: "Helicopter"
},
{
name: "Ice-skating"
},
{
name: "Jet-skiing"
},
{
name: "Kayaking"
},
{
name: "Park"
},
{
name: "Rooftop"
}
];
console.log("showCloseIcon", showCloseIcon);
return (
<>
<section className="let-discover-session let-discover-listing-session">
......@@ -144,20 +98,46 @@ const LetDiscover = () => {
modules={[Navigation, Autoplay]}
className="mySwiper01 mySwiper02"
>
{letDiscoverData &&
letDiscoverData.map((data, index) => {
<SwiperSlide>
<motion.div variants={zoomIn("left", 0.3)} initial={"hidden"} whileInView={"show"} viewport={{ once: false, amount: 0.2 }}>
<a
className={activeIndex=="All" ? "active" : ""}
onClick={() => {
dispatch(setActivityFilters({ filters: {} }));
handleTitleClick({ index: "All" });
}}
>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src={"/images/discover/01.png"} />
</span>
<div className="title">{"All"}</div>
</a>
</motion.div>
</SwiperSlide>
{categories &&
categories.data.map((data, index) => {
const isActive = activeIndex === index;
return (
<SwiperSlide>
<motion.div variants={zoomIn("left", 0.3)} initial={"hidden"} whileInView={"show"} viewport={{ once: false, amount: 0.2 }}>
<a className={isActive ? "active" : ""} onClick={() => handleTitleClick(index)}>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src={data.image} />
</span>
<div className="title">{data.title}</div>
</a>
</motion.div>
</SwiperSlide>
<>
<SwiperSlide>
<motion.div variants={zoomIn("left", 0.3)} initial={"hidden"} whileInView={"show"} viewport={{ once: false, amount: 0.2 }}>
<a
className={isActive ? "active" : ""}
onClick={async () => {
// router.push(`?category=${data.id}`);
dispatch(setActivityFilters({ filters: { ...activityFilters, category: data.id, subCategories: [] } }));
dispatch(getSubCategoriesByCategoryId(data.id));
handleTitleClick({ index, data });
}}
>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src={cleanImage(data.attributes.image.data.attributes)} />
</span>
<div className="title">{data.attributes.name}</div>
</a>
</motion.div>
</SwiperSlide>
</>
);
})}
</Swiper>
......@@ -179,20 +159,25 @@ const LetDiscover = () => {
</div>
</div>
<div className="row">
<div className="col-12">
<div className="sub-categories">
{subCategoriesData &&
subCategoriesData.map((data, index) => (
<a key={index} onClick={() => handleToggleCloseIcon(index)}>
<span>{data.name}</span>
{showCloseIcon[index] && (
<span className="image-container">
<Image layout="fill" alt="image" className="image" src="/images/icons/close-button.svg" />
</span>
)}
</a>
))}
</div>
<div className="col-12 text-center">
{!loading ? (
<div className="sub-categories">
{activityFilters.category && subCategories &&
subCategories.data.map((data, index) => (
<SubCategoryChips key={index} data={data} />
// <a key={index} onClick={() => handleToggleCloseIcon(index)}>
// <span>{data.attributes.name}</span>
// {showCloseIcon[index] && (
// <span className="image-container">
// <Image layout="fill" alt="image" className="image" src="/images/icons/close-button.svg" />
// </span>
// )}
// </a>
))}
</div>
) : (
<Loader />
)}
</div>
</div>
</div>
......
import React, { Fragment } from "react";
import React, { Fragment, useEffect } from "react";
import ListingInner from "./ListingInner";
import SignUpToExperienceOurPlatform from "../home/SignUpToExperienceOurPlatform";
import LetDiscover from "./LetDiscover";
......@@ -6,12 +6,16 @@ import { useSelector } from "react-redux";
const Listing = () => {
const { allActivitiesData } = useSelector(sate => sate.allActivitiesData);
console.log("allActivitiesData >>>> 123", allActivitiesData)
const { categories } = useSelector(sate => sate.categories);
const { subCategories } = useSelector(sate => sate.subCategories);
console.log("allActivitiesData >>>> 123", allActivitiesData);
return (
<Fragment>
<main>
<LetDiscover />
<LetDiscover categories={categories} subCategories={subCategories}/>
<ListingInner allActivitiesData={allActivitiesData} />
<SignUpToExperienceOurPlatform />
</main>
......
......@@ -3,10 +3,18 @@ import React, { useState } from "react";
import { Accordion, Form } from "react-bootstrap";
import { Slider } from "antd";
import { DatePicker, Space } from "antd";
import { useDispatch, useSelector } from "react-redux";
import { setActivityFilters } from "../../redux/actions/activityAction";
import { TimePicker } from "antd";
import dayjs from "dayjs";
import { Input } from "react-bootstrap-typeahead";
const format = "HH:mm";
const suitableAgeGroups = [2, 5, 8, 10, 12, 14, 16];
const ListingFilter = () => {
const [showContent, setShowContent] = useState(false);
const dispatch = useDispatch();
const { activityFilters } = useSelector(sate => sate.activityFilters);
const { subCategories, loading } = useSelector(sate => sate.subCategories);
const toggleContent = () => {
setShowContent(!showContent);
};
......@@ -20,7 +28,12 @@ const ListingFilter = () => {
<div className="df-sb p-all">
<div className="head">Filter By:</div>
<div className="reset">
<a href="">
<a
onClick={e => {
e.preventDefault();
dispatch(setActivityFilters({ filters: {} }));
}}
>
Reset
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/reset-icon.svg" />
......@@ -35,23 +48,29 @@ const ListingFilter = () => {
</div>
<div className="inner">
<div className="price">
$200 - $5000+ <span className="sub-text">Average price is $5000</span>
$0 - 3000 <span className="sub-text"></span>
</div>
<div className="graph">
<Slider
range={{
draggableTrack: true
}}
defaultValue={[200, 5000]}
min={200}
max={5000}
onChange={e => {
// console.log(e);
setTimeout(() => {
dispatch(setActivityFilters({ filters: { ...activityFilters, priceLowerLimit: e[0], priceUpperLimit: e[1] } }));
}, 1000);
}}
defaultValue={[0, 3000]}
min={0}
max={3000}
tooltip={{
open: true
}}
/>
<div className="graph-price">
<div className="min">$200</div>
<div className="min">$5000</div>
<div className="min">$0</div>
<div className="min">$3000</div>
</div>
{/* <img className="img-fluid w-100" src="/images/buget.svg" /> */}
</div>
......@@ -59,274 +78,121 @@ const ListingFilter = () => {
</div>
<div className="box-01">
<div className="p-all">
<div className="head">Experience Category</div>
</div>
<div className="inner">
<Accordion className="accordion-filter" defaultActiveKey="0" flush>
<Accordion.Item eventKey="0">
<Accordion.Header>Adventure</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Helicopter">
<input id="Helicopter" type="checkbox" /> Helicopter
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Ice-skating">
<input id="Ice-skating" type="checkbox" /> Ice-skating
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Jet-skiing">
<input id="Jet-skiing" type="checkbox" /> Jet-skiing
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Kayaking">
<input id="Kayaking" type="checkbox" /> Kayaking
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Park">
<input id="Park" type="checkbox" /> Park
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Rooftop">
<input id="Rooftop" type="checkbox" /> Rooftop
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="1">
<Accordion.Header>Art & History</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="2">
<Accordion.Header>Experiential Dining </Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="3">
<Accordion.Header>Family</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="4">
<Accordion.Header>Fitness</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="5">
<Accordion.Header>Performing Arts</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="6">
<Accordion.Header>Pop Ups</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="7">
<Accordion.Header>Tour</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="8">
<Accordion.Header>Classes</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="9">
<Accordion.Header>Wellness</Accordion.Header>
<Accordion.Body>
<div className="data-filters-item">
<label htmlFor="Boat">
<input id="Boat" type="checkbox" /> Boat
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Games">
<input id="Games" type="checkbox" /> Games
</label>
</div>
</Accordion.Body>
</Accordion.Item>
</Accordion>
<div className="head">Experience Sub Categories</div>
</div>
{activityFilters.category ? (
<div className="inner">
<label>
<input
// checked={activityFilters.subCategories?.includes(data.attributes.name)}
type="checkbox"
checked={activityFilters.subCategories?.length == subCategories?.data.length}
onChange={e => {
console.log(e.target.checked, e.target.value);
if (e.target.checked) {
dispatch(
setActivityFilters({
filters: {
...activityFilters,
subCategories: subCategories.data.map(data => {
return data.id;
})
}
})
);
} else {
dispatch(
setActivityFilters({
filters: {
...activityFilters,
subCategories: []
}
})
);
}
}}
/>{" "}
Select all
</label>
{activityFilters &&
subCategories &&
subCategories.data.map(data => {
return (
<div className="data-filters-item">
<label>
<input
checked={activityFilters.subCategories?.includes(data.id)}
type="checkbox"
value={data.id}
onChange={e => {
// e.preventDefault()
// console.log(">>>>>", e.target.checked, e.target.value);
if (activityFilters.subCategories.length > 0) {
// console.log("here >>>>", activityFilters.subCategories.includes(e.target.value),activityFilters.subCategories, e.target.value)
if (activityFilters.subCategories.includes(Number(e.target.value)) && !e.target.checked) {
let newArr = activityFilters.subCategories.filter(item => item != data.id);
dispatch(setActivityFilters({ filters: { ...activityFilters, subCategories: newArr } }));
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, subCategories: [...activityFilters.subCategories, data.id] } }));
}
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, subCategories: [data.id] } }));
}
}}
/>{" "}
{data.attributes.name}
</label>
</div>
);
})}
</div>
) : (
<div className="m-2 text-center">* Please select a category to explore sub categories </div>
)}
</div>
<div className="box-01">
<div className="p-all">
<div className="head">Location Type:</div>
<div className="head">Activity Type:</div>
</div>
<div className="inner">
<div className="data-filters-item">
<label htmlFor="Indoor">
<input id="Indoor" type="checkbox" /> Indoor
<input
checked={activityFilters.activityType == "indoor"}
onChange={e => {
if (e.target.checked) {
dispatch(setActivityFilters({ filters: { ...activityFilters, activityType: "indoor" } }));
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, activityType: null } }));
}
}}
id="Indoor"
type="checkbox"
/>{" "}
Indoor
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Outdoor">
<input id="Outdoor" type="checkbox" /> Outdoor
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Both">
<input id="Both" type="checkbox" /> Both
<input
checked={activityFilters.activityType == "outdoor"}
onChange={e => {
if (e.target.checked) {
dispatch(setActivityFilters({ filters: { ...activityFilters, activityType: "outdoor" } }));
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, activityType: null } }));
}
}}
id="Outdoor"
type="checkbox"
/>
Outdoor
</label>
</div>
</div>
</div>
{/* <div className="box-01">
<div className="p-all">
<div className="head">Rating:</div>
</div>
<div className="inner">
<div className="data-filters-item">
<label htmlFor="Excellent (9+)">
<input name="Rating" id="Excellent (9+)" type="radio" /> Excellent (9+)
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Very Good (7+)">
<input name="Rating" id="Very Good (7+)" type="radio" /> Very Good (7+)
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Pleasant (5+)">
<input name="Rating" id="Pleasant (5+)" type="radio" /> Pleasant (5+)
</label>
</div>
</div>
</div> */}
{/* <div className="box-01">
<div className="p-all">
<div className="head">Months:</div>
</div>
<div className="inner">
<div className="data-filters-item">
<Form.Select aria-label="Default select example">
<option>Select</option>
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
</Form.Select>
</div>
</div>
</div> */}
{/* <div className="box-01">
<div className="p-all">
<div className="head">Days</div>
</div>
<div className="inner">
<div className="data-filters-item">
<label htmlFor="Weekdays">
<input id="Weekdays" type="checkbox" /> Weekdays
</label>
</div>
<div className="data-filters-item">
<label htmlFor="Weekends">
<input id="Weekends" type="checkbox" /> Weekends
</label>
</div>
<div className="data-filters-item">
<label htmlFor="All">
<input id="All" type="checkbox" /> All
</label>
</div>
</div>
</div> */}
<div className="box-01">
<div className="p-all">
<div className="head">Date</div>
......@@ -336,102 +202,56 @@ const ListingFilter = () => {
<div className="col-6">
<div>From</div>
<Space direction="vertical">
<DatePicker onChange={onChange} />
<DatePicker
onChange={(date, dateString) => {
console.log("date", date, dateString);
dispatch(setActivityFilters({ filters: { ...activityFilters, startDate: dateString !== "" ? dateString : null } }));
}}
/>
</Space>
</div>
<div className="col-6">
<div>To</div>
<Space direction="vertical">
<DatePicker onChange={onChange} />
<DatePicker
onChange={(date, dateString) => {
console.log("date", date, dateString);
dispatch(setActivityFilters({ filters: { ...activityFilters, endDate: dateString !== "" ? dateString : null } }));
}}
/>
</Space>
</div>
</div>
</div>
</div>
<div className="box-01">
<div className="p-all">
<div className="head">Time</div>
</div>
<div className="inner">
<div className="data-filters-item">
<div className="time-filter">
<div className="time-field">
<div className="time">
<div>Hour</div>
<div className="">
<input className="form-control" type="text" placeholder="0" />
</div>
</div>
<div className="time">
<div>Mins</div>
<div className="">
<input className="form-control" type="text" placeholder="0" />
</div>
</div>
</div>
<div className="ampm-field">
<div className="ampm">
<input className="form-check-label" type="radio" id="Am" name="ampm" />
<label htmlFor="Am">Am</label>
</div>
<div className="ampm">
<input className="form-check-label" type="radio" id="Pm" name="ampm" />
<label htmlFor="Pm">Pm</label>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="box-01">
<div className="p-all">
<div className="head">Duration</div>
</div>
<div className="inner">
<div className="data-filters-item">
<label htmlFor="10 Mins">
<input id="10 Mins" type="checkbox" /> 10 Mins
</label>
</div>
<div className="data-filters-item">
<label htmlFor="10 to 60 Mins (Activity) - 120 Mins">
<input id="10 to 60 Mins (Activity) - 120 Mins" type="checkbox" /> 10 to 60 Mins (Activity) - 120 Mins
</label>
</div>
<div className="data-filters-item">
<label htmlFor="15+ (Activity) - 60 Mins ">
<input id="15+ (Activity) - 60 Mins " type="checkbox" /> 15+ (Activity) - 60 Mins
</label>
</div>
<div className="data-filters-item">
<label htmlFor="15 to 20 Mins ">
<input id="15 to 20 Mins " type="checkbox" /> 15 to 20 Mins
</label>
</div>
<div className="data-filters-item">
<label htmlFor="20 to 40 Mins">
<input id="20 to 40 Mins" type="checkbox" /> 20 to 40 Mins
</label>
</div>
<div className="data-filters-item">
<label htmlFor="20 Mins">
<input id="20 Mins" type="checkbox" /> 20 Mins
</label>
</div>
{showContent && (
<div className="data-filters-item">
<label htmlFor="30 Mins">
<input id="30 Mins" type="checkbox" /> 30 Mins
</label>
</div>
)}
<div className="data-filters-item">
<button className="show-all" onClick={toggleContent}>
{showContent ? "Hide" : "Show All"}
<img src={showContent ? "/images/icons/down-s.svg" : "/images/icons/up-s.svg"} alt="" style={{ marginLeft: "5px" }} />
</button>
</div>
<label>Minimum duration:</label>
<Input
placeholder="in minutes"
type="number"
onChange={e => {
// console.log(e.target.value);
setTimeout(() => {
dispatch(setActivityFilters({ filters: { ...activityFilters, minDuration: e.target.value } }));
}, 1500);
}}
></Input>
<label>Maximum duration:</label>
<Input
placeholder="in minutes"
type="number"
onChange={e => {
// console.log(e.target.value);
setTimeout(() => {
dispatch(setActivityFilters({ filters: { ...activityFilters, maxDuration: e.target.value } }));
}, 1500);
}}
></Input>
</div>
</div>
<div className="box-01">
......@@ -441,8 +261,27 @@ const ListingFilter = () => {
<div className="inner">
<div className="data-filters-item">
<label htmlFor="">Minimum Group Size</label>
<Form.Select aria-label="Default select example">
<Form.Select
aria-label="Default select example"
onChange={e => {
console.log(e.target.value);
if (e.target.value != "select") {
dispatch(setActivityFilters({ filters: { ...activityFilters, minGroupSize: e.target.value } }));
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, minGroupSize: null } }));
}
// setTimeout(() => {
// }, 1500);
}}
>
<option>Select</option>
<option>1</option>
<option>2</option>
<option>5</option>
<option>10</option>
<option>15</option>
<option>20</option>
{/* <option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option> */}
......@@ -450,8 +289,27 @@ const ListingFilter = () => {
</div>
<div className="data-filters-item">
<label htmlFor="">Maximum Group Size</label>
<Form.Select aria-label="Default select example">
<Form.Select
onChange={e => {
console.log(e.target.value);
if (e.target.value != "select") {
dispatch(setActivityFilters({ filters: { ...activityFilters, maxGroupSize: e.target.value } }));
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, maxGroupSize: null } }));
}
// setTimeout(() => {
// }, 1500);
}}
aria-label="Default select example"
>
<option>Select</option>
<option>1</option>
<option>2</option>
<option>5</option>
<option>10</option>
<option>15</option>
<option>20</option>
{/* <option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option> */}
......@@ -464,49 +322,26 @@ const ListingFilter = () => {
<div className="head">Suitable Age Group:</div>
</div>
<div className="inner">
<div className="data-filters-item">
<label htmlFor="2+">
<input id="2+" type="checkbox" /> 2+
</label>
</div>
<div className="data-filters-item">
<label htmlFor="5+">
<input id="5+" type="checkbox" /> 5+
</label>
</div>
<div className="data-filters-item">
<label htmlFor="8+ ">
<input id="8+ " type="checkbox" /> 8+
</label>
</div>
<div className="data-filters-item">
<label htmlFor="10+ ">
<input id="10+ " type="checkbox" /> 10+
</label>
</div>
<div className="data-filters-item">
<label htmlFor="12+">
<input id="12+" type="checkbox" /> 12+
</label>
</div>
<div className="data-filters-item">
<label htmlFor="14+">
<input id="14+" type="checkbox" /> 14+
</label>
</div>
{showContent && (
<div className="data-filters-item">
<label htmlFor="16+">
<input id="16+" type="checkbox" /> 16+
</label>
</div>
)}
<div className="data-filters-item">
<button className="show-all" onClick={toggleContent}>
{showContent ? "Hide" : "Show All"}
<img src={showContent ? "/images/icons/down-s.svg" : "/images/icons/up-s.svg"} alt="" style={{ marginLeft: "5px" }} />
</button>
</div>
<Form.Select
onChange={e => {
console.log(e.target.value);
if (e.target.value != "select") {
dispatch(setActivityFilters({ filters: { ...activityFilters, minAge: e.target.value } }));
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, minAge: null } }));
}
// setTimeout(() => {
// }, 1500);
}}
aria-label="Default select example"
>
<option>Select</option>
{suitableAgeGroups.map(item => {
return <option value={item}> {item}+ </option>;
})}
</Form.Select>
</div>
</div>
<div></div>
......
......@@ -2,12 +2,17 @@ import React, { useEffect, useState } from "react";
import ListingFilter from "./ListingFilter";
import ListingItems from "./ListingItems";
import Image from "next/image";
import { getActivitiesByFilters, getWishlists, setActivityFilters } from "../../redux/actions/activityAction";
import { useDispatch, useSelector } from "react-redux";
const ListingInner = ({allActivitiesData}) => {
console.log("allActivitiesData >>>>>", allActivitiesData)
const ListingInner = ({ allActivitiesData }) => {
console.log("allActivitiesData", allActivitiesData);
const [isFilterViewOpen, setIsFilterViewOpen] = useState(false);
const [isGridViewOpen, setIsGridViewOpen] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const { activityFilters } = useSelector(sate => sate.activityFilters);
const dispatch = useDispatch();
const [size, setSize] = useState(768);
const toggleGridViewDropdown = () => {
......@@ -36,14 +41,70 @@ const ListingInner = ({allActivitiesData}) => {
window.removeEventListener("resize", handleResize);
};
}, []);
// USEEFFECT FOR FILTERS
useEffect(() => {
let filters = {};
// console.log("subcategory here", activityFilters.startDate);
if (activityFilters.category) {
filters["category"] = { id: { $eq: activityFilters.category } };
}
if (activityFilters.subCategories?.length > 0) {
filters["category"] = null;
filters["subCategory"] = activityFilters.subCategories.map(item => {
return { subCategory: { id: { $eq: item } } };
});
}
if (activityFilters.activityType) {
filters["activityType"] = activityFilters.activityType;
}
if (activityFilters.startDate) {
filters["fromDate"] = activityFilters.startDate;
}
if (activityFilters.endDate) {
filters["toDate"] = activityFilters.endDate;
}
if (activityFilters.minDuration > 0) {
filters["minimumDuration"] = activityFilters.minDuration;
}
if (activityFilters.maxDuration > 0) {
filters["maximumDuration"] = activityFilters.maxDuration;
}
if (activityFilters.minGroupSize > 0) {
filters["minGroupSize"] = activityFilters.minGroupSize;
}
if (activityFilters.maxGroupSize > 0) {
filters["maxGroupSize"] = activityFilters.maxGroupSize;
}
if (activityFilters.minAge > 0) {
filters["ageLowerLimit"] = activityFilters.minAge;
}
if (activityFilters.sorting) {
filters["sort"] = activityFilters.sorting;
}
// console.log("subcategory >>", filters);
dispatch(
getActivitiesByFilters({
subCategory: filters.subCategory,
category: filters.category,
activityType: filters.activityType,
fromDate: filters.fromDate,
toDate: filters.toDate,
minimumDuration: filters.minimumDuration,
maximumDuration: filters.maximumDuration,
minGroupSize: filters.minGroupSize,
maxGroupSize: filters.maxGroupSize,
ageLowerLimit: filters.ageLowerLimit,
sort: filters.sort
})
);
}, [activityFilters]);
return (
<>
<section className="listing-inner-session">
<div className="container-fluid">
<div className="row">
<div className="col-12">
<div className="filter-dd">
......@@ -53,26 +114,6 @@ const ListingInner = ({allActivitiesData}) => {
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/filter-view.svg" />
</span>
</a>
{/* <div className={`inner-content ${isGridViewOpen ? "open" : ""}`}>
<div className="top-head">
<div className="">View By</div>
<div className="close-btn" onClick={toggleGridViewDropdown}>
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/close-icon.svg" />
</span>
</div>
</div>
<ul className="list-by">
<li>
<input className="form-check-labe" type="radio" id="3 Grid View" name="gridView" />
<label htmlFor="3 Grid View">3 Grid View</label>
</li>
<li>
<input className="form-check-labe" type="radio" id="4 Grid View" name="gridView" />
<label htmlFor="4 Grid View">4 Grid View</label>
</li>
</ul>
</div> */}
</div>
<div className="grid-view box-inner">
<a onClick={toggleGridViewDropdown}>
......@@ -118,21 +159,41 @@ const ListingInner = ({allActivitiesData}) => {
</div>
<ul className="list-by">
<li>
<input className="form-check-labe" type="radio" id="Price - High to Low" name="sort" />
<input
className="form-check-labe"
onChange={e => {
dispatch(setActivityFilters({ filters: { ...activityFilters, sorting: e.target.value } }));
// console.log(e.target.value);
}}
type="radio"
id="Price - High to Low"
name="sort"
value={"descending"}
/>
<label htmlFor="Price - High to Low">Price - High to Low</label>
</li>
<li>
<input className="form-check-labe" type="radio" id="Price - Low to High" name="sort" />
<input
className="form-check-labe"
onChange={e => {
dispatch(setActivityFilters({ filters: { ...activityFilters, sorting: e.target.value } }));
// console.log(e.target.value);
}}
type="radio"
id="Price - Low to High"
name="sort"
value={"ascending"}
/>
<label htmlFor="Price - Low to High">Price - Low to High</label>
</li>
<li>
{/* <li>
<input className="form-check-labe" type="radio" id="Most Rated" name="sort" />
<label htmlFor="Most Rated">Most Rated</label>
</li>
<li>
<input className="form-check-labe" type="radio" id="Most Popular" name="sort" />
<label htmlFor="Most Popular">Most Popular</label>
</li>
</li> */}
</ul>
</div>
</div>
......
......@@ -2,10 +2,13 @@ import Image from "next/image";
import { useRouter } from "next/router";
import React from "react";
import { Button } from "react-bootstrap";
import { useSelector } from "react-redux";
import { cleanImage } from "../../services/imageHandling";
import WishlistComponent from "../detail/WIshlistComponent";
const ListingItems = ({ allActivitiesData }) => {
console.log("allActivitiesData", allActivitiesData);
const { endUser } = useSelector(state => state.endUser);
console.log("endUser", endUser);
const router = useRouter();
return (
<>
......@@ -33,11 +36,7 @@ const ListingItems = ({ allActivitiesData }) => {
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/star.svg" />
</span>
</div>
<div className="wishlist">
<span className="image-container">
<Image layout="fill" alt="" className="image img-fluid" src="/images/icons/wishlist.svg" />
</span>
</div>
{endUser && <WishlistComponent activityId={data.id} userId={endUser.id} />}
</div>
</div>
<div className="discription">
......
import Image from "next/image";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { setActivityFilters } from "../../redux/actions/activityAction";
const SubCategoryChips = ({ data }) => {
const dispatch = useDispatch();
const { activityFilters } = useSelector(sate => sate.activityFilters);
const [select, setselect] = useState(activityFilters.subCategories?.includes(data.id));
useEffect(() => {
setselect(activityFilters.subCategories?.includes(data.id));
}, [activityFilters]);
return (
<div>
<a
onClick={() => {
setselect(!select);
if (activityFilters.subCategories.length > 0) {
if (activityFilters.subCategories.includes(data.id)) {
let newArr = activityFilters.subCategories.filter(item => item != data.id);
dispatch(setActivityFilters({ filters: { ...activityFilters, subCategories: newArr } }));
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, subCategories: [...activityFilters.subCategories, data.id] } }));
}
} else {
dispatch(setActivityFilters({ filters: { ...activityFilters, subCategories: [data.id] } }));
}
}}
// key={index} onClick={() => handleToggleCloseIcon(index)}
>
<span>{data.attributes.name}</span>
{select && (
<span className="image-container">
<Image layout="fill" alt="image" className="image" src="/images/icons/close-button.svg" />
</span>
)}
</a>
</div>
);
};
export default SubCategoryChips;
......@@ -865,7 +865,7 @@ const ActivityDetails = ({ isUpdate }) => {
</div>
<div className="col-2 col-lg-4">
<label>Minimum duration</label>
<label>Maximum duration</label>
<input
value={values.maxDuration}
id="maxDuration"
......
import React from "react";
import React, { useEffect } from "react";
import { useDispatch } from "react-redux";
import Detail from "../../components/detail/Detail";
import Layout from "../../components/layout/Layout";
import { getActivitiesByFilters, getActivityById } from "../../redux/actions/activityAction";
import { loadUser } from "../../redux/actions/userActions";
import { wrapper } from "../../redux/store";
const ActivityDetailPage = () => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(loadUser());
}, []);
return (
<Layout>
<Detail />
......@@ -16,9 +23,8 @@ export default ActivityDetailPage;
/** For server side rendering */
export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, query }) => {
await store.dispatch(getActivityById(query.id))
// await store.dispatch(getActivitiesByFilters({category: query.category}))
await store.dispatch(getActivityById(query.id));
// await store.dispatch(getActivitiesByFilters({category: query.category}))
return {
props: {}
......
import Layout from "../components/layout/Layout";
import Listing from "../components/listing/Listing";
import { getActivitiesByFilters } from "../redux/actions/activityAction";
import { getAllCategories, getAllSubCategories, getSubCategoriesByCategoryId } from "../redux/actions/categoriesAction";
import { wrapper } from "../redux/store";
export default function ListingPage() {
......@@ -23,19 +24,21 @@ export default function ListingPage() {
/** For server side rendering */
export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, query }) => {
try {
await store.dispatch(getActivitiesByFilters({}))
await store.dispatch(getActivitiesByFilters({}));
await store.dispatch(getAllCategories());
await store.dispatch(getSubCategoriesByCategoryId());
return {
props: {},
// Next.js will attempt to re-generate the page:
// - Any requests to the page after the initial request and before 10 seconds are also cached and instantaneous.
// - After the 10-second window, the next request will still show the cached (stale) page
// - Next.js triggers a regeneration of the page in the background.
// - Once the page generates successfully, Next.js will invalidate the cache and show the updated page. If the background regeneration fails, the old page would still be unaltered.
// In seconds
// revalidate: Number(process.env.NEXT_PUBLIC_ISR_REVALIDATE_AFTER)
};
} catch (error) {
console.log("index.js", error);
}
return {
props: {}
// Next.js will attempt to re-generate the page:
// - Any requests to the page after the initial request and before 10 seconds are also cached and instantaneous.
// - After the 10-second window, the next request will still show the cached (stale) page
// - Next.js triggers a regeneration of the page in the background.
// - Once the page generates successfully, Next.js will invalidate the cache and show the updated page. If the background regeneration fails, the old page would still be unaltered.
// In seconds
// revalidate: Number(process.env.NEXT_PUBLIC_ISR_REVALIDATE_AFTER)
};
} catch (error) {
console.log("index.js", error);
}
});
import axios from "axios";
import { getSession } from "next-auth/react";
import {
ACTIVITY_FILTERS_CONSTANT,
CREATE_ACTIVITY_FAIL,
CREATE_ACTIVITY_REQUEST,
CREATE_ACTIVITY_SUCCESS,
......@@ -10,6 +11,9 @@ import {
GET_ACTIVITY_BY_ID_FAIL,
GET_ACTIVITY_BY_ID_REQUEST,
GET_ACTIVITY_BY_ID_SUCCESS,
GET_WISHLISTS_FAIL,
GET_WISHLISTS_REQUEST,
GET_WISHLISTS_SUCCESS,
UPDATE_ACTIVITY_BY_ID_FAIL,
UPDATE_ACTIVITY_BY_ID_REQUEST,
UPDATE_ACTIVITY_BY_ID_SUCCESS
......@@ -315,8 +319,9 @@ export const getActivitiesForEndUser = () => async dispatch => {
};
export const getActivitiesByFilters =
({ category, subCategory, price, ageLimit, duration, fromDate, toDate, minGroupSize, maxGroupSize, minDuration, maxDuration, activityType }) =>
({ category, subCategory, price, ageLowerLimit, duration, fromDate, toDate, minGroupSize, maxGroupSize, minimumDuration, maximumDuration, activityType, sort }) =>
async dispatch => {
let sortFilter = [];
try {
dispatch({
type: GET_ACTIVITIES_REQUEST,
......@@ -328,24 +333,72 @@ export const getActivitiesByFilters =
"Content-Type": "application/json"
}
};
if (sort == "descending") {
sortFilter = ["pricePerPerson:desc"];
} else {
sortFilter = ["pricePerPerson:asc"];
}
let query = {
filters: {
approved: { $eq: true }
// fromDate: { $gte: fromDate },
// toDate: { $lte: toDate },
// $and: [{ fromDate: { $gte: "2024-05-05" } }, { toDate: { $lte: toDate } }]
// $or: subCategory
},
populate: ["masterMonths", "subCategory", "subCategory.category", "timeSlots", "masterPincode", "vendor", "image", "category"]
// sort: ["pricePerPerson:asc"]
};
console.log("query:", category);
if (category) {
query.filters["category"] = { id: { $eq: category } };
query.filters["category"] = category;
}
if (subCategory) {
query.filters["$or"] = subCategory;
}
if (activityType) {
query.filters["activityType"] = activityType;
}
if (fromDate && toDate) {
query.filters["$and"] = [{ fromDate: { $gte: fromDate } }, { toDate: { $lte: toDate } }];
delete query.filters.fromDate;
delete query.filters.toDate;
}
if (!(fromDate && toDate)) {
if (fromDate) {
query.filters["fromDate"] = { $gte: fromDate };
}
if (toDate) {
query.filters["toDate"] = { $lte: toDate };
}
}
if (maximumDuration) {
query.filters["maximumDuration"] = { $lte: maximumDuration };
}
if (minimumDuration) {
query.filters["minimumDuration"] = { $gte: minimumDuration };
}
if (minGroupSize) {
query.filters["minGroupSize"] = { $gte: minGroupSize };
}
if (maxGroupSize) {
query.filters["maxGroupSize"] = { $lte: maxGroupSize };
}
if (ageLowerLimit) {
query.filters["ageLowerLimit"] = { $gte: ageLowerLimit };
}
if (sort) {
query["sort"] = sortFilter;
}
// console.log("subcategoryquery:", query);
const queryString = qs.stringify(query, {
encodeValuesOnly: true
});
const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/experiences?${queryString}`, config);
// console.log("activity res", response);
dispatch({
type: GET_ACTIVITIES_SUCCESS,
payload: response.data
......@@ -359,3 +412,135 @@ export const getActivitiesByFilters =
});
}
};
export const setActivityFilters =
({ filters }) =>
async dispatch => {
dispatch({
type: ACTIVITY_FILTERS_CONSTANT,
payload: filters
});
};
export const getWishlists =
({ endUser }) =>
async dispatch => {
try {
const session = await getSession();
if (!session) {
return;
}
dispatch({
type: GET_WISHLISTS_REQUEST
});
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${session.jwt}`
}
};
const query = {
filters: {
endUser: {
id: {
$eq: endUser
}
}
},
populate: ["endUser", "experience"]
};
const queryString = qs.stringify(query, {
encodeValuesOnly: true
});
const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/wishlists?${queryString}`, config);
dispatch({
type: GET_WISHLISTS_SUCCESS,
payload: response.data.data
});
return response.data.data;
} catch (error) {
dispatch({
type: GET_WISHLISTS_FAIL,
payload: error.response.data
});
}
};
export const toggleWishlist = async ({ activityId, userId }) => {
try {
const session = await getSession();
if (!session) {
return;
}
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${session.jwt}`
}
};
const data = {
experience: activityId,
endUser: userId
};
// console.log("data", data);
const response = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/wishlists`, { data }, config);
// console.log("response.data.data", response.data);
return response.data.data;
} catch (error) {}
};
export const checkWishlist = async ({ activityId, userId }) => {
try {
const session = await getSession();
if (!session) {
return;
}
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${session.jwt}`
}
};
const data = {
experience: activityId,
endUser: userId
};
const query = {
filters: {
$and: [{ experience: { id: { $eq: activityId } } }, { endUser: { id: { $eq: userId } } }]
},
populate: ["experience", "endUser"]
};
const queryString = qs.stringify(query, {
encodeValuesOnly: true
});
// console.log("data", data);
const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/wishlists?${queryString}`, config);
console.log("response.data.data", response.data);
return response.data.data;
} catch (error) {}
};
export const deleteWishlist = async ({ wishlistId }) => {
try {
const session = await getSession();
if (!session) {
return;
}
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${session.jwt}`
}
};
const res = await axios.delete(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/wishlists/${wishlistId}`, config);
return res.data;
} catch (error) {}
};
......@@ -91,3 +91,52 @@ export const getAllSubCategories = categoryName => async dispatch => {
});
}
};
export const getSubCategoriesByCategoryId = categoryId => async dispatch => {
try {
dispatch({
type: GET_SUB_CATEGORIES_REQUEST,
loading: true
});
const config = {
headers: {
"Content-Type": "application/json"
}
};
let query = {
filters: {
category: {
id: {}
}
},
populate: ["category"]
};
if (categoryId) {
// console.log("here 1", query.filters.category);
query.filters.category.id = { $eq: categoryId };
}
// console.log(">>>", query);
const queryString = qs.stringify(query, {
encodeValuesOnly: true
});
const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/sub-categories/?${queryString}`, config);
dispatch({
type: GET_SUB_CATEGORIES_SUCCESS,
payload: response.data,
loading: false
});
return response.data;
} catch (error) {
dispatch({
type: GET_SUB_CATEGORIES_FAIL,
payload: error.response.data
});
}
};
......@@ -14,8 +14,10 @@ export const UPDATE_ACTIVITY_BY_ID_REQUEST = "UPDATE_ACTIVITY_BY_ID_REQUEST"
export const UPDATE_ACTIVITY_BY_ID_SUCCESS = "UPDATE_ACTIVITY_BY_ID_SUCCESS"
export const UPDATE_ACTIVITY_BY_ID_FAIL = "UPDATE_ACTIVITY_BY_ID_FAIL"
// export const GET_ACTIVITY_BY_ID_REQUEST = "GET_ACTIVITY_BY_ID_REQUEST"
// export const GET_ACTIVITY_BY_ID_SUCCESS = "GET_ACTIVITY_BY_ID_SUCCESS"
// export const GET_ACTIVITY_BY_ID_FAIL = "GET_ACTIVITY_BY_ID_FAIL"
export const GET_WISHLISTS_REQUEST = "GET_WISHLISTS_REQUEST"
export const GET_WISHLISTS_SUCCESS = "GET_WISHLISTS_SUCCESS"
export const GET_WISHLISTS_FAIL = "GET_WISHLISTS_FAIL"
export const ACTIVITY_FILTERS_CONSTANT = "ACTIVITY_FILTERS_CONSTANT"
export const CLEAR_ERRORS = "CLEAR_ERRORS";
\ No newline at end of file
import {
ACTIVITY_FILTERS_CONSTANT,
CREATE_ACTIVITY_FAIL,
CREATE_ACTIVITY_REQUEST,
CREATE_ACTIVITY_SUCCESS,
......@@ -8,6 +9,9 @@ import {
GET_ACTIVITY_BY_ID_FAIL,
GET_ACTIVITY_BY_ID_REQUEST,
GET_ACTIVITY_BY_ID_SUCCESS,
GET_WISHLISTS_FAIL,
GET_WISHLISTS_REQUEST,
GET_WISHLISTS_SUCCESS,
UPDATE_ACTIVITY_BY_ID_FAIL,
UPDATE_ACTIVITY_BY_ID_REQUEST,
UPDATE_ACTIVITY_BY_ID_SUCCESS
......@@ -123,3 +127,43 @@ export const updateActivityByIdReducer = (state = {}, action) => {
return state;
}
};
export const setActivityFilterReducer = (state = { activityFilters: {} }, action) => {
switch (action.type) {
case ACTIVITY_FILTERS_CONSTANT:
return {
activityFilters: action.payload
};
default:
return state;
}
};
export const getWishlistsReducer = (state = {}, action) => {
switch (action.type) {
case GET_WISHLISTS_REQUEST:
return { loading: true };
case GET_WISHLISTS_SUCCESS:
return {
loading: false,
wishlists: action.payload
};
case GET_WISHLISTS_FAIL:
return {
loading: false,
error: action.payload.error.message
};
case CLEAR_ERRORS:
return {
...state,
error: null
};
default:
return state;
}
};
......@@ -5,7 +5,7 @@ import { authReducer, forgotPasswordReducer, getEndUserReducer, loadedUserReduce
import { enquiryReducer, getEnquiriesReducer } from "./enquiryReducer";
import { displayEnquireNowReducer } from "./enquireNowModalReducer";
import { getAllVendorsReducer, getVendorDetailsReducer, loggedInVendorReducer, updateVendorReducer } from "./vendorReducers";
import { createActivityReducer, getActivitiesReducer, getActivityByIdReducer, updateActivityByIdReducer } from "./activitiesReducer";
import { createActivityReducer, getActivitiesReducer, getActivityByIdReducer, getWishlistsReducer, setActivityFilterReducer, updateActivityByIdReducer } from "./activitiesReducer";
import { getAllCategoriesReducer, getAllSubCategoriesReducer } from "./categoryReducer";
import { getAllTestimonialReducer } from "./testimonialReducer";
import { blogReducer, blogsReducer } from "./blogReducer";
......@@ -40,6 +40,8 @@ const reducers = combineReducers({
allVendors: getAllVendorsReducer,
endUser: getEndUserReducer,
enquiriesByVendor: getEnquiriesReducer,
activityFilters: setActivityFilterReducer,
wishlists: getWishlistsReducer,
});
export default reducers;
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!