add listings added
This commit is contained in:
@@ -9,6 +9,8 @@ import ForgotPassword from "./pages/ForgotPassword";
|
|||||||
import Offers from "./pages/Offers";
|
import Offers from "./pages/Offers";
|
||||||
import Signin from "./pages/Signin";
|
import Signin from "./pages/Signin";
|
||||||
import Signup from "./pages/Signup";
|
import Signup from "./pages/Signup";
|
||||||
|
import Category from "./pages/Category";
|
||||||
|
import CreateLising from "./pages/CreateListing";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
@@ -17,12 +19,15 @@ function App() {
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Explore />} />
|
<Route path="/" element={<Explore />} />
|
||||||
<Route path="/offers" element={<Offers />} />
|
<Route path="/offers" element={<Offers />} />
|
||||||
|
<Route path="/category/:categoryName" element={<Category />} />
|
||||||
|
|
||||||
<Route path="/profile" element={<PrivateRoute />}>
|
<Route path="/profile" element={<PrivateRoute />}>
|
||||||
<Route path="/profile" element={<Profile />} />
|
<Route path="/profile" element={<Profile />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/sign-in" element={<Signin />} />
|
<Route path="/sign-in" element={<Signin />} />
|
||||||
<Route path="/sign-up" element={<Signup />} />
|
<Route path="/sign-up" element={<Signup />} />
|
||||||
<Route path="/forgot-password" element={<ForgotPassword />} />
|
<Route path="/forgot-password" element={<ForgotPassword />} />
|
||||||
|
<Route path="/create-listing" element={<CreateLising />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
</Router>
|
</Router>
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { ReactComponent as DeleteIcon } from "../assets/svg/deleteIcon.svg";
|
||||||
|
import bedIcon from "../assets/svg/bedIcon.svg";
|
||||||
|
import bathtubIcon from "../assets/svg/bathtubIcon.svg";
|
||||||
|
|
||||||
|
function ListingItem({ listing, id, onDelete }) {
|
||||||
|
return (
|
||||||
|
<li className="categoryListing">
|
||||||
|
<Link
|
||||||
|
to={`/category/${listing.type}/${id}`}
|
||||||
|
className="categoryListingLink"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={listing.imgUrls[0]}
|
||||||
|
alt={listing.name}
|
||||||
|
className="categoryListingImg"
|
||||||
|
/>
|
||||||
|
<div className="categoryListingDetails">
|
||||||
|
<p className="categoryListingLocation">{listing.location}</p>
|
||||||
|
<p className="categoryListingName">{listing.name}</p>
|
||||||
|
<p className="categoryListingPrice">
|
||||||
|
$
|
||||||
|
{listing.offer
|
||||||
|
? listing.discountedPrice
|
||||||
|
.toString()
|
||||||
|
.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
|
||||||
|
: listing.regularPrice
|
||||||
|
.toString()
|
||||||
|
.replace(/\B(?=(\d{3})+(?!\d))/g, ",")}
|
||||||
|
{listing.type === "rent" && " / Month"}
|
||||||
|
</p>
|
||||||
|
<div className="categoryListingInfoDiv">
|
||||||
|
<img src={bedIcon} alt="bed" />
|
||||||
|
<p className="categoryListingInfoText">
|
||||||
|
{listing.bedrooms > 1
|
||||||
|
? `${listing.bedrooms} Bedrooms`
|
||||||
|
: "1 Bedrooms"}
|
||||||
|
</p>
|
||||||
|
<img src={bathtubIcon} alt="bath" />
|
||||||
|
<p className="categoryListingInfoText">
|
||||||
|
{listing.bathrooms > 1
|
||||||
|
? `${listing.bathrooms} Bedrooms`
|
||||||
|
: "1 Bathrooms"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
{onDelete && (
|
||||||
|
<DeleteIcon
|
||||||
|
className="removeIcon"
|
||||||
|
fill="rgb(231,76,60)"
|
||||||
|
onClick={() => onDelete(listing.id, listing.name)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default ListingItem;
|
||||||
@@ -16,7 +16,7 @@ function Navbar() {
|
|||||||
<footer className="navbar">
|
<footer className="navbar">
|
||||||
<nav className="navbarNan">
|
<nav className="navbarNan">
|
||||||
<ul className="navbarListItems">
|
<ul className="navbarListItems">
|
||||||
<li className="navbarListItems" onClick={() => navigate("/explore")}>
|
<li className="navbarListItems" onClick={() => navigate("/")}>
|
||||||
<ExploreIcon
|
<ExploreIcon
|
||||||
fill={pathMatchRoute("/") ? "#2c2c2c" : "#8f8f8f"}
|
fill={pathMatchRoute("/") ? "#2c2c2c" : "#8f8f8f"}
|
||||||
width="36px"
|
width="36px"
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ const PrivateRoute = () => {
|
|||||||
if (checkingStatus) {
|
if (checkingStatus) {
|
||||||
return <Spinner/>
|
return <Spinner/>
|
||||||
}
|
}
|
||||||
console.log(loggedIn)
|
|
||||||
return loggedIn ? <Outlet /> : <Navigate to="/sign-in" />;
|
return loggedIn ? <Outlet /> : <Navigate to="/sign-in" />;
|
||||||
};
|
};
|
||||||
export default PrivateRoute;
|
export default PrivateRoute;
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import {
|
||||||
|
collection,
|
||||||
|
getDocs,
|
||||||
|
query,
|
||||||
|
where,
|
||||||
|
orderBy,
|
||||||
|
limit,
|
||||||
|
startAfter,
|
||||||
|
} from "firebase/firestore";
|
||||||
|
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() {
|
||||||
|
const [listings, setListings] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
|
const params = useParams();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchListings = async () => {
|
||||||
|
try {
|
||||||
|
const listingsRef = collection(db, "listings");
|
||||||
|
const q = query(
|
||||||
|
listingsRef,
|
||||||
|
where("type", "==", params.categoryName),
|
||||||
|
orderBy("timestamp", "desc"),
|
||||||
|
limit(10)
|
||||||
|
);
|
||||||
|
const querySnap = await getDocs(q);
|
||||||
|
let listings = [];
|
||||||
|
querySnap.forEach((doc) => {
|
||||||
|
return listings.push({
|
||||||
|
id: doc.id,
|
||||||
|
data: doc.data(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setListings(listings);
|
||||||
|
setLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
toast.error("could not fetch listings");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchListings();
|
||||||
|
}, [params.categoryName]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="category">
|
||||||
|
<header>
|
||||||
|
<p className="pageHeader">
|
||||||
|
{params.categoryName === "rent"
|
||||||
|
? "Places for rent"
|
||||||
|
: "Places for sale"}
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
{loading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : listings && listings.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<main>
|
||||||
|
<ul className="categoryListings">
|
||||||
|
{listings.map((listing) => (
|
||||||
|
<ListingItem
|
||||||
|
listing={listing.data}
|
||||||
|
id={listing.id}
|
||||||
|
key={listing.id}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<p>No listings for {params.categoryName}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default Category;
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
import { useState, useRef, useEffect } from "react";
|
||||||
|
import { getAuth, onAuthStateChanged } from "firebase/auth";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import Spinner from "../components/Spinner";
|
||||||
|
|
||||||
|
function CreateLising() {
|
||||||
|
const [geolocationEnabled, setGeolocationEnabled] = useState(true);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
type: "rent",
|
||||||
|
name: "",
|
||||||
|
bedrooms: 1,
|
||||||
|
bathrooms: 1,
|
||||||
|
parking: false,
|
||||||
|
furnished: false,
|
||||||
|
address: "",
|
||||||
|
offer: false,
|
||||||
|
regularPrice: 0,
|
||||||
|
discountedPrice: 0,
|
||||||
|
images: {},
|
||||||
|
latittude: 0,
|
||||||
|
longitude: 0,
|
||||||
|
});
|
||||||
|
const {
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
bedrooms,
|
||||||
|
bathrooms,
|
||||||
|
parking,
|
||||||
|
furnished,
|
||||||
|
address,
|
||||||
|
offer,
|
||||||
|
regularPrice,
|
||||||
|
discountedPrice,
|
||||||
|
images,
|
||||||
|
latittude,
|
||||||
|
longitude,
|
||||||
|
} = formData;
|
||||||
|
|
||||||
|
const auth = getAuth();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const isMounted = useRef(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isMounted) {
|
||||||
|
onAuthStateChanged(auth, (user) => {
|
||||||
|
if (user) {
|
||||||
|
setFormData({ ...formData, userRef: user.uid });
|
||||||
|
} else {
|
||||||
|
navigate("/sign-in");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
isMounted.current = false;
|
||||||
|
};
|
||||||
|
}, [isMounted]);
|
||||||
|
|
||||||
|
const onSubmit = (e) => {
|
||||||
|
e.prevent.default();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMutate = (e) => {
|
||||||
|
let boolean = null;
|
||||||
|
if (e.target.value === "false") {
|
||||||
|
boolean = false;
|
||||||
|
}
|
||||||
|
if (e.target.value === "true") {
|
||||||
|
boolean = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.target.files) {
|
||||||
|
setFormData((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
image: e.target.files,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (!e.target.files) {
|
||||||
|
setFormData((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
[e.target.id]: boolean ?? e.target.value,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <Spinner />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="profile">
|
||||||
|
<header>
|
||||||
|
<p className="pageHeader">Create a listing</p>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<form onSubmit={onSubmit}>
|
||||||
|
<label className="formLabel">Sell / Rent</label>
|
||||||
|
<div className="formButtons">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={type === "sale" ? "formButtonActive" : "formButton"}
|
||||||
|
id="type"
|
||||||
|
value="sale"
|
||||||
|
onClick={onMutate}
|
||||||
|
>
|
||||||
|
Sell
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={type === "rent" ? "formButtonActive" : "formButton"}
|
||||||
|
id="type"
|
||||||
|
value="rent"
|
||||||
|
onClick={onMutate}
|
||||||
|
>
|
||||||
|
Rent
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<label className="formLabel">Sell / Rent</label>
|
||||||
|
<input
|
||||||
|
className="formInputName"
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
value={name}
|
||||||
|
onChange={onMutate}
|
||||||
|
maxLength="32"
|
||||||
|
minLength="10"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div className="formRooms fles">
|
||||||
|
<div>
|
||||||
|
<label className="formLabel">Bedrooms</label>
|
||||||
|
<input
|
||||||
|
className="formInputSmall"
|
||||||
|
type="number"
|
||||||
|
id="bedrooms"
|
||||||
|
value={bedrooms}
|
||||||
|
onChange={onMutate}
|
||||||
|
min="1"
|
||||||
|
max="50"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="formLabel">Bathrooms</label>
|
||||||
|
<input
|
||||||
|
className="formInputSmall"
|
||||||
|
type="number"
|
||||||
|
id="bathrooms"
|
||||||
|
value={bathrooms}
|
||||||
|
onChange={onMutate}
|
||||||
|
min="1"
|
||||||
|
max="50"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label className="formLabel">Parking spot</label>
|
||||||
|
<div className="formButtons">
|
||||||
|
<button
|
||||||
|
className={parking ? "formButtonActive" : "formButton"}
|
||||||
|
type="button"
|
||||||
|
id="parking"
|
||||||
|
value={true}
|
||||||
|
onClick={onMutate}
|
||||||
|
min="1"
|
||||||
|
max="50"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={
|
||||||
|
!parking && parking !== null ? "formButtonActive" : "formButton"
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
|
id="parking"
|
||||||
|
value={false}
|
||||||
|
onClick={onMutate}
|
||||||
|
>
|
||||||
|
No
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label className="formLabel">Furnished</label>
|
||||||
|
<div className="formButtons">
|
||||||
|
<button
|
||||||
|
className={furnished ? "formButtonActive" : "formButton"}
|
||||||
|
type="button"
|
||||||
|
id="furnished"
|
||||||
|
value={true}
|
||||||
|
onClick={onMutate}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={
|
||||||
|
!furnished && furnished !== null
|
||||||
|
? "formButtonActive"
|
||||||
|
: "formButton"
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
|
id="furnished"
|
||||||
|
value={false}
|
||||||
|
onClick={onMutate}
|
||||||
|
>
|
||||||
|
No
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<textarea
|
||||||
|
className="formInputAddress"
|
||||||
|
type="text"
|
||||||
|
id="address"
|
||||||
|
value={address}
|
||||||
|
onChange={onMutate}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
{!geolocationEnabled && (
|
||||||
|
<div className="formLatLng fles">
|
||||||
|
<div>
|
||||||
|
<label className="formLabel">Latitude</label>
|
||||||
|
<input
|
||||||
|
className="formInputSmall"
|
||||||
|
type="number"
|
||||||
|
id="latittude"
|
||||||
|
value={latittude}
|
||||||
|
onChange={onMutate}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="formLabel">Longitude</label>
|
||||||
|
<input
|
||||||
|
className="formInputSmall"
|
||||||
|
type="number"
|
||||||
|
id="longitude"
|
||||||
|
value={longitude}
|
||||||
|
onChange={onMutate}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<label className='formLabel'>Offer</label>
|
||||||
|
<div className='formButtons'>
|
||||||
|
<button
|
||||||
|
className={offer ? 'formButtonActive' : 'formButton'}
|
||||||
|
type='button'
|
||||||
|
id='offer'
|
||||||
|
value={true}
|
||||||
|
onClick={onMutate}
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={
|
||||||
|
!offer && offer !== null ? 'formButtonActive' : 'formButton'
|
||||||
|
}
|
||||||
|
type='button'
|
||||||
|
id='offer'
|
||||||
|
value={false}
|
||||||
|
onClick={onMutate}
|
||||||
|
>
|
||||||
|
No
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<label className="formLabel"> Regular Price</label>
|
||||||
|
<div className="formPriceDiv">
|
||||||
|
<input
|
||||||
|
className="formInputSmall"
|
||||||
|
type="number"
|
||||||
|
id="regularPrice"
|
||||||
|
value={regularPrice}
|
||||||
|
onChange={onMutate}
|
||||||
|
min="50"
|
||||||
|
max="750000000"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
{formData.type === "rent" && (
|
||||||
|
<p className="formPriceText">$ / Month</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{offer && (
|
||||||
|
<>
|
||||||
|
<label className="formLabel">Discounted Price</label>
|
||||||
|
<input
|
||||||
|
className="formInputName"
|
||||||
|
type="number"
|
||||||
|
id="discountedPrice"
|
||||||
|
value={discountedPrice}
|
||||||
|
onChange={onMutate}
|
||||||
|
min="50"
|
||||||
|
max="750000000"
|
||||||
|
required={offer}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<label className="formLabel">Discounted Price</label>
|
||||||
|
<p className="imagesInfo">
|
||||||
|
The first image will be the cover (max 6).
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
className="formInputFile"
|
||||||
|
type="file"
|
||||||
|
id="image"
|
||||||
|
onChange={onMutate}
|
||||||
|
max="6"
|
||||||
|
accept=".jpg,.png,.jpeg"
|
||||||
|
multiple
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<button className="primaryButton createListingButton">
|
||||||
|
Create Listing
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default CreateLising;
|
||||||
+22
-4
@@ -1,9 +1,27 @@
|
|||||||
|
import {Link} from 'react-router-dom'
|
||||||
|
import rentCategoryImage from '../assets/jpg/rentCategoryImage.jpg'
|
||||||
|
import sellCategoryImage from '../assets/jpg/sellCategoryImage.jpg'
|
||||||
function Explore (){
|
function Explore (){
|
||||||
return (
|
return (
|
||||||
<>
|
<div className='export'>
|
||||||
<h1>My app</h1>
|
<header>
|
||||||
</>
|
<p className='pageHeader'>Explore</p>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
{/*Slider*/}
|
||||||
|
<p className='exploreCategoryHeading'>Categories</p>
|
||||||
|
<div className='exploreCategories'>
|
||||||
|
<Link to='/category/rent'>
|
||||||
|
<img src={rentCategoryImage} alt='rent' className='exploreCategoryImg'/>
|
||||||
|
</Link>
|
||||||
|
<p className='exploreCategoryName'>Places for rent</p>
|
||||||
|
<Link to='/category/sale'>
|
||||||
|
<img src={sellCategoryImage} alt='sell' className='exploreCategoryImg'/>
|
||||||
|
</Link>
|
||||||
|
<p className='exploreCategoryName'>Places for sale</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+78
-5
@@ -1,9 +1,82 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import {
|
||||||
|
collection,
|
||||||
|
getDocs,
|
||||||
|
query,
|
||||||
|
where,
|
||||||
|
orderBy,
|
||||||
|
limit,
|
||||||
|
startAfter,
|
||||||
|
} from "firebase/firestore";
|
||||||
|
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 Offers() {
|
||||||
|
const [listings, setListings] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
|
const params = useParams();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchListings = async () => {
|
||||||
|
try {
|
||||||
|
const listingsRef = collection(db, "listings");
|
||||||
|
const q = query(
|
||||||
|
listingsRef,
|
||||||
|
where("offer", "==", true),
|
||||||
|
orderBy("timestamp", "desc"),
|
||||||
|
limit(10)
|
||||||
|
);
|
||||||
|
const querySnap = await getDocs(q);
|
||||||
|
let listings = [];
|
||||||
|
querySnap.forEach((doc) => {
|
||||||
|
return listings.push({
|
||||||
|
id: doc.id,
|
||||||
|
data: doc.data(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setListings(listings);
|
||||||
|
setLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
toast.error("could not fetch listings");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchListings();
|
||||||
|
}, []);
|
||||||
|
|
||||||
function Offers (){
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="category">
|
||||||
<h1>My app</h1>
|
<header>
|
||||||
</>
|
<p className="pageHeader">Offers</p>
|
||||||
|
</header>
|
||||||
|
{loading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : listings && listings.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<main>
|
||||||
|
<ul className="categoryListings">
|
||||||
|
{listings.map((listing) => (
|
||||||
|
<ListingItem
|
||||||
|
listing={listing.data}
|
||||||
|
id={listing.id}
|
||||||
|
key={listing.id}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<p>There are no current Offers</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default Offers
|
export default Offers;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import arrowRight from '../assets/svg/keyboardArrowRightIcon.svg'
|
||||||
|
import homeIcon from '../assets/svg/homeIcon.svg'
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { getAuth, updateProfile } from "firebase/auth";
|
import { getAuth, updateProfile } from "firebase/auth";
|
||||||
@@ -82,6 +84,11 @@ function Profile() {
|
|||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<Link to='/create-listing' className='createListing'>
|
||||||
|
<img src={homeIcon} alt='home'/>
|
||||||
|
<p>Sell or rent your home</p>
|
||||||
|
<img src={arrowRight} alt='arrowRight'/>
|
||||||
|
</Link>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user