added swiper to explore and singular offers, and capability to remove offers

This commit is contained in:
QkoSad
2022-12-03 17:46:43 +02:00
parent 09b6b0ad86
commit 7841afe8de
7 changed files with 213 additions and 5 deletions
+59
View File
@@ -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",
+1
View File
@@ -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"
},
+70
View File
@@ -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;
-2
View File
@@ -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() {
+3 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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>
);