stay_commerce-frontend 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +8 -0
- data/app/assets/builds/404error-RVKQJ4S4.digested.jpg +0 -0
- data/app/assets/builds/Facebook-5HJUILVR.digested.svg +3 -0
- data/app/assets/builds/Google-CZ3UPVSC.digested.svg +6 -0
- data/app/assets/builds/application.js +95 -0
- data/app/assets/builds/application.js.map +7 -0
- data/app/assets/builds/beach-KAZW5GM3.digested.jpg +0 -0
- data/app/assets/builds/beach2-3ARC34NS.digested.jpg +0 -0
- data/app/assets/builds/beach3-PSTOH5FV.digested.jpg +0 -0
- data/app/assets/builds/beach4-PWNRPD3S.digested.jpg +0 -0
- data/app/assets/builds/beach5-SBOKKRHF.digested.jpg +0 -0
- data/app/assets/builds/beach6-SXZ5Y5AI.digested.jpg +0 -0
- data/app/assets/builds/beach7-FNBMFVKK.digested.jpg +0 -0
- data/app/assets/builds/beach8-TD7LTRQM.digested.jpg +0 -0
- data/app/assets/builds/bg-image-H7UGUMV2.digested.jpg +0 -0
- data/app/assets/builds/bgimage-DU3PCXKN.digested.jpg +0 -0
- data/app/assets/builds/bundle.css +30914 -0
- data/app/assets/builds/bundle.css.map +7 -0
- data/app/assets/builds/bundle.js +74569 -0
- data/app/assets/builds/bundle.js.map +7 -0
- data/app/assets/builds/hotel1-HGBXPKJK.digested.jpg +0 -0
- data/app/assets/builds/logo_updated-KQWAXLYL.digested.png +0 -0
- data/app/assets/builds/styles.css +6422 -0
- data/app/assets/builds/styles.css.map +7 -0
- data/app/assets/config/manifest.js +2 -0
- data/app/assets/images/favicon.ico +0 -0
- data/app/assets/images/stay_commerce/frontend/beach-666122_1280 (1).jpg +0 -0
- data/app/assets/images/stay_commerce/frontend/beach-666122_1280.jpg +0 -0
- data/app/assets/stylesheets/stay_commerce/frontend/application.css +15 -0
- data/app/controllers/stay_commerce/frontend/application_controller.rb +8 -0
- data/app/controllers/stay_commerce/frontend/welcome_controller.rb +6 -0
- data/app/helpers/stay_commerce/frontend/application_helper.rb +6 -0
- data/app/javascript/Images/404error.jpg +0 -0
- data/app/javascript/Images/Facebook.svg +3 -0
- data/app/javascript/Images/Google.svg +6 -0
- data/app/javascript/Images/beach-2245867_1280.jpg +0 -0
- data/app/javascript/Images/beach.jpg +0 -0
- data/app/javascript/Images/beach2.jpg +0 -0
- data/app/javascript/Images/beach3.jpg +0 -0
- data/app/javascript/Images/beach4.jpg +0 -0
- data/app/javascript/Images/beach5.jpg +0 -0
- data/app/javascript/Images/beach6.jpg +0 -0
- data/app/javascript/Images/beach7.jpg +0 -0
- data/app/javascript/Images/beach8.jpg +0 -0
- data/app/javascript/Images/bg-image.jpg +0 -0
- data/app/javascript/Images/bgimage.jpg +0 -0
- data/app/javascript/Images/blog-1.jpg +0 -0
- data/app/javascript/Images/gallery.png +0 -0
- data/app/javascript/Images/home 5.jpg +0 -0
- data/app/javascript/Images/home1.jpg +0 -0
- data/app/javascript/Images/home2.jpg +0 -0
- data/app/javascript/Images/home3.jpg +0 -0
- data/app/javascript/Images/home6.jpg +0 -0
- data/app/javascript/Images/hotel1.jpg +0 -0
- data/app/javascript/Images/room1.jpg +0 -0
- data/app/javascript/Images/room2.jpg +0 -0
- data/app/javascript/Images/room3.jpg +0 -0
- data/app/javascript/Images/room4.jpg +0 -0
- data/app/javascript/Images/wine-4520213_1280.jpg +0 -0
- data/app/javascript/application.js +1 -0
- data/app/javascript/react/Api/apiConstants.js +47 -0
- data/app/javascript/react/assets/beach-2245867_1280.jpg +0 -0
- data/app/javascript/react/assets/logo.png +0 -0
- data/app/javascript/react/assets/logo_updated.png +0 -0
- data/app/javascript/react/components/AboutUsPage/AboutPage.jsx +41 -0
- data/app/javascript/react/components/AboutusFront/About.jsx +37 -0
- data/app/javascript/react/components/Accommodation/Accommodation.jsx +32 -0
- data/app/javascript/react/components/Accommodation/NormalListing.jsx +50 -0
- data/app/javascript/react/components/Accommodation/SpecialListing.jsx +51 -0
- data/app/javascript/react/components/Accountpage/AccountInfo.jsx +217 -0
- data/app/javascript/react/components/Accountpage/AccountPage.jsx +27 -0
- data/app/javascript/react/components/Accountpage/CommonPage.jsx +24 -0
- data/app/javascript/react/components/AddNewProperty/CommonLayout.jsx +68 -0
- data/app/javascript/react/components/AddNewProperty/Description.jsx +229 -0
- data/app/javascript/react/components/AddNewProperty/Details.jsx +234 -0
- data/app/javascript/react/components/AddNewProperty/Images.jsx +196 -0
- data/app/javascript/react/components/AddNewProperty/Location.jsx +239 -0
- data/app/javascript/react/components/AddNewProperty/Room.jsx +1132 -0
- data/app/javascript/react/components/AvatarDropdown/AvatarDropDown.jsx +142 -0
- data/app/javascript/react/components/BlogDesign/BlogsLatest.jsx +67 -0
- data/app/javascript/react/components/ContactUs/Contact.jsx +89 -0
- data/app/javascript/react/components/FacilitiesSection/Facilities.jsx +66 -0
- data/app/javascript/react/components/FixedNavbar/FixedNav.jsx +88 -0
- data/app/javascript/react/components/ForgetPassword/ForgetPassword.jsx +103 -0
- data/app/javascript/react/components/Gallery/Gallery.jsx +164 -0
- data/app/javascript/react/components/GalleryModalLight/GalleryModalLight.jsx +35 -0
- data/app/javascript/react/components/GallerySlider/GallerySlider.jsx +58 -0
- data/app/javascript/react/components/Headers/PropertyCard.jsx +46 -0
- data/app/javascript/react/components/HeroSectionDesign/BookingForm.jsx +178 -0
- data/app/javascript/react/components/HeroSectionDesign/HeroSection.jsx +29 -0
- data/app/javascript/react/components/HeroSectionDesign/MyPropertiesListing.jsx +104 -0
- data/app/javascript/react/components/HeroSectionDesign/PropertiesPage.jsx +122 -0
- data/app/javascript/react/components/HotelListing/Listing.jsx +48 -0
- data/app/javascript/react/components/Layout/Layout.js +18 -0
- data/app/javascript/react/components/Listing-stay-Detail/AmenitiesFeatures.jsx +58 -0
- data/app/javascript/react/components/Listing-stay-Detail/AmenitiesModal.jsx +250 -0
- data/app/javascript/react/components/Listing-stay-Detail/ApartmentCard.jsx +120 -0
- data/app/javascript/react/components/Listing-stay-Detail/BookingModal.jsx +398 -0
- data/app/javascript/react/components/Listing-stay-Detail/CheckoutForm.jsx +296 -0
- data/app/javascript/react/components/Listing-stay-Detail/ListingStayDetailPage.jsx +512 -0
- data/app/javascript/react/components/Listing-stay-Detail/PropertyDescription.jsx +76 -0
- data/app/javascript/react/components/Listing-stay-Detail/PropertyDetailsCard.jsx +62 -0
- data/app/javascript/react/components/Listing-stay-Detail/Reviews.jsx +132 -0
- data/app/javascript/react/components/Listing-stay-Detail/RoomDescriptionModal.jsx +105 -0
- data/app/javascript/react/components/Listing-stay-Detail/Rules.jsx +23 -0
- data/app/javascript/react/components/ListingImageGallery/ListingImageGallery.jsx +30 -0
- data/app/javascript/react/components/LoginPage/LoginPage.jsx +115 -0
- data/app/javascript/react/components/MobileNav/MobileMenu.jsx +47 -0
- data/app/javascript/react/components/Navbar/Navbar.jsx +25 -0
- data/app/javascript/react/components/Page404/Page404.jsx +30 -0
- data/app/javascript/react/components/PropertyListing/MyProperties.jsx +146 -0
- data/app/javascript/react/components/PropertyListing/StayBooking/BookingDetails.jsx +178 -0
- data/app/javascript/react/components/PropertyListing/StayBooking/MyBooking.jsx +83 -0
- data/app/javascript/react/components/ResetPassword/ResetPassword.jsx +117 -0
- data/app/javascript/react/components/SignupPage/SignupPage.jsx +185 -0
- data/app/javascript/react/components/SmallNavbar/SmallNav.jsx +51 -0
- data/app/javascript/react/components/SocialAuth/SocialAuth.jsx +21 -0
- data/app/javascript/react/components/StayCard/StayCard.jsx +69 -0
- data/app/javascript/react/components/StayCard/StayCard2.jsx +45 -0
- data/app/javascript/react/components/StayCard/StayCard3.jsx +45 -0
- data/app/javascript/react/components/TestimonialSection/Testimonial.jsx +113 -0
- data/app/javascript/react/components/Unauthorized/Unauthorized.jsx +12 -0
- data/app/javascript/react/data/jsons/__countryListing.json +201 -0
- data/app/javascript/react/packs/App.js +26 -0
- data/app/javascript/react/packs/index.jsx +38 -0
- data/app/javascript/react/packs/routes/ParentRoute.jsx +14 -0
- data/app/javascript/react/packs/routes/Route.jsx +163 -0
- data/app/javascript/react/pages/AccommodationList.jsx +21 -0
- data/app/javascript/react/pages/Home.jsx +32 -0
- data/app/javascript/react/redux/slices/AuthSlice/AuthSlice.jsx +100 -0
- data/app/javascript/react/redux/slices/PropertySlice/PropertySlice.jsx +722 -0
- data/app/javascript/react/redux/slices/PropertySlice/Searchslice.jsx +36 -0
- data/app/javascript/react/redux/slices/UserSlice/UserSlice.jsx +215 -0
- data/app/javascript/react/redux/store.js +35 -0
- data/app/javascript/react/shared/Avatar/Avatar.jsx +32 -0
- data/app/javascript/react/shared/Badge/Badge.jsx +33 -0
- data/app/javascript/react/shared/Button/Button.jsx +67 -0
- data/app/javascript/react/shared/Button/ButtonPrimary.jsx +11 -0
- data/app/javascript/react/shared/Button/ButtonSelect.jsx +9 -0
- data/app/javascript/react/shared/Checkbox/Checkbox.jsx +38 -0
- data/app/javascript/react/shared/CurrencySymbol.jsx +6 -0
- data/app/javascript/react/shared/DateField/CustomDatePicker.jsx +69 -0
- data/app/javascript/react/shared/FooterSection/Footer.jsx +75 -0
- data/app/javascript/react/shared/FormField/FormField.jsx +75 -0
- data/app/javascript/react/shared/FormItem/FormItem.jsx +20 -0
- data/app/javascript/react/shared/Input/Input.jsx +27 -0
- data/app/javascript/react/shared/Label/Label.jsx +12 -0
- data/app/javascript/react/shared/Modal.jsx +20 -0
- data/app/javascript/react/shared/NcImage/NcImage.jsx +101 -0
- data/app/javascript/react/shared/NcImage/PlaceIcon.jsx +31 -0
- data/app/javascript/react/shared/NcImage/placecImageIcon.svg +6 -0
- data/app/javascript/react/shared/Select/Select.jsx +20 -0
- data/app/javascript/react/styles/404error.scss +58 -0
- data/app/javascript/react/styles/ApartmentCard.scss +126 -0
- data/app/javascript/react/styles/BookingDetails.scss +457 -0
- data/app/javascript/react/styles/Modal.scss +36 -0
- data/app/javascript/react/styles/PropertiesPage.scss +219 -0
- data/app/javascript/react/styles/RenderSection.scss +480 -0
- data/app/javascript/react/styles/about.scss +97 -0
- data/app/javascript/react/styles/accountinfo.scss +67 -0
- data/app/javascript/react/styles/accountpage.scss +36 -0
- data/app/javascript/react/styles/amenitiesfeatures.scss +223 -0
- data/app/javascript/react/styles/application.scss +87 -0
- data/app/javascript/react/styles/avatar.scss +39 -0
- data/app/javascript/react/styles/avatardropdown.scss +57 -0
- data/app/javascript/react/styles/badge.scss +90 -0
- data/app/javascript/react/styles/blog.scss +100 -0
- data/app/javascript/react/styles/bookingform.scss +124 -0
- data/app/javascript/react/styles/button.scss +44 -0
- data/app/javascript/react/styles/buttonprimary.scss +32 -0
- data/app/javascript/react/styles/checkbox.scss +37 -0
- data/app/javascript/react/styles/commonlayout.scss +83 -0
- data/app/javascript/react/styles/commonpage.scss +51 -0
- data/app/javascript/react/styles/contact.scss +173 -0
- data/app/javascript/react/styles/customdatepicker.scss +120 -0
- data/app/javascript/react/styles/description.scss +21 -0
- data/app/javascript/react/styles/details.scss +88 -0
- data/app/javascript/react/styles/facilities.scss +131 -0
- data/app/javascript/react/styles/fixednavbar.scss +137 -0
- data/app/javascript/react/styles/fonts.scss +22 -0
- data/app/javascript/react/styles/footer.scss +300 -0
- data/app/javascript/react/styles/forgetpassword.scss +68 -0
- data/app/javascript/react/styles/formfield.scss +39 -0
- data/app/javascript/react/styles/formitem.scss +20 -0
- data/app/javascript/react/styles/gallery.scss +142 -0
- data/app/javascript/react/styles/gallerymodallight.scss +137 -0
- data/app/javascript/react/styles/galleryslider.scss +114 -0
- data/app/javascript/react/styles/header.scss +49 -0
- data/app/javascript/react/styles/herosection.scss +61 -0
- data/app/javascript/react/styles/images.scss +112 -0
- data/app/javascript/react/styles/input.scss +58 -0
- data/app/javascript/react/styles/label.scss +11 -0
- data/app/javascript/react/styles/listing.scss +94 -0
- data/app/javascript/react/styles/listingimagegallery.scss +57 -0
- data/app/javascript/react/styles/listingstaydetailpage.scss +887 -0
- data/app/javascript/react/styles/location.scss +66 -0
- data/app/javascript/react/styles/loginpage.scss +150 -0
- data/app/javascript/react/styles/mobilemenu.scss +53 -0
- data/app/javascript/react/styles/mybooking.scss +104 -0
- data/app/javascript/react/styles/myproperty.scss +51 -0
- data/app/javascript/react/styles/ncimage.scss +24 -0
- data/app/javascript/react/styles/normallisting.scss +95 -0
- data/app/javascript/react/styles/property-description.scss +75 -0
- data/app/javascript/react/styles/propertycard.scss +48 -0
- data/app/javascript/react/styles/propertydetailscard.scss +302 -0
- data/app/javascript/react/styles/resetpassword.scss +79 -0
- data/app/javascript/react/styles/reviews.scss +185 -0
- data/app/javascript/react/styles/room.scss +275 -0
- data/app/javascript/react/styles/rooms.scss +0 -0
- data/app/javascript/react/styles/select.scss +44 -0
- data/app/javascript/react/styles/signuppage.scss +132 -0
- data/app/javascript/react/styles/smallnav.scss +94 -0
- data/app/javascript/react/styles/socialauth.scss +62 -0
- data/app/javascript/react/styles/speciallisting.scss +94 -0
- data/app/javascript/react/styles/staycard.scss +77 -0
- data/app/javascript/react/styles/staycard2.scss +115 -0
- data/app/javascript/react/styles/testimonial.scss +216 -0
- data/app/javascript/react/styles/unauthorized.scss +22 -0
- data/app/javascript/react/styles/variables.scss +3 -0
- data/app/javascript/react/styles/wrapper.scss +4 -0
- data/app/javascript/react/utils/formSchema.js +120 -0
- data/app/javascript/react/utils/helpers/APIHelper.jsx +55 -0
- data/app/javascript/react/utils/helpers/ErrorHandler.js +21 -0
- data/app/javascript/react/utils/helpers/InfoHandler.js +15 -0
- data/app/javascript/react/utils/helpers/SuccessHandler.js +12 -0
- data/app/javascript/react/utils/helpers/isInViewPortIntersectionObserver.jsx +39 -0
- data/app/jobs/stay_commerce/frontend/application_job.rb +6 -0
- data/app/mailers/stay_commerce/frontend/application_mailer.rb +8 -0
- data/app/models/stay_commerce/frontend/application_record.rb +7 -0
- data/app/views/layouts/stay_commerce/frontend/application.html.erb +61 -0
- data/app/views/stay_commerce/frontend/welcome/index.html.erb +2 -0
- data/config/initializers/cors.rb +6 -0
- data/config/initializers/devise.rb +359 -0
- data/config/routes.rb +11 -0
- data/lib/stay_commerce/frontend/engine.rb +14 -0
- data/lib/stay_commerce/frontend/version.rb +5 -0
- data/lib/stay_commerce/frontend.rb +8 -0
- data/lib/tasks/stay_commerce/frontend_tasks.rake +4 -0
- metadata +370 -0
@@ -0,0 +1,164 @@
|
|
1
|
+
|
2
|
+
import React, { useState } from "react";
|
3
|
+
import Navbar from "../Navbar/Navbar";
|
4
|
+
import { Link } from "react-router-dom";
|
5
|
+
import Lightbox from "../GalleryModalLight/GalleryModalLight";
|
6
|
+
import Bg from "../../../Images/bgimage.jpg";
|
7
|
+
|
8
|
+
import Bg1 from "../../../Images/beach.jpg";
|
9
|
+
import Bg2 from "../../../Images/beach2.jpg";
|
10
|
+
import Bg3 from "../../../Images/beach3.jpg";
|
11
|
+
import Bg4 from "../../../Images/beach4.jpg";
|
12
|
+
import Bg5 from "../../../Images/beach5.jpg";
|
13
|
+
import Bg6 from "../../../Images/beach6.jpg";
|
14
|
+
import Bg7 from "../../../Images/beach7.jpg";
|
15
|
+
import Bg8 from "../../../Images/blog-1.jpg";
|
16
|
+
import Bg9 from "../../../Images/beach8.jpg";
|
17
|
+
|
18
|
+
import "../../styles/gallery.scss";
|
19
|
+
import "../../styles/wrapper.scss";
|
20
|
+
|
21
|
+
const Gallery = () => {
|
22
|
+
const [lightboxOpen, setLightboxOpen] = useState(false);
|
23
|
+
const [currentImage, setCurrentImage] = useState(null);
|
24
|
+
|
25
|
+
const galleryImages = [
|
26
|
+
{ src: Bg1, alt: "Hotel room" },
|
27
|
+
{ src: Bg2, alt: "Chef cooking" },
|
28
|
+
{ src: Bg3, alt: "Pool with loungers" },
|
29
|
+
{ src: Bg9, alt: "Infinity pool" },
|
30
|
+
{ src: Bg4, alt: "Woman at beach" },
|
31
|
+
{ src: Bg5, alt: "Overwater bungalows" },
|
32
|
+
{ src: Bg6, alt: "Strawberry dessert" },
|
33
|
+
{ src: Bg7, alt: "Beach view" },
|
34
|
+
];
|
35
|
+
|
36
|
+
const openLightbox = (image) => {
|
37
|
+
setCurrentImage(image);
|
38
|
+
setLightboxOpen(true);
|
39
|
+
document.body.style.overflow = "hidden";
|
40
|
+
};
|
41
|
+
|
42
|
+
const closeLightbox = () => {
|
43
|
+
setLightboxOpen(false);
|
44
|
+
document.body.style.overflow = "auto";
|
45
|
+
};
|
46
|
+
|
47
|
+
const navigateImage = (direction) => {
|
48
|
+
const currentIndex = galleryImages.findIndex(img => img.src === currentImage.src);
|
49
|
+
const newIndex = (currentIndex + direction + galleryImages.length) % galleryImages.length;
|
50
|
+
setCurrentImage(galleryImages[newIndex]);
|
51
|
+
};
|
52
|
+
|
53
|
+
return (
|
54
|
+
<>
|
55
|
+
{/* Hero Section */}
|
56
|
+
<div
|
57
|
+
className="gallery-hero"
|
58
|
+
style={{ backgroundImage: `url(${Bg})` }}
|
59
|
+
>
|
60
|
+
<h1 className="gallery-title">Gallery</h1>
|
61
|
+
|
62
|
+
<div className="breadcrumb">
|
63
|
+
<Link to="/" className="breadcrumb-link">
|
64
|
+
Home
|
65
|
+
</Link>
|
66
|
+
<span className="breadcrumb-separator">→</span>
|
67
|
+
<span className="breadcrumb-current">Gallery</span>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
|
71
|
+
<div className="gallery-content">
|
72
|
+
<div className="wrapper">
|
73
|
+
<h2 className="gallery-heading">Hotel Gallery</h2>
|
74
|
+
<p className="gallery-subheading">
|
75
|
+
Who are in extremely love with eco-friendly system.
|
76
|
+
</p>
|
77
|
+
|
78
|
+
<div className="gallery-grid">
|
79
|
+
{/* First row */}
|
80
|
+
<div className="gallery-item">
|
81
|
+
<img
|
82
|
+
src={Bg1}
|
83
|
+
alt="Hotel room"
|
84
|
+
className="gallery-img"
|
85
|
+
onClick={() => openLightbox(galleryImages[0])}
|
86
|
+
/>
|
87
|
+
</div>
|
88
|
+
<div className="gallery-item tall">
|
89
|
+
<img
|
90
|
+
src={Bg2}
|
91
|
+
alt="Chef cooking"
|
92
|
+
className="gallery-img"
|
93
|
+
onClick={() => openLightbox(galleryImages[1])}
|
94
|
+
/>
|
95
|
+
</div>
|
96
|
+
<div className="gallery-item">
|
97
|
+
<img
|
98
|
+
src={Bg3}
|
99
|
+
alt="Pool with loungers"
|
100
|
+
className="gallery-img"
|
101
|
+
onClick={() => openLightbox(galleryImages[2])}
|
102
|
+
/>
|
103
|
+
</div>
|
104
|
+
|
105
|
+
{/* Second row */}
|
106
|
+
<div className="gallery-item">
|
107
|
+
<img
|
108
|
+
src={Bg9}
|
109
|
+
alt="Infinity pool"
|
110
|
+
className="gallery-img"
|
111
|
+
onClick={() => openLightbox(galleryImages[3])}
|
112
|
+
/>
|
113
|
+
</div>
|
114
|
+
<div className="gallery-item">
|
115
|
+
<img
|
116
|
+
src={Bg4}
|
117
|
+
alt="Woman at beach"
|
118
|
+
className="gallery-img"
|
119
|
+
onClick={() => openLightbox(galleryImages[4])}
|
120
|
+
/>
|
121
|
+
</div>
|
122
|
+
|
123
|
+
{/* Third row */}
|
124
|
+
<div className="gallery-item">
|
125
|
+
<img
|
126
|
+
src={Bg5}
|
127
|
+
alt="Overwater bungalows"
|
128
|
+
className="gallery-img"
|
129
|
+
onClick={() => openLightbox(galleryImages[5])}
|
130
|
+
/>
|
131
|
+
</div>
|
132
|
+
<div className="gallery-item">
|
133
|
+
<img
|
134
|
+
src={Bg6}
|
135
|
+
alt="Strawberry dessert"
|
136
|
+
className="gallery-img"
|
137
|
+
onClick={() => openLightbox(galleryImages[6])}
|
138
|
+
/>
|
139
|
+
</div>
|
140
|
+
<div className="gallery-item">
|
141
|
+
<img
|
142
|
+
src={Bg7}
|
143
|
+
alt="Beach view"
|
144
|
+
className="gallery-img"
|
145
|
+
onClick={() => openLightbox(galleryImages[7])}
|
146
|
+
/>
|
147
|
+
</div>
|
148
|
+
</div>
|
149
|
+
</div>
|
150
|
+
</div>
|
151
|
+
|
152
|
+
{/* Lightbox Component */}
|
153
|
+
<Lightbox
|
154
|
+
currentImage={currentImage}
|
155
|
+
isOpen={lightboxOpen}
|
156
|
+
onClose={closeLightbox}
|
157
|
+
onNavigate={navigateImage}
|
158
|
+
/>
|
159
|
+
|
160
|
+
</>
|
161
|
+
);
|
162
|
+
};
|
163
|
+
|
164
|
+
export default Gallery;
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import "../../styles/gallerymodallight.scss";
|
3
|
+
|
4
|
+
const Lightbox = ({ currentImage, isOpen, onClose, onNavigate }) => {
|
5
|
+
if (!isOpen || !currentImage) return null;
|
6
|
+
|
7
|
+
return (
|
8
|
+
<div className="lightbox-overlay" onClick={onClose}>
|
9
|
+
<div className="lightbox-container" onClick={(e) => e.stopPropagation()}>
|
10
|
+
<button className="lightbox-close" onClick={onClose}>×</button>
|
11
|
+
<button
|
12
|
+
className="lightbox-nav lightbox-prev"
|
13
|
+
onClick={() => onNavigate(-1)}
|
14
|
+
>
|
15
|
+
‹
|
16
|
+
</button>
|
17
|
+
<div className="lightbox-image-container">
|
18
|
+
<img
|
19
|
+
src={currentImage.src}
|
20
|
+
alt={currentImage.alt}
|
21
|
+
className="lightbox-image"
|
22
|
+
/>
|
23
|
+
</div>
|
24
|
+
<button
|
25
|
+
className="lightbox-nav lightbox-next"
|
26
|
+
onClick={() => onNavigate(1)}
|
27
|
+
>
|
28
|
+
›
|
29
|
+
</button>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
);
|
33
|
+
};
|
34
|
+
|
35
|
+
export default Lightbox;
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import Slider from "react-slick";
|
3
|
+
import "../../styles/galleryslider.scss";
|
4
|
+
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/outline";
|
5
|
+
import fallback from "../../../Images/bg-image.jpg";
|
6
|
+
|
7
|
+
const PrevArrow = ({ onClick }) => (
|
8
|
+
<button className="slick-arrow slick-prev" onClick={onClick}>
|
9
|
+
<ChevronLeftIcon />
|
10
|
+
</button>
|
11
|
+
);
|
12
|
+
|
13
|
+
const NextArrow = ({ onClick }) => (
|
14
|
+
<button className="slick-arrow slick-next" onClick={onClick}>
|
15
|
+
<ChevronRightIcon />
|
16
|
+
</button>
|
17
|
+
);
|
18
|
+
|
19
|
+
const GallerySlider = ({ images, style }) => {
|
20
|
+
const isSingleImage = images && images.length === 1;
|
21
|
+
|
22
|
+
const settings = {
|
23
|
+
dots: true,
|
24
|
+
infinite: !isSingleImage,
|
25
|
+
speed: 500,
|
26
|
+
slidesToShow: 1,
|
27
|
+
slidesToScroll: 1,
|
28
|
+
autoplay: !isSingleImage,
|
29
|
+
autoplaySpeed: 3000,
|
30
|
+
arrows: !isSingleImage,
|
31
|
+
prevArrow: <PrevArrow />,
|
32
|
+
nextArrow: <NextArrow />,
|
33
|
+
centerMode: false,
|
34
|
+
centerPadding: "0px",
|
35
|
+
variableWidth: false,
|
36
|
+
customPaging: () => <button className="custom-dot"></button>,
|
37
|
+
};
|
38
|
+
|
39
|
+
return (
|
40
|
+
<div className="image-slider" style={style}>
|
41
|
+
<Slider {...settings}>
|
42
|
+
{images && images.length > 0 ? (
|
43
|
+
images.map((img, index) => (
|
44
|
+
<div key={index} className="slide">
|
45
|
+
<img src={img} alt={`Slide ${index + 1}`} />
|
46
|
+
</div>
|
47
|
+
))
|
48
|
+
) : (
|
49
|
+
<div className="slide">
|
50
|
+
<img src={fallback} alt="Fallback" />
|
51
|
+
</div>
|
52
|
+
)}
|
53
|
+
</Slider>
|
54
|
+
</div>
|
55
|
+
);
|
56
|
+
};
|
57
|
+
|
58
|
+
export default GallerySlider;
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import StayCard2 from "../StayCard/StayCard2";
|
3
|
+
import "../../styles/propertycard.scss";
|
4
|
+
|
5
|
+
const PropertyCard = ({
|
6
|
+
stayListings = [],
|
7
|
+
gridClass = "",
|
8
|
+
setAllData,
|
9
|
+
isLoading,
|
10
|
+
}) => {
|
11
|
+
const renderCard = (stay) => {
|
12
|
+
return (
|
13
|
+
<StayCard2
|
14
|
+
key={stay?.id}
|
15
|
+
data={stay}
|
16
|
+
setAllData={setAllData}
|
17
|
+
stayListings={stayListings}
|
18
|
+
/>
|
19
|
+
);
|
20
|
+
};
|
21
|
+
|
22
|
+
if (!isLoading && stayListings?.length === 0) {
|
23
|
+
return (
|
24
|
+
<div className="property-card-wrapper">
|
25
|
+
<div className="property-card-container">
|
26
|
+
<div className="property-card-empty">
|
27
|
+
<div className="text-center">
|
28
|
+
<h2 className="no-results-title">No Listings Found</h2>
|
29
|
+
<p className="no-results-text">
|
30
|
+
There are currently no properties listed.
|
31
|
+
</p>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
);
|
37
|
+
}
|
38
|
+
|
39
|
+
return (
|
40
|
+
<div className={`property-card-grid ${gridClass}`}>
|
41
|
+
{stayListings?.map((stay) => renderCard(stay))}
|
42
|
+
</div>
|
43
|
+
);
|
44
|
+
};
|
45
|
+
|
46
|
+
export default PropertyCard;
|
@@ -0,0 +1,178 @@
|
|
1
|
+
import React, { useState } from "react";
|
2
|
+
import "../../styles/bookingform.scss";
|
3
|
+
import ButtonPrimary from "../../shared/Button/ButtonPrimary";
|
4
|
+
import { useFormik } from "formik";
|
5
|
+
import { useNavigate } from "react-router-dom";
|
6
|
+
import moment from "moment";
|
7
|
+
import { useDispatch } from "react-redux";
|
8
|
+
import { searchProperties } from "../../redux/slices/PropertySlice/PropertySlice";
|
9
|
+
import { setSearchMeta } from "../../redux/slices/PropertySlice/Searchslice";
|
10
|
+
|
11
|
+
function BookingForm() {
|
12
|
+
const navigate = useNavigate();
|
13
|
+
const dispatch = useDispatch();
|
14
|
+
const [isLoading, setIsLoading] = useState(false);
|
15
|
+
const [latLng, setLatLng] = useState({ lat: null, lng: null });
|
16
|
+
|
17
|
+
const initialValues = {
|
18
|
+
address: "",
|
19
|
+
arrivalDate: "",
|
20
|
+
departureDate: "",
|
21
|
+
adults: 1,
|
22
|
+
};
|
23
|
+
|
24
|
+
const getLatLngFromAddress = async (address) => {
|
25
|
+
const response = await fetch(
|
26
|
+
`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(
|
27
|
+
address
|
28
|
+
)}`
|
29
|
+
);
|
30
|
+
const data = await response.json();
|
31
|
+
if (data.length > 0) {
|
32
|
+
return {
|
33
|
+
lat: data[0].lat,
|
34
|
+
lng: data[0].lon,
|
35
|
+
};
|
36
|
+
}
|
37
|
+
return { lat: null, lng: null };
|
38
|
+
};
|
39
|
+
|
40
|
+
const onSubmit = async (values) => {
|
41
|
+
setIsLoading(true);
|
42
|
+
try {
|
43
|
+
const { lat, lng } = await getLatLngFromAddress(values.address);
|
44
|
+
setLatLng({ lat, lng });
|
45
|
+
|
46
|
+
const modifiedStartDate = moment(values.arrivalDate).format("YYYY-MM-DD");
|
47
|
+
const modifiedEndDate = moment(values.departureDate).format("YYYY-MM-DD");
|
48
|
+
|
49
|
+
const searchQuery = `q[availability_start_lteq]=${modifiedStartDate}&q[availability_end_gteq]=${modifiedEndDate}&q[guest_number_gteq]=${values.adults}&q[latitude]=${lat}&q[longitude]=${lng}`;
|
50
|
+
|
51
|
+
const action = await dispatch(searchProperties(searchQuery)).unwrap();
|
52
|
+
|
53
|
+
if (action?.success) {
|
54
|
+
dispatch(
|
55
|
+
setSearchMeta({
|
56
|
+
startDate: values.arrivalDate,
|
57
|
+
endDate: values.departureDate,
|
58
|
+
totalGuests: values.adults,
|
59
|
+
address: values.address,
|
60
|
+
latitude: lat,
|
61
|
+
longitude: lng,
|
62
|
+
})
|
63
|
+
);
|
64
|
+
navigate("/listingSearchPage");
|
65
|
+
}
|
66
|
+
} catch (error) {
|
67
|
+
console.error("Search error:", error);
|
68
|
+
} finally {
|
69
|
+
setIsLoading(false);
|
70
|
+
}
|
71
|
+
};
|
72
|
+
|
73
|
+
const formik = useFormik({
|
74
|
+
initialValues,
|
75
|
+
onSubmit,
|
76
|
+
validate: (values) => {
|
77
|
+
const errors = {};
|
78
|
+
if (!values.address) errors.address = "Required";
|
79
|
+
if (!values.arrivalDate) errors.arrivalDate = "Required";
|
80
|
+
if (!values.departureDate) {
|
81
|
+
errors.departureDate = "Required";
|
82
|
+
} else if (values.departureDate <= values.arrivalDate) {
|
83
|
+
errors.departureDate = "Departure must be after arrival";
|
84
|
+
}
|
85
|
+
return errors;
|
86
|
+
},
|
87
|
+
});
|
88
|
+
|
89
|
+
return (
|
90
|
+
<div className="">
|
91
|
+
<div className="container">
|
92
|
+
<section className="booking-section">
|
93
|
+
<div className="booking-table">
|
94
|
+
<form onSubmit={formik.handleSubmit} className="form-fields">
|
95
|
+
<div className="form-row">
|
96
|
+
<div className="input-group">
|
97
|
+
<input
|
98
|
+
type="text"
|
99
|
+
className="form-control"
|
100
|
+
placeholder="Enter Address"
|
101
|
+
name="address"
|
102
|
+
value={formik.values.address}
|
103
|
+
onChange={formik.handleChange}
|
104
|
+
onBlur={formik.handleBlur}
|
105
|
+
/>
|
106
|
+
{formik.touched.address && formik.errors.address && (
|
107
|
+
<div className="error-message">{formik.errors.address}</div>
|
108
|
+
)}
|
109
|
+
</div>
|
110
|
+
<div className="input-group">
|
111
|
+
<input
|
112
|
+
type="date"
|
113
|
+
className="form-control"
|
114
|
+
name="arrivalDate"
|
115
|
+
value={formik.values.arrivalDate}
|
116
|
+
onChange={formik.handleChange}
|
117
|
+
onBlur={formik.handleBlur}
|
118
|
+
min={moment().format("YYYY-MM-DD")}
|
119
|
+
/>
|
120
|
+
{formik.touched.arrivalDate && formik.errors.arrivalDate && (
|
121
|
+
<div className="error-message">
|
122
|
+
{formik.errors.arrivalDate}
|
123
|
+
</div>
|
124
|
+
)}
|
125
|
+
</div>
|
126
|
+
<div className="input-group">
|
127
|
+
<input
|
128
|
+
type="date"
|
129
|
+
className="form-control"
|
130
|
+
name="departureDate"
|
131
|
+
value={formik.values.departureDate}
|
132
|
+
onChange={formik.handleChange}
|
133
|
+
onBlur={formik.handleBlur}
|
134
|
+
min={
|
135
|
+
formik.values.arrivalDate || moment().format("YYYY-MM-DD")
|
136
|
+
}
|
137
|
+
/>
|
138
|
+
{formik.touched.departureDate &&
|
139
|
+
formik.errors.departureDate && (
|
140
|
+
<div className="error-message">
|
141
|
+
{formik.errors.departureDate}
|
142
|
+
</div>
|
143
|
+
)}
|
144
|
+
</div>
|
145
|
+
<div className="input-group">
|
146
|
+
<select
|
147
|
+
className="form-control"
|
148
|
+
name="adults"
|
149
|
+
value={formik.values.adults}
|
150
|
+
onChange={formik.handleChange}
|
151
|
+
onBlur={formik.handleBlur}
|
152
|
+
>
|
153
|
+
<option value={1}>1 Adult</option>
|
154
|
+
<option value={2}>2 Adults</option>
|
155
|
+
<option value={3}>3 Adults</option>
|
156
|
+
<option value={4}>4 Adults</option>
|
157
|
+
<option value={5}>5+ Adults</option>
|
158
|
+
</select>
|
159
|
+
</div>
|
160
|
+
<div className="book-now-container">
|
161
|
+
<ButtonPrimary
|
162
|
+
className="book-now-btn"
|
163
|
+
type="submit"
|
164
|
+
loading={isLoading}
|
165
|
+
>
|
166
|
+
BOOK NOW
|
167
|
+
</ButtonPrimary>
|
168
|
+
</div>
|
169
|
+
</div>
|
170
|
+
</form>
|
171
|
+
</div>
|
172
|
+
</section>
|
173
|
+
</div>
|
174
|
+
</div>
|
175
|
+
);
|
176
|
+
}
|
177
|
+
|
178
|
+
export default BookingForm;
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import Img from "../../../Images/bg-image.jpg";
|
3
|
+
import "../../styles/herosection.scss";
|
4
|
+
|
5
|
+
function HeroSection() {
|
6
|
+
return (
|
7
|
+
<div
|
8
|
+
className="container hero-section"
|
9
|
+
style={{
|
10
|
+
backgroundImage: `url(${Img})`,
|
11
|
+
marginTop: "110px",
|
12
|
+
}}
|
13
|
+
>
|
14
|
+
<div className="hero-overlay" />
|
15
|
+
<div className="hero-content">
|
16
|
+
<p className="hero-subtitle">AWAY FROM MONOTONOUS LIFE</p>
|
17
|
+
<h1 className="hero-title">Relax Your Mind</h1>
|
18
|
+
<p className="hero-desc">
|
19
|
+
If you are looking at blank cassettes on the web, you may be very
|
20
|
+
confused at the <br />
|
21
|
+
difference in price. You may see some for as low as $17 each.
|
22
|
+
</p>
|
23
|
+
<button className="hero-btn">GET STARTED</button>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
);
|
27
|
+
}
|
28
|
+
|
29
|
+
export default HeroSection;
|
@@ -0,0 +1,104 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import GallerySlider from "../GallerySlider/GallerySlider";
|
3
|
+
import { useNavigate } from "react-router-dom";
|
4
|
+
|
5
|
+
const MyPropertiesListing = ({
|
6
|
+
heading = "Explore Travel Experiences",
|
7
|
+
setAllData,
|
8
|
+
stayListings,
|
9
|
+
data,
|
10
|
+
}) => {
|
11
|
+
const navigate = useNavigate();
|
12
|
+
const handleClick = (id) => {
|
13
|
+
navigate(`/listing-stay-detail/${id}`);
|
14
|
+
};
|
15
|
+
console.log("stayListings", stayListings);
|
16
|
+
const handleViewAll = (slug) => navigate(`/property-1/${slug}`);
|
17
|
+
return (
|
18
|
+
<div className="properties-page">
|
19
|
+
<div className="container">
|
20
|
+
<h2>{heading}</h2>
|
21
|
+
<div className="property-grid grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
22
|
+
{stayListings.map((property, index) => (
|
23
|
+
<div key={property.id || index} className="property-card">
|
24
|
+
<div className="card-image-section">
|
25
|
+
{property.property_state && (
|
26
|
+
<div className="discount-badge">
|
27
|
+
{{
|
28
|
+
approved: "Approved",
|
29
|
+
waiting_for_approval: "Waiting for Approval",
|
30
|
+
}[property.property_state] || "Unknown Status"}
|
31
|
+
</div>
|
32
|
+
)}
|
33
|
+
|
34
|
+
<GallerySlider
|
35
|
+
images={property.place_images || []}
|
36
|
+
alt={property.title}
|
37
|
+
style={{ height: "220px" }}
|
38
|
+
/>
|
39
|
+
</div>
|
40
|
+
<div className="card-content">
|
41
|
+
<div className="location-duration">
|
42
|
+
<span className="location">
|
43
|
+
{property.location || property.address}
|
44
|
+
</span>
|
45
|
+
</div>
|
46
|
+
<h3 className="property-title">{property.title}</h3>
|
47
|
+
<p className="description">{property.description}</p>
|
48
|
+
|
49
|
+
<div className="card-footer">
|
50
|
+
<div className="features">
|
51
|
+
{property.property_category && (
|
52
|
+
<span className="feature-tag">
|
53
|
+
{property.property_category}
|
54
|
+
</span>
|
55
|
+
)}
|
56
|
+
{property.property_type && (
|
57
|
+
<span className="feature-tag">
|
58
|
+
{property.freeCancellation
|
59
|
+
? "Free Cancellation"
|
60
|
+
: property.property_type}
|
61
|
+
</span>
|
62
|
+
)}
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<div className="custom-border"></div>
|
68
|
+
|
69
|
+
<div className="price-section">
|
70
|
+
<button
|
71
|
+
className="view-details-btn"
|
72
|
+
onClick={() => handleViewAll(property.slug)}
|
73
|
+
>
|
74
|
+
<svg className="icon" viewBox="0 0 24 24" fill="none">
|
75
|
+
<path
|
76
|
+
stroke="currentColor"
|
77
|
+
strokeWidth="1.5"
|
78
|
+
strokeLinecap="round"
|
79
|
+
strokeLinejoin="round"
|
80
|
+
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
81
|
+
/>
|
82
|
+
</svg>
|
83
|
+
</button>
|
84
|
+
<div className="price-info">
|
85
|
+
<span className="price">
|
86
|
+
From - ${property.price || "500"}
|
87
|
+
</span>
|
88
|
+
<button
|
89
|
+
className="view-details-btn"
|
90
|
+
onClick={() => handleClick(property.slug)}
|
91
|
+
>
|
92
|
+
View Details
|
93
|
+
</button>
|
94
|
+
</div>
|
95
|
+
</div>
|
96
|
+
</div>
|
97
|
+
))}
|
98
|
+
</div>
|
99
|
+
</div>
|
100
|
+
</div>
|
101
|
+
);
|
102
|
+
};
|
103
|
+
|
104
|
+
export default MyPropertiesListing;
|