added map to listings

This commit is contained in:
QkoSad
2022-12-02 22:21:43 +02:00
parent d79737a497
commit 09b6b0ad86
7 changed files with 270 additions and 44 deletions
+7
View File
@@ -11,6 +11,8 @@ import Signin from "./pages/Signin";
import Signup from "./pages/Signup";
import Category from "./pages/Category";
import CreateLising from "./pages/CreateListing";
import Listing from "./pages/Listing";
import Contact from "./pages/Contact";
function App() {
return (
@@ -28,6 +30,11 @@ function App() {
<Route path="/sign-up" element={<Signup />} />
<Route path="/forgot-password" element={<ForgotPassword />} />
<Route path="/create-listing" element={<CreateLising />} />
<Route
path="/category/:categoryName/:listingId"
element={<Listing />}
/>
<Route path="/contact/:landlordId" element={<Contact />}/>
</Routes>
<Navbar />
</Router>
+67
View File
@@ -0,0 +1,67 @@
import { useState, useEffect } from "react";
import { useParams, useSearchParams } from "react-router-dom";
import { doc, getDoc } from "firebase/firestore";
import { db } from "../firebase.config";
import { toast } from "react-toastify";
function Contact() {
const [message, setMassage] = useState("");
const [landlord, setLandlord] = useState(null);
const [searchParams, setSearchParams] = useSearchParams();
const params = useParams();
useEffect(() => {
const getLandlord = async () => {
const docRef = doc(db, "users", params.landlordId);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
setLandlord(docSnap.data());
} else {
toast.error("Landlord does not exist");
}
};
getLandlord();
}, [params.landlordId]);
const onChange = (e) => setMassage(e.target.value);
return (
<div className="pageContainer">
<header>
<p className="pageHeader">Contact Landlord</p>
</header>
{landlord !== null && (
<main>
<div className="contactLandlord">
<p className="landlordName">Contact {landlord?.name}</p>
</div>
<form className="messageForm">
<div className="messageDiv">
<label htmlFor="message" className="messageLable">
Message
</label>
<textarea
onChange={onChange}
name="message"
id="message"
className="textarea"
value={message}
/>
</div>
<a
href={`mailto:${landlord.email}?Subject=${searchParams.get(
"listingName"
)}&body=${message}`}
>
<button className="primaryButton" type="button">
Send Message
</button>
</a>
</form>
</main>
)}
</div>
);
}
export default Contact;
+120
View File
@@ -0,0 +1,120 @@
import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";
import { useState, useEffect } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import { getDoc, doc } from "firebase/firestore";
import { getAuth } from "firebase/auth";
import { db } from "../firebase.config";
import Spinner from "../components/Spinner";
import shareIcon from "../assets/svg/shareIcon.svg";
function Listing() {
const [listing, setListing] = useState(null);
const [loading, setLoading] = useState(true);
const [shareLinkCopied, setShareLinkCopied] = useState(false);
const navigate = useNavigate();
const params = useParams();
const auth = getAuth();
useEffect(() => {
const fetchListings = async () => {
const docRef = doc(db, "listings", params.listingId);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
setListing(docSnap.data());
setLoading(false);
}
};
fetchListings();
}, [navigate, params.listingId]);
if (loading) return <Spinner />;
return (
<main>
{/*Slider*/}
<div
className="shareIconDiv"
onClick={() => {
navigator.clipboard.writeText(window.location.href);
setShareLinkCopied(true);
setTimeout(() => {
setShareLinkCopied(false);
}, 2000);
}}
>
<img src={shareIcon} alt="" />
</div>
{shareLinkCopied && <p className="linkCopied">Link Copied!</p>}
<div className="listingDetails">
<p className="listingName">
{listing.name} -{" "}
{listing.offer
? listing.discountedPrice
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
: listing.regularPrice
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ",")}
</p>
<p className="listingLocation">{listing.location}</p>
<p className="listingType">
For {listing.type === "rent" ? "Rent" : "Sale"}
</p>
{listing.offer && (
<p className="discountPrice">
${listing.regularPrice - listing.discountedPrice} discount
</p>
)}
<ul className="listingDetailsList">
<li>
{listing.bedrooms > 1
? `${listing.bedrooms} Bedrooms`
: "1 Bedroom"}
</li>
<li>
{listing.bathrooms > 1
? `${listing.bathrooms} Bathrooms`
: "1 Bathroom"}
</li>
<li>{listing.parking && "Parking Spot"}</li>
<li>{listing.furnished && "Furnished"}</li>
</ul>
<p className="listingLocationTitle">Location</p>
<div className="leafletContainer">
<MapContainer
style={{ height: "100%", width: "100%" }}
center={[listing.geolocation.lat, listing.geolocation.lng]}
zoom={13}
scrollWheelZoom={false}
>
<TileLayer
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png"
/>
<Marker
position={[listing.geolocation.lat, listing.geolocation.lng]}
>
<Popup>{listing.location}</Popup>
</Marker>
</MapContainer>
</div>
{auth.currentUser?.uid !== listing.userRef && (
<Link
to={`/contact/${listing.userRef}?listingName=${listing.name}`}
className="primaryButton"
>
Contact Landlord
</Link>
)}
</div>
</main>
);
}
export default Listing;
+21 -22
View File
@@ -1,11 +1,11 @@
import arrowRight from '../assets/svg/keyboardArrowRightIcon.svg'
import homeIcon from '../assets/svg/homeIcon.svg'
import arrowRight from "../assets/svg/keyboardArrowRightIcon.svg";
import homeIcon from "../assets/svg/homeIcon.svg";
import { toast } from "react-toastify";
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 } from "firebase/firestore";
function Profile() {
const [changeDetails, setChangeDetails] = useState(false);
@@ -27,13 +27,13 @@ function Profile() {
await updateProfile(auth.currentUser, {
displayName: name,
});
const userRef = doc(db,'users',auth.currentUser.uid)
await updateDoc(userRef,{
name
})
const userRef = doc(db, "users", auth.currentUser.uid);
await updateDoc(userRef, {
name,
});
}
} catch (error) {
toast.error('could no update profile details')
toast.error("could no update profile details");
}
};
const onChange = (e) => {
@@ -46,22 +46,21 @@ function Profile() {
<div className="profile">
<header className="profileHeader">
<p className="pageHeader">My Profile</p>
<button type="button" className="logOut" onclick={onLogout}>
<button type="button" className="logOut" onClick={onLogout}>
Logout
</button>
</header>
<main>
<div className="profileDetailsHeader">
<p className="profileDetailsText">
<p
className="changePersonalDetails"
onClick={() => {
changeDetails && onSubmit();
setChangeDetails((prevState) => !prevState);
}}
>
{changeDetails ? "done" : "change"}
</p>
<p className="profileDetailsText">Personal Details</p>
<p
className="changePersonalDetails"
onClick={() => {
changeDetails && onSubmit();
setChangeDetails((prevState) => !prevState);
}}
>
{changeDetails ? "done" : "change"}
</p>
</div>
<div className="profileCard">
@@ -84,10 +83,10 @@ function Profile() {
/>
</form>
</div>
<Link to='/create-listing' className='createListing'>
<img src={homeIcon} alt='home'/>
<Link to="/create-listing" className="createListing">
<img src={homeIcon} alt="home" />
<p>Sell or rent your home</p>
<img src={arrowRight} alt='arrowRight'/>
<img src={arrowRight} alt="arrowRight" />
</Link>
</main>
</div>