diff --git a/real_estate/client/package-lock.json b/real_estate/client/package-lock.json index 48ca987..6cc0f80 100644 --- a/real_estate/client/package-lock.json +++ b/real_estate/client/package-lock.json @@ -15,7 +15,8 @@ "react-icons": "^5.0.1", "react-redux": "^9.1.0", "react-router-dom": "^6.22.3", - "redux-persist": "^6.0.0" + "redux-persist": "^6.0.0", + "swiper": "^11.0.7" }, "devDependencies": { "@types/react": "^18.2.56", @@ -5202,6 +5203,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swiper": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-11.0.7.tgz", + "integrity": "sha512-cDfglW1B6uSmB6eB6pNmzDTNLmZtu5bWWa1vak0RU7fOI9qHjMzl7gVBvYSl34b0RU2N11HxxETJqQ5LeqI1cA==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/tailwindcss": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", diff --git a/real_estate/client/package.json b/real_estate/client/package.json index 7aa1f3f..bda3b16 100644 --- a/real_estate/client/package.json +++ b/real_estate/client/package.json @@ -17,7 +17,8 @@ "react-icons": "^5.0.1", "react-redux": "^9.1.0", "react-router-dom": "^6.22.3", - "redux-persist": "^6.0.0" + "redux-persist": "^6.0.0", + "swiper": "^11.0.7" }, "devDependencies": { "@types/react": "^18.2.56", diff --git a/real_estate/client/src/App.jsx b/real_estate/client/src/App.jsx index 4377412..2b2cd9a 100644 --- a/real_estate/client/src/App.jsx +++ b/real_estate/client/src/App.jsx @@ -8,6 +8,7 @@ import Navbar from './components/Navbar' import PrivateRoute from './components/PrivateRoute' import CreatListing from './pages/CreatListing' import UpdateListing from './pages/UpdateListing' +import Listing from './pages/Listing' const App = () => { @@ -21,6 +22,7 @@ const App = () => { }/> }/> + }/> }/> }/> }/> diff --git a/real_estate/client/src/index.css b/real_estate/client/src/index.css index bcf21eb..012f137 100644 --- a/real_estate/client/src/index.css +++ b/real_estate/client/src/index.css @@ -3,3 +3,46 @@ @tailwind utilities; +.swiper-slide{ + display: flex; + justify-content: center; + align-items: center; +} +.swiper-slide img{ + display: block; + width: 600px; + height: 100%; + object-fit: contain; +} +.swiper{ + width: 500px; + height: 100%; + margin-left: auto; + margin-right: auto; +} +.swiper-slide { + background-size: cover; + background-position: center; +} +.mySwiper2 { + height: 100%; + width: 100%; +} +.mySwiper { + box-sizing: border-box; + padding: 10px 0px; +} +.mySwiper .swiper-slide { + width: 500px; + height: 100px; + opacity: 0.4; +} +.mySwiper .swiper-slide-thumb-active { + opacity: 1; +} +.swiper-slide img { + display: block; + width: 850px; + height: 100%; + object-fit: contain; +} diff --git a/real_estate/client/src/pages/Listing.jsx b/real_estate/client/src/pages/Listing.jsx new file mode 100644 index 0000000..895ec7b --- /dev/null +++ b/real_estate/client/src/pages/Listing.jsx @@ -0,0 +1,103 @@ +import { useEffect, useState } from "react" +import {useParams} from 'react-router-dom' +import {Swiper, SwiperSlide} from 'swiper/react' +import { useSelector } from 'react-redux'; +import 'swiper/css'; +import 'swiper/css/free-mode'; +import 'swiper/css/navigation'; +import 'swiper/css/thumbs'; +import { FreeMode, Navigation, Thumbs } from 'swiper/modules'; +import { BiSolidMap } from "react-icons/bi"; + + +const Listing = () => { + const [thumbsSwiper, setThumbsSwiper] = useState(null); + const params = useParams(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(false); + const [listing, setListing] = useState(null); + const { currentUser } = useSelector((state) => state.user); + useEffect(() => { + const fetchListing = async() =>{ + try { + setLoading(true) + const res = await fetch(`/server/listing/get/${params.listingId}`); + const data = await res.json(); + if(data.success === false){ + setError(true); + setLoading(false); + return; + } + setListing(data); + setLoading(false); + setError(false) + + } catch (error) { + setError(true); + setLoading(false); + } + }; + fetchListing(); + }, [params.listingId]); + + + return ( +
+ {loading &&

Loading...

} + {error &&

Something went wrong

} + {listing && !loading && !error && + <> + + {listing.imageUrls.map(url => + + )} + + + {listing.imageUrls.map(url => + + )} + +
+

+ {listing.name} - $ {''} + {listing.offer ? listing.discountPrice.toLocaleString('en-US') : listing.currentPrice.toLocaleString('en-US')} + {listing.type === 'rent' && ' / month'} +

+

{listing.address}

+ +
+
    +
  • +
    {listing.bed > 1 ? `${listing.bed} beds ` : `${listing.bed} bed `}
    +
  • +
  • +
    | {listing.bath > 1? `${listing.bath} baths ` : `${listing.bath} bath `}
    +
  • +
  • +
    | {listing.parking ? 'Garage' : 'No Garage'}
    +
  • +
  • +
    | {listing.furnished ? 'Furnished' : 'Unfurnished'}
    +
  • +
+
+

{listing.type === 'rent' ? 'For Rent' : 'For Sale'}

+ {listing.offer && ( +

+ ${+listing.currentPrice - +listing.discountPrice} Off

+ )} +
+
+

+ About this property + {listing.description} +

+ +
+ + } +
+ ) +} + +export default Listing \ No newline at end of file