added swiper to explore and singular offers, and capability to remove offers
This commit is contained in:
Generated
+59
@@ -19,6 +19,7 @@
|
||||
"react-router-dom": "^6.4.3",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-toastify": "^9.1.1",
|
||||
"swiper": "^8.4.5",
|
||||
"uuid": "^9.0.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
}
|
||||
@@ -7265,6 +7266,14 @@
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dom7": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/dom7/-/dom7-4.0.4.tgz",
|
||||
"integrity": "sha512-DSSgBzQ4rJWQp1u6o+3FVwMNnT5bzQbMb+o31TjYYeRi05uAcpF8koxdfzeoe5ElzPmua7W7N28YJhF7iEKqIw==",
|
||||
"dependencies": {
|
||||
"ssr-window": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
@@ -16048,6 +16057,11 @@
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||
},
|
||||
"node_modules/ssr-window": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz",
|
||||
"integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="
|
||||
},
|
||||
"node_modules/stable": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
|
||||
@@ -16411,6 +16425,29 @@
|
||||
"boolbase": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/swiper": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/swiper/-/swiper-8.4.5.tgz",
|
||||
"integrity": "sha512-zveyEFBBv4q1sVkbJHnuH4xCtarKieavJ4SxP0QEHvdpPLJRuD7j/Xg38IVVLbp7Db6qrPsLUePvxohYx39Agw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/swiperjs"
|
||||
},
|
||||
{
|
||||
"type": "open_collective",
|
||||
"url": "http://opencollective.com/swiper"
|
||||
}
|
||||
],
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"dom7": "^4.0.4",
|
||||
"ssr-window": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
@@ -23184,6 +23221,14 @@
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"dom7": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/dom7/-/dom7-4.0.4.tgz",
|
||||
"integrity": "sha512-DSSgBzQ4rJWQp1u6o+3FVwMNnT5bzQbMb+o31TjYYeRi05uAcpF8koxdfzeoe5ElzPmua7W7N28YJhF7iEKqIw==",
|
||||
"requires": {
|
||||
"ssr-window": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
@@ -29383,6 +29428,11 @@
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||
},
|
||||
"ssr-window": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz",
|
||||
"integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="
|
||||
},
|
||||
"stable": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
|
||||
@@ -29661,6 +29711,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"swiper": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/swiper/-/swiper-8.4.5.tgz",
|
||||
"integrity": "sha512-zveyEFBBv4q1sVkbJHnuH4xCtarKieavJ4SxP0QEHvdpPLJRuD7j/Xg38IVVLbp7Db6qrPsLUePvxohYx39Agw==",
|
||||
"requires": {
|
||||
"dom7": "^4.0.4",
|
||||
"ssr-window": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"react-router-dom": "^6.4.3",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-toastify": "^9.1.1",
|
||||
"swiper": "^8.4.5",
|
||||
"uuid": "^9.0.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { getDocs, query, orderBy, limit, collection } from "firebase/firestore";
|
||||
import { db } from "../firebase.config";
|
||||
import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from "swiper";
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import "swiper/swiper-bundle.css";
|
||||
import Spinner from "./Spinner";
|
||||
|
||||
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y]);
|
||||
|
||||
function Slider() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [listings, setListings] = useState(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchListings = async () => {
|
||||
const listingsRef = collection(db, "listings");
|
||||
const q = query(listingsRef, orderBy("timestamp", "desc"), limit(5));
|
||||
const querySnap = await getDocs(q);
|
||||
|
||||
let listings = [];
|
||||
|
||||
querySnap.forEach((doc) => {
|
||||
return listings.push({
|
||||
id: doc.id,
|
||||
data: doc.data(),
|
||||
});
|
||||
});
|
||||
|
||||
setListings(listings);
|
||||
setLoading(false);
|
||||
};
|
||||
fetchListings();
|
||||
}, []);
|
||||
if (loading) return <Spinner />;
|
||||
console.log(listings[0].data.imgUrls);
|
||||
return (
|
||||
listings && (
|
||||
<>
|
||||
<p className="exploreHeading">Recommended</p>
|
||||
<Swiper slidesPerView={1} pagination={{ clickable: true }}>
|
||||
{listings.map(({ data, id }) => (
|
||||
<SwiperSlide
|
||||
key={id}
|
||||
onClick={() => navigate(`/category/${data.type}/${id}`)}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
background: `url(${data.imgUrls[0]}) center no-repeat`,
|
||||
backgroundSize: "cover",
|
||||
minHeight: "20rem",
|
||||
}}
|
||||
className="swiperSlideDiv"
|
||||
>
|
||||
<p className="swiperSlideText">{data.name}</p>
|
||||
<p className="swiperSlidePrice">
|
||||
${data.discountedPrice ?? data.regularPrice}{" "}
|
||||
{data.type === "rent" && "/ month"}
|
||||
</p>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
export default Slider;
|
||||
@@ -12,8 +12,6 @@ import {
|
||||
import { db } from "../firebase.config";
|
||||
import { toast } from "react-toastify";
|
||||
import Spinner from "../components/Spinner";
|
||||
import { async } from "@firebase/util";
|
||||
import Listing from "../components/ListingItem";
|
||||
import ListingItem from "../components/ListingItem";
|
||||
|
||||
function Category() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Slider from '../components/Slider';
|
||||
import {Link} from 'react-router-dom'
|
||||
import rentCategoryImage from '../assets/jpg/rentCategoryImage.jpg'
|
||||
import sellCategoryImage from '../assets/jpg/sellCategoryImage.jpg'
|
||||
@@ -7,8 +8,9 @@ function Explore (){
|
||||
<header>
|
||||
<p className='pageHeader'>Explore</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
{/*Slider*/}
|
||||
<Slider/>
|
||||
<p className='exploreCategoryHeading'>Categories</p>
|
||||
<div className='exploreCategories'>
|
||||
<Link to='/category/rent'>
|
||||
|
||||
+19
-1
@@ -1,3 +1,6 @@
|
||||
import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from "swiper";
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import "swiper/swiper-bundle.css";
|
||||
import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||
@@ -7,6 +10,8 @@ import { db } from "../firebase.config";
|
||||
import Spinner from "../components/Spinner";
|
||||
import shareIcon from "../assets/svg/shareIcon.svg";
|
||||
|
||||
SwiperCore.use([Navigation, Pagination,Scrollbar,A11y])
|
||||
|
||||
function Listing() {
|
||||
const [listing, setListing] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -33,7 +38,20 @@ function Listing() {
|
||||
if (loading) return <Spinner />;
|
||||
return (
|
||||
<main>
|
||||
{/*Slider*/}
|
||||
<Swiper slidesPerView={1} pagination={{ clickable: true }}>
|
||||
{listing.imgUrls.map((url, index) => (
|
||||
<SwiperSlide key={index}>
|
||||
<div
|
||||
className="swiperSlideDiv"
|
||||
style={{
|
||||
background: `url(${listing.imgUrls[index]}) center no-repeat`,
|
||||
backgroundSize: "cover",
|
||||
minHeight:'20rem'
|
||||
}}
|
||||
></div>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
<div
|
||||
className="shareIconDiv"
|
||||
onClick={() => {
|
||||
|
||||
+61
-1
@@ -1,3 +1,4 @@
|
||||
import ListingItem from "../components/ListingItem";
|
||||
import arrowRight from "../assets/svg/keyboardArrowRightIcon.svg";
|
||||
import homeIcon from "../assets/svg/homeIcon.svg";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -5,17 +6,49 @@ import { useEffect, useState } from "react";
|
||||
import { getAuth, updateProfile } from "firebase/auth";
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import { db } from "../firebase.config";
|
||||
import { updateDoc, doc } from "firebase/firestore";
|
||||
import {
|
||||
updateDoc,
|
||||
doc,
|
||||
collection,
|
||||
getDocs,
|
||||
query,
|
||||
where,
|
||||
orderBy,
|
||||
deleteDoc,
|
||||
} from "firebase/firestore";
|
||||
|
||||
function Profile() {
|
||||
const [changeDetails, setChangeDetails] = useState(false);
|
||||
const auth = getAuth();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [listings, setListings] = useState(null);
|
||||
const [formData, setFormData] = useState({
|
||||
name: auth.currentUser.displayName,
|
||||
email: auth.currentUser.email,
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { name, email } = formData;
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUserListingts = async () => {
|
||||
const listingsRef = collection(db, "listings");
|
||||
const q = query(
|
||||
listingsRef,
|
||||
where("userRef", "==", auth.currentUser.uid),
|
||||
orderBy("timestamp", "desc")
|
||||
);
|
||||
const querySnap = await getDocs(q);
|
||||
const listings = [];
|
||||
querySnap.forEach((doc) => {
|
||||
return listings.push({ id: doc.id, data: doc.data() });
|
||||
});
|
||||
setListings(listings);
|
||||
setLoading(false);
|
||||
};
|
||||
fetchUserListingts();
|
||||
}, [auth.currentUser.uid]);
|
||||
|
||||
const onLogout = () => {
|
||||
auth.signOut();
|
||||
navigate("/");
|
||||
@@ -36,12 +69,24 @@ function Profile() {
|
||||
toast.error("could no update profile details");
|
||||
}
|
||||
};
|
||||
|
||||
const onChange = (e) => {
|
||||
setFormData((prevState) => ({
|
||||
...prevState,
|
||||
[e.target.id]: e.target.value,
|
||||
}));
|
||||
};
|
||||
|
||||
const onDelete = async (listingId) => {
|
||||
if (window.confirm("Are you sure you want to delte?")) {
|
||||
await deleteDoc(doc(db, "listings", listingId));
|
||||
const updatedListings = listings.filter(
|
||||
(listing) => listing.id !== listingId
|
||||
);
|
||||
setListings(updatedListings);
|
||||
toast.success("Successfully deleted listing ");
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="profile">
|
||||
<header className="profileHeader">
|
||||
@@ -88,6 +133,21 @@ function Profile() {
|
||||
<p>Sell or rent your home</p>
|
||||
<img src={arrowRight} alt="arrowRight" />
|
||||
</Link>
|
||||
{!loading && listings?.length > 0 && (
|
||||
<>
|
||||
<p className="listingText">Your Listings</p>
|
||||
<ul className="listingsList">
|
||||
{listings.map((listing) => (
|
||||
<ListingItem
|
||||
key={listing.id}
|
||||
listing={listing.data}
|
||||
id={listing.id}
|
||||
onDelete={() => onDelete(listing.id)}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user