From 7841afe8defadd97219785fbd7b130a98f1c5fdb Mon Sep 17 00:00:00 2001 From: QkoSad Date: Sat, 3 Dec 2022 17:46:43 +0200 Subject: [PATCH] added swiper to explore and singular offers, and capability to remove offers --- package-lock.json | 59 +++++++++++++++++++++++++++++++++ package.json | 1 + src/components/Slider.jsx | 70 +++++++++++++++++++++++++++++++++++++++ src/pages/Category.jsx | 2 -- src/pages/Explore.jsx | 4 ++- src/pages/Listing.jsx | 20 ++++++++++- src/pages/Profile.jsx | 62 +++++++++++++++++++++++++++++++++- 7 files changed, 213 insertions(+), 5 deletions(-) create mode 100644 src/components/Slider.jsx diff --git a/package-lock.json b/package-lock.json index 39e7cd8..3c4397c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index a94eb92..68dae96 100644 --- a/package.json +++ b/package.json @@ -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" }, diff --git a/src/components/Slider.jsx b/src/components/Slider.jsx new file mode 100644 index 0000000..9e70ea8 --- /dev/null +++ b/src/components/Slider.jsx @@ -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 ; + console.log(listings[0].data.imgUrls); + return ( + listings && ( + <> +

Recommended

+ + {listings.map(({ data, id }) => ( + navigate(`/category/${data.type}/${id}`)} + > +
+

{data.name}

+

+ ${data.discountedPrice ?? data.regularPrice}{" "} + {data.type === "rent" && "/ month"} +

+
+
+ ))} +
+ + ) + ); +} +export default Slider; diff --git a/src/pages/Category.jsx b/src/pages/Category.jsx index 3e27fae..2fbe760 100644 --- a/src/pages/Category.jsx +++ b/src/pages/Category.jsx @@ -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() { diff --git a/src/pages/Explore.jsx b/src/pages/Explore.jsx index 4bc67aa..3768625 100644 --- a/src/pages/Explore.jsx +++ b/src/pages/Explore.jsx @@ -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 (){

Explore

+
- {/*Slider*/} +

Categories

diff --git a/src/pages/Listing.jsx b/src/pages/Listing.jsx index 0f5ff89..e63c8b7 100644 --- a/src/pages/Listing.jsx +++ b/src/pages/Listing.jsx @@ -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 ; return (
- {/*Slider*/} + + {listing.imgUrls.map((url, index) => ( + +
+
+ ))} +
{ diff --git a/src/pages/Profile.jsx b/src/pages/Profile.jsx index 695b44f..ce24b95 100644 --- a/src/pages/Profile.jsx +++ b/src/pages/Profile.jsx @@ -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 (
@@ -88,6 +133,21 @@ function Profile() {

Sell or rent your home

arrowRight + {!loading && listings?.length > 0 && ( + <> +

Your Listings

+
    + {listings.map((listing) => ( + onDelete(listing.id)} + /> + ))} +
+ + )}
);