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.
Files changed (242) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/builds/404error-RVKQJ4S4.digested.jpg +0 -0
  6. data/app/assets/builds/Facebook-5HJUILVR.digested.svg +3 -0
  7. data/app/assets/builds/Google-CZ3UPVSC.digested.svg +6 -0
  8. data/app/assets/builds/application.js +95 -0
  9. data/app/assets/builds/application.js.map +7 -0
  10. data/app/assets/builds/beach-KAZW5GM3.digested.jpg +0 -0
  11. data/app/assets/builds/beach2-3ARC34NS.digested.jpg +0 -0
  12. data/app/assets/builds/beach3-PSTOH5FV.digested.jpg +0 -0
  13. data/app/assets/builds/beach4-PWNRPD3S.digested.jpg +0 -0
  14. data/app/assets/builds/beach5-SBOKKRHF.digested.jpg +0 -0
  15. data/app/assets/builds/beach6-SXZ5Y5AI.digested.jpg +0 -0
  16. data/app/assets/builds/beach7-FNBMFVKK.digested.jpg +0 -0
  17. data/app/assets/builds/beach8-TD7LTRQM.digested.jpg +0 -0
  18. data/app/assets/builds/bg-image-H7UGUMV2.digested.jpg +0 -0
  19. data/app/assets/builds/bgimage-DU3PCXKN.digested.jpg +0 -0
  20. data/app/assets/builds/bundle.css +30914 -0
  21. data/app/assets/builds/bundle.css.map +7 -0
  22. data/app/assets/builds/bundle.js +74569 -0
  23. data/app/assets/builds/bundle.js.map +7 -0
  24. data/app/assets/builds/hotel1-HGBXPKJK.digested.jpg +0 -0
  25. data/app/assets/builds/logo_updated-KQWAXLYL.digested.png +0 -0
  26. data/app/assets/builds/styles.css +6422 -0
  27. data/app/assets/builds/styles.css.map +7 -0
  28. data/app/assets/config/manifest.js +2 -0
  29. data/app/assets/images/favicon.ico +0 -0
  30. data/app/assets/images/stay_commerce/frontend/beach-666122_1280 (1).jpg +0 -0
  31. data/app/assets/images/stay_commerce/frontend/beach-666122_1280.jpg +0 -0
  32. data/app/assets/stylesheets/stay_commerce/frontend/application.css +15 -0
  33. data/app/controllers/stay_commerce/frontend/application_controller.rb +8 -0
  34. data/app/controllers/stay_commerce/frontend/welcome_controller.rb +6 -0
  35. data/app/helpers/stay_commerce/frontend/application_helper.rb +6 -0
  36. data/app/javascript/Images/404error.jpg +0 -0
  37. data/app/javascript/Images/Facebook.svg +3 -0
  38. data/app/javascript/Images/Google.svg +6 -0
  39. data/app/javascript/Images/beach-2245867_1280.jpg +0 -0
  40. data/app/javascript/Images/beach.jpg +0 -0
  41. data/app/javascript/Images/beach2.jpg +0 -0
  42. data/app/javascript/Images/beach3.jpg +0 -0
  43. data/app/javascript/Images/beach4.jpg +0 -0
  44. data/app/javascript/Images/beach5.jpg +0 -0
  45. data/app/javascript/Images/beach6.jpg +0 -0
  46. data/app/javascript/Images/beach7.jpg +0 -0
  47. data/app/javascript/Images/beach8.jpg +0 -0
  48. data/app/javascript/Images/bg-image.jpg +0 -0
  49. data/app/javascript/Images/bgimage.jpg +0 -0
  50. data/app/javascript/Images/blog-1.jpg +0 -0
  51. data/app/javascript/Images/gallery.png +0 -0
  52. data/app/javascript/Images/home 5.jpg +0 -0
  53. data/app/javascript/Images/home1.jpg +0 -0
  54. data/app/javascript/Images/home2.jpg +0 -0
  55. data/app/javascript/Images/home3.jpg +0 -0
  56. data/app/javascript/Images/home6.jpg +0 -0
  57. data/app/javascript/Images/hotel1.jpg +0 -0
  58. data/app/javascript/Images/room1.jpg +0 -0
  59. data/app/javascript/Images/room2.jpg +0 -0
  60. data/app/javascript/Images/room3.jpg +0 -0
  61. data/app/javascript/Images/room4.jpg +0 -0
  62. data/app/javascript/Images/wine-4520213_1280.jpg +0 -0
  63. data/app/javascript/application.js +1 -0
  64. data/app/javascript/react/Api/apiConstants.js +47 -0
  65. data/app/javascript/react/assets/beach-2245867_1280.jpg +0 -0
  66. data/app/javascript/react/assets/logo.png +0 -0
  67. data/app/javascript/react/assets/logo_updated.png +0 -0
  68. data/app/javascript/react/components/AboutUsPage/AboutPage.jsx +41 -0
  69. data/app/javascript/react/components/AboutusFront/About.jsx +37 -0
  70. data/app/javascript/react/components/Accommodation/Accommodation.jsx +32 -0
  71. data/app/javascript/react/components/Accommodation/NormalListing.jsx +50 -0
  72. data/app/javascript/react/components/Accommodation/SpecialListing.jsx +51 -0
  73. data/app/javascript/react/components/Accountpage/AccountInfo.jsx +217 -0
  74. data/app/javascript/react/components/Accountpage/AccountPage.jsx +27 -0
  75. data/app/javascript/react/components/Accountpage/CommonPage.jsx +24 -0
  76. data/app/javascript/react/components/AddNewProperty/CommonLayout.jsx +68 -0
  77. data/app/javascript/react/components/AddNewProperty/Description.jsx +229 -0
  78. data/app/javascript/react/components/AddNewProperty/Details.jsx +234 -0
  79. data/app/javascript/react/components/AddNewProperty/Images.jsx +196 -0
  80. data/app/javascript/react/components/AddNewProperty/Location.jsx +239 -0
  81. data/app/javascript/react/components/AddNewProperty/Room.jsx +1132 -0
  82. data/app/javascript/react/components/AvatarDropdown/AvatarDropDown.jsx +142 -0
  83. data/app/javascript/react/components/BlogDesign/BlogsLatest.jsx +67 -0
  84. data/app/javascript/react/components/ContactUs/Contact.jsx +89 -0
  85. data/app/javascript/react/components/FacilitiesSection/Facilities.jsx +66 -0
  86. data/app/javascript/react/components/FixedNavbar/FixedNav.jsx +88 -0
  87. data/app/javascript/react/components/ForgetPassword/ForgetPassword.jsx +103 -0
  88. data/app/javascript/react/components/Gallery/Gallery.jsx +164 -0
  89. data/app/javascript/react/components/GalleryModalLight/GalleryModalLight.jsx +35 -0
  90. data/app/javascript/react/components/GallerySlider/GallerySlider.jsx +58 -0
  91. data/app/javascript/react/components/Headers/PropertyCard.jsx +46 -0
  92. data/app/javascript/react/components/HeroSectionDesign/BookingForm.jsx +178 -0
  93. data/app/javascript/react/components/HeroSectionDesign/HeroSection.jsx +29 -0
  94. data/app/javascript/react/components/HeroSectionDesign/MyPropertiesListing.jsx +104 -0
  95. data/app/javascript/react/components/HeroSectionDesign/PropertiesPage.jsx +122 -0
  96. data/app/javascript/react/components/HotelListing/Listing.jsx +48 -0
  97. data/app/javascript/react/components/Layout/Layout.js +18 -0
  98. data/app/javascript/react/components/Listing-stay-Detail/AmenitiesFeatures.jsx +58 -0
  99. data/app/javascript/react/components/Listing-stay-Detail/AmenitiesModal.jsx +250 -0
  100. data/app/javascript/react/components/Listing-stay-Detail/ApartmentCard.jsx +120 -0
  101. data/app/javascript/react/components/Listing-stay-Detail/BookingModal.jsx +398 -0
  102. data/app/javascript/react/components/Listing-stay-Detail/CheckoutForm.jsx +296 -0
  103. data/app/javascript/react/components/Listing-stay-Detail/ListingStayDetailPage.jsx +512 -0
  104. data/app/javascript/react/components/Listing-stay-Detail/PropertyDescription.jsx +76 -0
  105. data/app/javascript/react/components/Listing-stay-Detail/PropertyDetailsCard.jsx +62 -0
  106. data/app/javascript/react/components/Listing-stay-Detail/Reviews.jsx +132 -0
  107. data/app/javascript/react/components/Listing-stay-Detail/RoomDescriptionModal.jsx +105 -0
  108. data/app/javascript/react/components/Listing-stay-Detail/Rules.jsx +23 -0
  109. data/app/javascript/react/components/ListingImageGallery/ListingImageGallery.jsx +30 -0
  110. data/app/javascript/react/components/LoginPage/LoginPage.jsx +115 -0
  111. data/app/javascript/react/components/MobileNav/MobileMenu.jsx +47 -0
  112. data/app/javascript/react/components/Navbar/Navbar.jsx +25 -0
  113. data/app/javascript/react/components/Page404/Page404.jsx +30 -0
  114. data/app/javascript/react/components/PropertyListing/MyProperties.jsx +146 -0
  115. data/app/javascript/react/components/PropertyListing/StayBooking/BookingDetails.jsx +178 -0
  116. data/app/javascript/react/components/PropertyListing/StayBooking/MyBooking.jsx +83 -0
  117. data/app/javascript/react/components/ResetPassword/ResetPassword.jsx +117 -0
  118. data/app/javascript/react/components/SignupPage/SignupPage.jsx +185 -0
  119. data/app/javascript/react/components/SmallNavbar/SmallNav.jsx +51 -0
  120. data/app/javascript/react/components/SocialAuth/SocialAuth.jsx +21 -0
  121. data/app/javascript/react/components/StayCard/StayCard.jsx +69 -0
  122. data/app/javascript/react/components/StayCard/StayCard2.jsx +45 -0
  123. data/app/javascript/react/components/StayCard/StayCard3.jsx +45 -0
  124. data/app/javascript/react/components/TestimonialSection/Testimonial.jsx +113 -0
  125. data/app/javascript/react/components/Unauthorized/Unauthorized.jsx +12 -0
  126. data/app/javascript/react/data/jsons/__countryListing.json +201 -0
  127. data/app/javascript/react/packs/App.js +26 -0
  128. data/app/javascript/react/packs/index.jsx +38 -0
  129. data/app/javascript/react/packs/routes/ParentRoute.jsx +14 -0
  130. data/app/javascript/react/packs/routes/Route.jsx +163 -0
  131. data/app/javascript/react/pages/AccommodationList.jsx +21 -0
  132. data/app/javascript/react/pages/Home.jsx +32 -0
  133. data/app/javascript/react/redux/slices/AuthSlice/AuthSlice.jsx +100 -0
  134. data/app/javascript/react/redux/slices/PropertySlice/PropertySlice.jsx +722 -0
  135. data/app/javascript/react/redux/slices/PropertySlice/Searchslice.jsx +36 -0
  136. data/app/javascript/react/redux/slices/UserSlice/UserSlice.jsx +215 -0
  137. data/app/javascript/react/redux/store.js +35 -0
  138. data/app/javascript/react/shared/Avatar/Avatar.jsx +32 -0
  139. data/app/javascript/react/shared/Badge/Badge.jsx +33 -0
  140. data/app/javascript/react/shared/Button/Button.jsx +67 -0
  141. data/app/javascript/react/shared/Button/ButtonPrimary.jsx +11 -0
  142. data/app/javascript/react/shared/Button/ButtonSelect.jsx +9 -0
  143. data/app/javascript/react/shared/Checkbox/Checkbox.jsx +38 -0
  144. data/app/javascript/react/shared/CurrencySymbol.jsx +6 -0
  145. data/app/javascript/react/shared/DateField/CustomDatePicker.jsx +69 -0
  146. data/app/javascript/react/shared/FooterSection/Footer.jsx +75 -0
  147. data/app/javascript/react/shared/FormField/FormField.jsx +75 -0
  148. data/app/javascript/react/shared/FormItem/FormItem.jsx +20 -0
  149. data/app/javascript/react/shared/Input/Input.jsx +27 -0
  150. data/app/javascript/react/shared/Label/Label.jsx +12 -0
  151. data/app/javascript/react/shared/Modal.jsx +20 -0
  152. data/app/javascript/react/shared/NcImage/NcImage.jsx +101 -0
  153. data/app/javascript/react/shared/NcImage/PlaceIcon.jsx +31 -0
  154. data/app/javascript/react/shared/NcImage/placecImageIcon.svg +6 -0
  155. data/app/javascript/react/shared/Select/Select.jsx +20 -0
  156. data/app/javascript/react/styles/404error.scss +58 -0
  157. data/app/javascript/react/styles/ApartmentCard.scss +126 -0
  158. data/app/javascript/react/styles/BookingDetails.scss +457 -0
  159. data/app/javascript/react/styles/Modal.scss +36 -0
  160. data/app/javascript/react/styles/PropertiesPage.scss +219 -0
  161. data/app/javascript/react/styles/RenderSection.scss +480 -0
  162. data/app/javascript/react/styles/about.scss +97 -0
  163. data/app/javascript/react/styles/accountinfo.scss +67 -0
  164. data/app/javascript/react/styles/accountpage.scss +36 -0
  165. data/app/javascript/react/styles/amenitiesfeatures.scss +223 -0
  166. data/app/javascript/react/styles/application.scss +87 -0
  167. data/app/javascript/react/styles/avatar.scss +39 -0
  168. data/app/javascript/react/styles/avatardropdown.scss +57 -0
  169. data/app/javascript/react/styles/badge.scss +90 -0
  170. data/app/javascript/react/styles/blog.scss +100 -0
  171. data/app/javascript/react/styles/bookingform.scss +124 -0
  172. data/app/javascript/react/styles/button.scss +44 -0
  173. data/app/javascript/react/styles/buttonprimary.scss +32 -0
  174. data/app/javascript/react/styles/checkbox.scss +37 -0
  175. data/app/javascript/react/styles/commonlayout.scss +83 -0
  176. data/app/javascript/react/styles/commonpage.scss +51 -0
  177. data/app/javascript/react/styles/contact.scss +173 -0
  178. data/app/javascript/react/styles/customdatepicker.scss +120 -0
  179. data/app/javascript/react/styles/description.scss +21 -0
  180. data/app/javascript/react/styles/details.scss +88 -0
  181. data/app/javascript/react/styles/facilities.scss +131 -0
  182. data/app/javascript/react/styles/fixednavbar.scss +137 -0
  183. data/app/javascript/react/styles/fonts.scss +22 -0
  184. data/app/javascript/react/styles/footer.scss +300 -0
  185. data/app/javascript/react/styles/forgetpassword.scss +68 -0
  186. data/app/javascript/react/styles/formfield.scss +39 -0
  187. data/app/javascript/react/styles/formitem.scss +20 -0
  188. data/app/javascript/react/styles/gallery.scss +142 -0
  189. data/app/javascript/react/styles/gallerymodallight.scss +137 -0
  190. data/app/javascript/react/styles/galleryslider.scss +114 -0
  191. data/app/javascript/react/styles/header.scss +49 -0
  192. data/app/javascript/react/styles/herosection.scss +61 -0
  193. data/app/javascript/react/styles/images.scss +112 -0
  194. data/app/javascript/react/styles/input.scss +58 -0
  195. data/app/javascript/react/styles/label.scss +11 -0
  196. data/app/javascript/react/styles/listing.scss +94 -0
  197. data/app/javascript/react/styles/listingimagegallery.scss +57 -0
  198. data/app/javascript/react/styles/listingstaydetailpage.scss +887 -0
  199. data/app/javascript/react/styles/location.scss +66 -0
  200. data/app/javascript/react/styles/loginpage.scss +150 -0
  201. data/app/javascript/react/styles/mobilemenu.scss +53 -0
  202. data/app/javascript/react/styles/mybooking.scss +104 -0
  203. data/app/javascript/react/styles/myproperty.scss +51 -0
  204. data/app/javascript/react/styles/ncimage.scss +24 -0
  205. data/app/javascript/react/styles/normallisting.scss +95 -0
  206. data/app/javascript/react/styles/property-description.scss +75 -0
  207. data/app/javascript/react/styles/propertycard.scss +48 -0
  208. data/app/javascript/react/styles/propertydetailscard.scss +302 -0
  209. data/app/javascript/react/styles/resetpassword.scss +79 -0
  210. data/app/javascript/react/styles/reviews.scss +185 -0
  211. data/app/javascript/react/styles/room.scss +275 -0
  212. data/app/javascript/react/styles/rooms.scss +0 -0
  213. data/app/javascript/react/styles/select.scss +44 -0
  214. data/app/javascript/react/styles/signuppage.scss +132 -0
  215. data/app/javascript/react/styles/smallnav.scss +94 -0
  216. data/app/javascript/react/styles/socialauth.scss +62 -0
  217. data/app/javascript/react/styles/speciallisting.scss +94 -0
  218. data/app/javascript/react/styles/staycard.scss +77 -0
  219. data/app/javascript/react/styles/staycard2.scss +115 -0
  220. data/app/javascript/react/styles/testimonial.scss +216 -0
  221. data/app/javascript/react/styles/unauthorized.scss +22 -0
  222. data/app/javascript/react/styles/variables.scss +3 -0
  223. data/app/javascript/react/styles/wrapper.scss +4 -0
  224. data/app/javascript/react/utils/formSchema.js +120 -0
  225. data/app/javascript/react/utils/helpers/APIHelper.jsx +55 -0
  226. data/app/javascript/react/utils/helpers/ErrorHandler.js +21 -0
  227. data/app/javascript/react/utils/helpers/InfoHandler.js +15 -0
  228. data/app/javascript/react/utils/helpers/SuccessHandler.js +12 -0
  229. data/app/javascript/react/utils/helpers/isInViewPortIntersectionObserver.jsx +39 -0
  230. data/app/jobs/stay_commerce/frontend/application_job.rb +6 -0
  231. data/app/mailers/stay_commerce/frontend/application_mailer.rb +8 -0
  232. data/app/models/stay_commerce/frontend/application_record.rb +7 -0
  233. data/app/views/layouts/stay_commerce/frontend/application.html.erb +61 -0
  234. data/app/views/stay_commerce/frontend/welcome/index.html.erb +2 -0
  235. data/config/initializers/cors.rb +6 -0
  236. data/config/initializers/devise.rb +359 -0
  237. data/config/routes.rb +11 -0
  238. data/lib/stay_commerce/frontend/engine.rb +14 -0
  239. data/lib/stay_commerce/frontend/version.rb +5 -0
  240. data/lib/stay_commerce/frontend.rb +8 -0
  241. data/lib/tasks/stay_commerce/frontend_tasks.rake +4 -0
  242. metadata +370 -0
@@ -0,0 +1,132 @@
1
+ import React, { useState } from "react";
2
+ import "../../styles/reviews.scss";
3
+ import ButtonPrimary from "../../shared/Button/ButtonPrimary";
4
+
5
+ const Reviews = () => {
6
+ const [visibleCount, setVisibleCount] = useState(2);
7
+
8
+ const reviews = [
9
+ {
10
+ id: 1,
11
+ name: "Luciano S",
12
+ rating: 5.0,
13
+ content:
14
+ "Excellent place to stay! The apartment is beautiful and very cozy. The communication with the coliving team was very good, and they were super attentive to everything I needed. The location is excellent with many cafes and restaurants nearby. I would definitely return!",
15
+ profileImg: "https://i.pravatar.cc/100?img=1",
16
+ },
17
+ {
18
+ id: 2,
19
+ name: "Matias A",
20
+ rating: 5.0,
21
+ content:
22
+ "I stayed in a coliving and the experience was excellent. The apartment was impeccable, with a divine level of detail, well-equipped, and very comfortable. The host was attentive and responded quickly to my questions. The neighborhood is quiet but with many options to eat and drink something. Very recommended!",
23
+ profileImg: "https://i.pravatar.cc/100?img=2",
24
+ },
25
+ {
26
+ id: 3,
27
+ name: "Nico R",
28
+ rating: 5.0,
29
+ content:
30
+ "The experience, overall, was perfect! The place was clean and cozy, the staff were nice, communication was great, and the location was awesome!",
31
+ profileImg: "https://i.pravatar.cc/100?img=3",
32
+ },
33
+ {
34
+ id: 4,
35
+ name: "Mirta C",
36
+ rating: 5.0,
37
+ content:
38
+ "I loved my stay at the coliving! As a digital nomad, finding a place that combines comfort, good internet and a nice community is essential. This place exceeded my expectations.",
39
+ profileImg: "https://i.pravatar.cc/100?img=4",
40
+ },
41
+ ];
42
+
43
+ const ratings = [5, 4, 3, 2, 1];
44
+ const percentages = [100, 0, 0, 0, 0];
45
+
46
+ const showMore = () => {
47
+ setVisibleCount(reviews?.length || 0);
48
+ };
49
+
50
+ const showLess = () => {
51
+ setVisibleCount(3);
52
+ };
53
+
54
+ const visibleReviews = reviews?.slice(0, visibleCount) || [];
55
+ const hasMoreReviews = visibleCount < (reviews?.length || 0);
56
+
57
+ return (
58
+ <div className="reviews-container">
59
+ <h2>Reviews</h2>
60
+ <div className="divider"></div>
61
+
62
+ <div className="reviews-summary">
63
+ <div className="rating-average">
64
+ <h1>5.0</h1>
65
+ <div className="stars">
66
+ {[...Array(5)].map((_, i) => (
67
+ <span key={i} className="star">
68
+
69
+ </span>
70
+ ))}
71
+ </div>
72
+ <p>Excellent!</p>
73
+ <p className="review-count">Based on 19 reviews</p>
74
+ </div>
75
+
76
+ <div className="rating-bars">
77
+ {ratings?.map((rating, index) => (
78
+ <div className="rating-bar" key={rating}>
79
+ <span className="rating-number">{rating} ★</span>
80
+ <div className="progress-container">
81
+ <div
82
+ className="progress-bar"
83
+ style={{ width: `${percentages?.[index] || 0}%` }}
84
+ ></div>
85
+ </div>
86
+ <span className="percentage">{percentages?.[index] || 0} %</span>
87
+ </div>
88
+ ))}
89
+ </div>
90
+ </div>
91
+
92
+ <div className="reviews-list">
93
+ {visibleReviews?.map((review) => (
94
+ <div className="review-item" key={review?.id}>
95
+ <div className="user-info">
96
+ <img
97
+ src={review?.profileImg}
98
+ alt={review?.name}
99
+ className="profile-pic"
100
+ />
101
+ <div className="user-rating">
102
+ <h3>{review?.name}</h3>
103
+ <div className="rating-display">
104
+ <span className="star">★</span>
105
+ <span className="rating-value">{review?.rating}</span>
106
+ </div>
107
+ </div>
108
+ </div>
109
+ <p className="review-content">{review?.content}</p>
110
+ <div className="review-divider"></div>
111
+ </div>
112
+ ))}
113
+
114
+ {(reviews?.length || 0) > 2 && (
115
+ <div className="show-more-container">
116
+ {hasMoreReviews ? (
117
+ <ButtonPrimary className="show-more-btn" onClick={showMore}>
118
+ Show more
119
+ </ButtonPrimary>
120
+ ) : (
121
+ <ButtonPrimary className="show-less-btn" onClick={showLess}>
122
+ Show less
123
+ </ButtonPrimary>
124
+ )}
125
+ </div>
126
+ )}
127
+ </div>
128
+ </div>
129
+ );
130
+ };
131
+
132
+ export default Reviews;
@@ -0,0 +1,105 @@
1
+ import React from "react";
2
+ import { X } from "lucide-react";
3
+
4
+ const RoomDescriptionModal = ({ isOpen, onClose, room }) => {
5
+ const handleBackdropClick = (e) => {
6
+ if (e.target === e.currentTarget) {
7
+ onClose();
8
+ }
9
+ };
10
+
11
+ if (!isOpen || !room?.description) return null;
12
+
13
+ return (
14
+ <div
15
+ className="modal-overlay"
16
+ onClick={handleBackdropClick}
17
+ style={{
18
+ position: "fixed",
19
+ top: 0,
20
+ left: 0,
21
+ right: 0,
22
+ bottom: 0,
23
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
24
+ display: "flex",
25
+ alignItems: "center",
26
+ justifyContent: "center",
27
+ zIndex: 1000,
28
+ padding: "20px",
29
+ }}
30
+ >
31
+ <div
32
+ className="modal-content"
33
+ style={{
34
+ backgroundColor: "white",
35
+ borderRadius: "12px",
36
+ padding: "24px",
37
+ maxWidth: "600px",
38
+ width: "100%",
39
+ maxHeight: "80vh",
40
+ overflowY: "auto",
41
+ position: "relative",
42
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
43
+ }}
44
+ >
45
+ {/* Close Button */}
46
+ <button
47
+ onClick={onClose}
48
+ style={{
49
+ position: "absolute",
50
+ top: "16px",
51
+ right: "16px",
52
+ background: "none",
53
+ border: "none",
54
+ cursor: "pointer",
55
+ padding: "8px",
56
+ borderRadius: "50%",
57
+ display: "flex",
58
+ alignItems: "center",
59
+ justifyContent: "center",
60
+ transition: "background-color 0.2s",
61
+ }}
62
+ onMouseEnter={(e) => (e.target.style.backgroundColor = "#f3f4f6")}
63
+ onMouseLeave={(e) => (e.target.style.backgroundColor = "transparent")}
64
+ >
65
+ <X size={20} />
66
+ </button>
67
+
68
+ {/* Modal Header */}
69
+ <div style={{ marginBottom: "24px", paddingRight: "40px" }}>
70
+ <h2
71
+ style={{
72
+ margin: 0,
73
+ fontSize: "24px",
74
+ fontWeight: "600",
75
+ color: "#111827",
76
+ }}
77
+ >
78
+ Room Description
79
+ </h2>
80
+ <p
81
+ style={{ margin: "8px 0 0 0", color: "#6b7280", fontSize: "14px" }}
82
+ >
83
+ {room?.name}
84
+ </p>
85
+ </div>
86
+
87
+ {/* Description Body */}
88
+ <div>
89
+ <p
90
+ style={{
91
+ fontSize: "16px",
92
+ color: "#374151",
93
+ lineHeight: "1.6",
94
+ whiteSpace: "pre-line",
95
+ }}
96
+ >
97
+ {room?.description}
98
+ </p>
99
+ </div>
100
+ </div>
101
+ </div>
102
+ );
103
+ };
104
+
105
+ export default RoomDescriptionModal;
@@ -0,0 +1,23 @@
1
+ import React from "react";
2
+ import "../../styles/rules.scss";
3
+
4
+ const Rules = ({ propertyData }) => {
5
+ return (
6
+ <div className="policy__wrap">
7
+ <h2 className="policy__title">Property Policies & Rules</h2>
8
+ <div className="policy__divider" />
9
+ <div>
10
+ <h4 className="policy__subtitle">Special Note</h4>
11
+ <ul className="policy__rules-list">
12
+ {propertyData?.additional_rules.map((rule) => (
13
+ <li key={rule?.id} className="policy__rule">
14
+ {rule?.name}
15
+ </li>
16
+ ))}
17
+ </ul>
18
+ </div>
19
+ </div>
20
+ );
21
+ };
22
+
23
+ export default Rules;
@@ -0,0 +1,30 @@
1
+
2
+ import React from "react";
3
+ import { LazyLoadImage } from "react-lazy-load-image-component";
4
+ import { XMarkIcon } from "@heroicons/react/24/outline";
5
+ import "../../styles/listingimagegallery.scss";
6
+
7
+ const ListingImageGallery = ({ images, onClose }) => {
8
+ return (
9
+ <div className="image-gallery-overlay">
10
+ <div className="image-gallery-content">
11
+ <button className="close-button" onClick={onClose}>
12
+ <XMarkIcon className="close-icon" />
13
+ </button>
14
+ <div className="gallery-grid">
15
+ {images?.map((img) => (
16
+ <div key={img?.id} className="gallery-image-wrapper">
17
+ <LazyLoadImage
18
+ src={img?.url}
19
+ alt={`Image ${img?.id}`}
20
+ className="gallery-image"
21
+ />
22
+ </div>
23
+ ))}
24
+ </div>
25
+ </div>
26
+ </div>
27
+ );
28
+ };
29
+
30
+ export default ListingImageGallery;
@@ -0,0 +1,115 @@
1
+ import React, { useState } from "react";
2
+ import { useFormik } from "formik";
3
+ import { Link, useNavigate } from "react-router-dom";
4
+ import { useDispatch, useSelector } from "react-redux";
5
+ import "../../styles/loginpage.scss";
6
+ import { loginSchema } from "../../utils/formSchema";
7
+ import { signIn } from "../../redux/slices/AuthSlice/AuthSlice";
8
+ import { getCurrentUser } from "../../redux/slices/UserSlice/UserSlice";
9
+ import successHandler from "../../utils/helpers/SuccessHandler";
10
+ import SocialAuth from "../SocialAuth/SocialAuth";
11
+ import FormField from "../../shared/FormField/FormField";
12
+ import "../../styles/formfield.scss";
13
+
14
+ const LoginPage = () => {
15
+ const dispatch = useDispatch();
16
+ const navigate = useNavigate();
17
+
18
+ const formik = useFormik({
19
+ initialValues: {
20
+ email: "",
21
+ password: "",
22
+ },
23
+ validationSchema: loginSchema,
24
+ onSubmit: (values, { setSubmitting, resetForm }) => {
25
+ setSubmitting(true);
26
+
27
+ dispatch(signIn(values))
28
+ .unwrap()
29
+ .then((response) => {
30
+ if (response?.access_token) {
31
+ localStorage.setItem("authToken", response.access_token);
32
+ successHandler("Logged in successfully");
33
+ // dispatch(getCurrentUser());
34
+ dispatch(getCurrentUser()).then((res) => {
35
+ localStorage.setItem("user", JSON.stringify(res.payload.data)); // ⬅️ Add this
36
+ });
37
+ navigate("/");
38
+ resetForm();
39
+ } else {
40
+ console.warn("Login failed: ", response);
41
+ }
42
+ })
43
+ .catch((error) => {
44
+ console.warn("Error in login: ", error);
45
+ })
46
+ .finally(() => {
47
+ setSubmitting(false);
48
+ });
49
+ },
50
+ });
51
+
52
+ return (
53
+ <div className="login-container">
54
+ <span className="logos">👑 STAY COMMERCE</span>
55
+ <div className="main-title">
56
+ <h2>Welcome Back</h2>
57
+ <h3>Booking Platform</h3>
58
+ </div>
59
+
60
+ <div className="login-card">
61
+ <div className="log-title">
62
+ <h2>Login</h2>
63
+ </div>
64
+ <div className="social-login">
65
+ <SocialAuth />
66
+ <h4>OR</h4>
67
+ </div>
68
+
69
+ <form className="login-form" onSubmit={formik.handleSubmit}>
70
+ <FormField
71
+ label="Email"
72
+ name="email"
73
+ type="email"
74
+ placeholder="Your Email"
75
+ value={formik.values.email}
76
+ onChange={formik.handleChange}
77
+ onBlur={formik.handleBlur}
78
+ error={formik.touched.email && formik.errors.email}
79
+ />
80
+
81
+ <FormField
82
+ label="Password"
83
+ name="password"
84
+ type="password"
85
+ placeholder="Your Password"
86
+ value={formik.values.password}
87
+ onChange={formik.handleChange}
88
+ onBlur={formik.handleBlur}
89
+ error={formik.touched.password && formik.errors.password}
90
+ />
91
+
92
+ <button
93
+ type="submit"
94
+ className="login-button"
95
+ disabled={formik.isSubmitting}
96
+ >
97
+ {formik.isSubmitting ? "Logging in..." : "Login"}
98
+ </button>
99
+ </form>
100
+
101
+ <span className="forgot-password-link">
102
+ <Link to="/forget-password" className="forgot-password-link__text">
103
+ Forgot password?
104
+ </Link>
105
+ </span>
106
+
107
+ <p className="signup-text">
108
+ Don't have an account? <Link to="/signup">Create an account</Link>
109
+ </p>
110
+ </div>
111
+ </div>
112
+ );
113
+ };
114
+
115
+ export default LoginPage;
@@ -0,0 +1,47 @@
1
+ import React, { useState } from "react";
2
+ import { Link, useLocation } from "react-router-dom";
3
+ import { Menu, X } from "lucide-react";
4
+ import "../../styles/mobilemenu.scss"
5
+
6
+ function MobileMenu() {
7
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
8
+ const location = useLocation();
9
+
10
+ const toggleMenu = () => setIsMenuOpen((prev) => !prev);
11
+
12
+ const navItems = [
13
+ { name: "HOME", path: "/" },
14
+ { name: "ABOUT US", path: "/about-us" },
15
+ { name: "ACCOMMODATION", path: "/accommodation" },
16
+ { name: "GALLERY", path: "/gallery" },
17
+ { name: "BLOG", path: "/blog" },
18
+ { name: "ELEMENT", path: "/element" },
19
+ { name: "CONTACT", path: "/contact" },
20
+ ];
21
+
22
+ return (
23
+ <div className="mobileMenu">
24
+ <div className="hamburger" onClick={toggleMenu}>
25
+ {isMenuOpen ? <X size={28} /> : <Menu size={28} />}
26
+ </div>
27
+
28
+ {/* Dropdown Menu */}
29
+ <div className={`nav ${isMenuOpen ? "open" : ""}`}>
30
+ {navItems.map((item) => (
31
+ <Link
32
+ key={item.name}
33
+ to={item.path}
34
+ className={`Link ${
35
+ location.pathname === item.path ? "active" : ""
36
+ }`}
37
+ onClick={toggleMenu}
38
+ >
39
+ {item.name}
40
+ </Link>
41
+ ))}
42
+ </div>
43
+ </div>
44
+ );
45
+ }
46
+
47
+ export default MobileMenu;
@@ -0,0 +1,25 @@
1
+
2
+ // import React, { useState, useEffect } from "react";
3
+ // import FixedNavbar from "../FixedNavbar/FixedNav";
4
+ // import SmallNavbar from "../SmallNavbar/SmallNav";
5
+ // import "../../styles/fixednavbar.scss";
6
+
7
+ // function Navbar() {
8
+ // const [isScrolled, setIsScrolled] = useState(false);
9
+
10
+ // useEffect(() => {
11
+ // const handleScroll = () => {
12
+ // setIsScrolled(window.scrollY > 50);
13
+ // };
14
+
15
+ // window.addEventListener("scroll", handleScroll);
16
+ // return () => window.removeEventListener("scroll", handleScroll);
17
+ // }, []);
18
+
19
+ // return isScrolled ? <FixedNavbar /> : <SmallNavbar />;
20
+ // }
21
+
22
+
23
+ // export default Navbar;
24
+
25
+
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import Img from "../../../Images/404error.jpg";
3
+ import "../../styles/404error.scss";
4
+ import { Link } from "react-router-dom";
5
+ import Navbar from "../../components/Navbar/Navbar";
6
+ import "../../styles/wrapper.scss";
7
+
8
+ const Page404 = () => (
9
+ <>
10
+
11
+ <div className="page404">
12
+ <div className="wrapper">
13
+ <div className="contain">
14
+ <img src={Img} alt="404 Error" className="page404-image" />
15
+ <h1 className="page404-title">404 - Page Not Found</h1>
16
+ <p className="page404-subtitle">
17
+ Oops! The page you're looking for doesn't exist.
18
+ </p>
19
+ <Link to="/" className="page404-button">
20
+ Return Home Page
21
+ </Link>
22
+ </div>
23
+ </div>
24
+ </div>
25
+
26
+ </>
27
+
28
+ );
29
+
30
+ export default Page404;
@@ -0,0 +1,146 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import { useDispatch } from "react-redux";
3
+
4
+ import PropertyCard from "../Headers/PropertyCard";
5
+ import ButtonPrimary from "../../shared/Button/ButtonPrimary";
6
+ import "../../styles/myproperty.scss";
7
+ import { getallPropertieslisting } from "../../redux/slices/PropertySlice/PropertySlice";
8
+ import PropertiesPage from "../HeroSectionDesign/PropertiesPage";
9
+ import MyPropertiesListing from "../HeroSectionDesign/MyPropertiesListing";
10
+
11
+ const MyProperties = () => {
12
+ const dispatch = useDispatch();
13
+
14
+ const [allData, setAllData] = useState([]);
15
+ const [isLoading, setIsLoading] = useState(true);
16
+ const [isSearchLoading, setIsSearchLoading] = useState(false);
17
+ const [query, setQuery] = useState("");
18
+ const [page, setPage] = useState(1);
19
+ const [totalPages, setTotalPages] = useState(1);
20
+
21
+ const mergedData = (dataToBeMerged) => {
22
+ const newData = dataToBeMerged.map((apiItem) => ({
23
+ id: apiItem?.id,
24
+ title: apiItem?.title,
25
+ place_images: apiItem?.place_images,
26
+ address: `${apiItem?.city}, ${apiItem?.state}`,
27
+ availability_start: apiItem?.availability_start,
28
+ availability_end: apiItem?.availability_end,
29
+ price: apiItem?.price_per_month,
30
+ href: `/listing-stay-detail/${apiItem?.slug}`,
31
+ property_state: apiItem?.property_state || null,
32
+ active: apiItem?.active ?? false,
33
+ property_category: apiItem?.property_category?.name,
34
+ property_type: apiItem?.property_type?.name,
35
+ city: apiItem?.city,
36
+ country: apiItem?.country,
37
+ slug: apiItem?.slug,
38
+ reviewCount: apiItem?.average,
39
+ reviewTotal: apiItem?.count,
40
+ description: apiItem?.description,
41
+ }));
42
+ setAllData(newData);
43
+ };
44
+
45
+ const fetchData = async (currentPage = 1) => {
46
+ setIsLoading(true);
47
+ try {
48
+ const payload = { page: currentPage, query };
49
+ const res = await dispatch(getallPropertieslisting(payload)).unwrap();
50
+ if (res?.properties?.length > 0) {
51
+ mergedData(res.properties);
52
+ setTotalPages(res?.meta?.total_pages || 1);
53
+ } else {
54
+ setAllData([]);
55
+ setTotalPages(1); // Or 0, depending on your UI handling
56
+ }
57
+ } catch (error) {
58
+ console.error("Error fetching properties:", error);
59
+ setAllData([]);
60
+ setTotalPages(1); // Optional fallback
61
+ } finally {
62
+ setIsLoading(false);
63
+ }
64
+ };
65
+
66
+ // // 🔍 Search handler
67
+ // const handleSearch = async () => {
68
+ // if (!query.trim()) return;
69
+ // setIsSearchLoading(true);
70
+ // try {
71
+ // await fetchData(1);
72
+ // setPage(1);
73
+ // } catch (error) {
74
+ // console.error("Search error:", error);
75
+ // } finally {
76
+ // setIsSearchLoading(false);
77
+ // }
78
+ // };
79
+ const handleSearch = async () => {
80
+ if (!query.trim()) return;
81
+ setIsSearchLoading(true);
82
+ try {
83
+ const success = await fetchData(1);
84
+ if (success) {
85
+ setPage(1); // ✅ Set page only when fetch is successful
86
+ }
87
+ } catch (error) {
88
+ console.error("Search error:", error);
89
+ } finally {
90
+ setIsSearchLoading(false);
91
+ }
92
+ };
93
+
94
+ // ⌨️ Handle query input
95
+ const handleSearchChange = (event) => {
96
+ setQuery(event.target.value);
97
+ };
98
+
99
+ // 📦 Auto-fetch on mount or when query is cleared
100
+ useEffect(() => {
101
+ if (query.length === 0) {
102
+ fetchData(1);
103
+ }
104
+ }, [query]);
105
+
106
+ return (
107
+ <div className="myListing-page">
108
+ <div className="myListing-content">
109
+ <div className="myListing-header">
110
+ {/* 🔍 Search Input */}
111
+ {/* <div className="myListing-search">
112
+ <div className="search-bar">
113
+ <input
114
+ type="text"
115
+ value={query}
116
+ onChange={handleSearchChange}
117
+ placeholder="Search By Property Name..."
118
+ className="search-input"
119
+ />
120
+ <ButtonPrimary
121
+ onClick={handleSearch}
122
+ className={`search-button ${
123
+ isSearchLoading || query.trim() === ""
124
+ ? "search-button-disabled"
125
+ : "search-button-active"
126
+ }`}
127
+ disabled={isSearchLoading || query.trim() === ""}
128
+ >
129
+ {isSearchLoading ? "Searching..." : "Search"}
130
+ </ButtonPrimary>
131
+ </div>
132
+ </div> */}
133
+ <div className="myListing-property-cards">
134
+ <MyPropertiesListing
135
+ heading="My Properties"
136
+ stayListings={allData}
137
+ setAllData={setAllData}
138
+ />
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ );
144
+ };
145
+
146
+ export default MyProperties;