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,77 @@
1
+ .stay-card {
2
+ background: #fff;
3
+ border-radius: 12px;
4
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
5
+ overflow: hidden;
6
+ transition: transform 0.2s ease-in-out;
7
+ width: 100%;
8
+
9
+ &:hover {
10
+ transform: translateY(-5px);
11
+ }
12
+
13
+ &__status {
14
+ position: absolute;
15
+ top: 10px;
16
+ left: 10px;
17
+ background: #333;
18
+ color: white;
19
+ padding: 4px 10px;
20
+ border-radius: 6px;
21
+ font-size: 12px;
22
+ font-weight: bold;
23
+ text-transform: capitalize;
24
+ }
25
+
26
+ // &__slider {
27
+ // width: 100%;
28
+ // overflow: hidden;
29
+
30
+ // .gallery-slider {
31
+ // width: 100%;
32
+ // height: 100%;
33
+ // object-fit: cover;
34
+ // }
35
+ // }
36
+
37
+ &__content {
38
+ padding: 15px;
39
+ text-align: left;
40
+ }
41
+
42
+ &__title {
43
+ font-size: 18px;
44
+ font-weight: bold;
45
+ margin-bottom: 10px;
46
+ }
47
+
48
+ &__info {
49
+ display: flex;
50
+ justify-content: space-between;
51
+ font-size: 14px;
52
+ color: #666;
53
+ padding: 4px 0;
54
+ }
55
+ }
56
+
57
+ .stay-card__info-location {
58
+ display: flex;
59
+ align-items: center;
60
+ gap: 5px;
61
+ margin-bottom: 10px;
62
+ }
63
+
64
+ .stay-card__title {
65
+ font-size: 16px;
66
+ line-clamp: 3;
67
+ }
68
+
69
+ .feature-icon-cards {
70
+ height: 15px;
71
+ width: 15px;
72
+ font-weight: 200;
73
+ }
74
+
75
+ .listing-location {
76
+ font-size: 14px;
77
+ }
@@ -0,0 +1,115 @@
1
+ .stay-card-v5 {
2
+
3
+ background: #fff;
4
+ border-radius: 12px;
5
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
6
+ overflow: hidden;
7
+ transition: transform 0.2s ease-in-out;
8
+ width: 100%;
9
+
10
+ &:hover {
11
+ transform: translateY(-5px);
12
+ }
13
+
14
+ .slider-wrapper {
15
+ position: relative;
16
+
17
+
18
+ .status-badge {
19
+ position: absolute;
20
+ top: 0.75rem;
21
+ left: 0.75rem;
22
+ background: rgba(0, 0, 0, 0.5);
23
+ color: white;
24
+ padding: 0.25rem 1rem;
25
+ border-radius: 0.5rem;
26
+ font-size: 0.85rem;
27
+ }
28
+ }
29
+
30
+ .content {
31
+ &.default {
32
+ padding: 1rem;
33
+ }
34
+
35
+ &.small {
36
+ padding: 0.75rem;
37
+ }
38
+
39
+ .info {
40
+ .subtext {
41
+ font-size: 0.85rem;
42
+ color: #666;
43
+ }
44
+
45
+ .title-row {
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 0.5rem;
49
+
50
+ .title {
51
+ font-size: 1rem;
52
+ font-weight: 600;
53
+ text-transform: capitalize;
54
+ }
55
+ }
56
+
57
+ .location {
58
+ display: flex;
59
+ align-items: center;
60
+ gap: 0.5rem;
61
+ color: #666;
62
+
63
+ .icon {
64
+ width: 1.25rem;
65
+ height: 1.25rem;
66
+ }
67
+ }
68
+ }
69
+
70
+ .separator {
71
+ width: 3.5rem;
72
+ border-bottom: 1px solid #eee;
73
+ margin: 0.5rem 0;
74
+ }
75
+
76
+ .price-review {
77
+ display: flex;
78
+ justify-content: space-between;
79
+ align-items: center;
80
+
81
+ .price {
82
+ font-weight: 600;
83
+ }
84
+
85
+ .per-month {
86
+ font-size: 0.85rem;
87
+ color: #888;
88
+ font-weight: 400;
89
+ margin-left: 0.25rem;
90
+ }
91
+ }
92
+
93
+ .meta {
94
+ font-size: 0.85rem;
95
+ color: #666;
96
+
97
+ strong {
98
+ color: #fb923c;
99
+ }
100
+ }
101
+
102
+ .action-buttons {
103
+ display: flex;
104
+ align-items: center;
105
+ gap: 1rem;
106
+ margin-top: 1.5rem;
107
+
108
+ .icon {
109
+ width: 1.25rem;
110
+ height: 1.25rem;
111
+ }
112
+ }
113
+ }
114
+ }
115
+
@@ -0,0 +1,216 @@
1
+
2
+ .testimonial-section {
3
+ background-color: #f8f9fa;
4
+ padding-top: 90px;
5
+ padding-bottom:90px;
6
+ text-align: center;
7
+ overflow: hidden;
8
+ width: 100%;
9
+
10
+ .testimonial-container {
11
+ max-width: 1200px;
12
+ margin: 0 auto;
13
+ padding: 0 15px;
14
+
15
+ h2 {
16
+ font-size: 2.4rem;
17
+ font-weight: 700;
18
+ color: #333;
19
+ margin-bottom: 15px;
20
+ position: relative;
21
+ display: inline-block;
22
+
23
+ }
24
+
25
+ .subtitle {
26
+ font-size: 16px;
27
+ color: #777;
28
+ max-width: 800px;
29
+ margin: 0 auto 50px;
30
+ }
31
+ }
32
+
33
+ .testimonial-slider {
34
+ margin: 0 auto 30px;
35
+ position: relative;
36
+
37
+ .slick-list {
38
+ overflow: hidden;
39
+ margin: 0 -15px;
40
+ }
41
+
42
+ .slick-track {
43
+ display: flex;
44
+ align-items: stretch;
45
+ }
46
+
47
+ .slick-slide{
48
+ height: auto;
49
+ margin: 0 15px;
50
+ float: left;
51
+ min-height: 1px;
52
+ display: flex !important;
53
+ justify-content: center;
54
+ align-items: center;
55
+
56
+ & > div {
57
+ width: 100%;
58
+ display: flex;
59
+ height: 100%;
60
+ }
61
+ }
62
+ .slick-slide[aria-hidden="true"] {
63
+ opacity: 0.5;
64
+ pointer-events: none;
65
+ }
66
+
67
+ .slick-dots {
68
+ position: absolute;
69
+ bottom: -30px;
70
+ list-style: none;
71
+ display: flex !important;
72
+ justify-content: center;
73
+ padding: 0;
74
+ margin: 0;
75
+ width: 100%;
76
+
77
+ li {
78
+ margin: 0 5px;
79
+ padding: 0;
80
+
81
+ &.slick-active .custom-dot {
82
+ background-color: #ffc107;
83
+ }
84
+ }
85
+
86
+ .custom-dot {
87
+ width: 13px;
88
+ height: 13px;
89
+ background-color: #ccc;
90
+ display: block;
91
+ cursor: pointer;
92
+ }
93
+ }
94
+
95
+ .custom-prev-arrow,
96
+ .custom-next-arrow {
97
+ position: absolute;
98
+ top: 50%;
99
+ transform: translateY(-50%);
100
+ z-index: 1;
101
+ width: 40px;
102
+ height: 40px;
103
+ background-color: rgba(255, 255, 255, 0.8);
104
+ color: #ffc107;
105
+ border: none;
106
+ border-radius: 50%;
107
+ font-size: 20px;
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ cursor: pointer;
112
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
113
+
114
+ &:hover {
115
+ background-color: #ffc107;
116
+ color: white;
117
+ }
118
+ }
119
+
120
+ .custom-prev-arrow {
121
+ left: -20px;
122
+ }
123
+
124
+ .custom-next-arrow {
125
+ right: -20px;
126
+ }
127
+ }
128
+
129
+ .testimonial-card {
130
+ background-color: #fff;
131
+ border-radius: 5px;
132
+ padding: 12px;
133
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
134
+ display: flex;
135
+ flex-direction: row;
136
+ align-items: center;
137
+ position: relative;
138
+ margin: 40px auto;
139
+ text-align: left;
140
+ justify-content: center;
141
+ gap: 24px;
142
+ flex-wrap: wrap;
143
+ max-width: 1000px;
144
+ flex: 0 0 100%;
145
+
146
+ .client-image {
147
+ width: 80px;
148
+ height: 80px;
149
+ border-radius: 50%;
150
+ overflow: hidden;
151
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
152
+ border: 3px solid #fff;
153
+ position: relative;
154
+ order: 1;
155
+
156
+ img {
157
+ width: 100%;
158
+ height: 100%;
159
+ object-fit: cover;
160
+ }
161
+ }
162
+
163
+ .testimonial-content{
164
+ width: 100%;
165
+ max-width: 400px;
166
+ text-align: left;
167
+ order: 2;
168
+ }
169
+
170
+ .client-quote {
171
+ font-size: 16px;
172
+ line-height: 1.6;
173
+ color: #666;
174
+ margin-top: 20px;
175
+ margin-bottom: 20px;
176
+ font-style: italic;
177
+ }
178
+
179
+ .client-name {
180
+ text-align: left;
181
+ width: 100%;
182
+ color: #333;
183
+ font-size: 18px;
184
+ font-weight: 700;
185
+ }
186
+
187
+ .client-rating {
188
+ margin-bottom: 5px;
189
+ display: flex;
190
+ justify-content: flex-start;
191
+
192
+ .star {
193
+ color: #ffc107;
194
+ font-size: 18px;
195
+ margin: 0 2px;
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+
202
+ @media (max-width: 768px) {
203
+ .testimonial-card {
204
+ flex-direction: column;
205
+ align-items: center;
206
+ text-align: center;
207
+ .client-image {
208
+ order: 1;
209
+ }
210
+ .testimonial-content {
211
+ order: 2;
212
+ text-align: center;
213
+ }
214
+ }
215
+ }
216
+
@@ -0,0 +1,22 @@
1
+ // pages/Unauthorized.scss
2
+
3
+ .unauthorized {
4
+ padding: 2rem;
5
+ text-align: center;
6
+ margin-top: 12rem;
7
+ margin-bottom:12rem;
8
+
9
+
10
+ &__title {
11
+ font-size: 2rem;
12
+ font-weight: bold;
13
+ margin-bottom: 1rem;
14
+ color: #e74c3c;
15
+ }
16
+
17
+ &__message {
18
+ font-size: 1rem;
19
+ color: #555;
20
+ }
21
+ }
22
+
@@ -0,0 +1,3 @@
1
+
2
+ // Variables
3
+ $primary-color: #db7c0b;
@@ -0,0 +1,4 @@
1
+ .wrapper{
2
+ margin-left:40px;
3
+ margin-right:40px;
4
+ }
@@ -0,0 +1,120 @@
1
+ import * as Yup from "yup";
2
+
3
+ export const loginSchema = Yup.object().shape({
4
+ email: Yup.string().email("Invalid email").required("Email is required"),
5
+ password: Yup.string().min(6, "Password must be at least 6 characters").required("Password is required"),
6
+ });
7
+
8
+ export const signupSchema = Yup.object().shape({
9
+ first_name: Yup.string()
10
+ .matches(
11
+ /^(?!.*\s{2})[A-Za-z]+(?: [A-Za-z]+)*$/,
12
+ "First name must contain only letters."
13
+ )
14
+ .required("First name is required"),
15
+ last_name: Yup.string()
16
+ .matches(
17
+ /^(?!.*\s{2})[A-Za-z]+(?: [A-Za-z]+)*$/,
18
+ "First name must contain only letters."
19
+ )
20
+ .required("Last name is required"),
21
+ email: Yup.string()
22
+ .email("Invalid email address")
23
+ .matches(
24
+ /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
25
+ "Email must have a valid domain"
26
+ )
27
+ .required("Email is required"),
28
+ password: Yup.string()
29
+ .min(6, "Password is too short")
30
+ .matches(
31
+ /^(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])/,
32
+ "Password must contain at least one uppercase letter, one number, and one special character"
33
+ )
34
+ .required("Password is required"),
35
+ });
36
+
37
+
38
+ export const UpdateUser = Yup.object().shape({
39
+ first_name: Yup.string()
40
+ .matches(
41
+ /^(?!.*\s{2})[A-Za-z]+(?: [A-Za-z]+)*$/,
42
+ "First name must contain only letters."
43
+ )
44
+ .required("First name is required"),
45
+ last_name: Yup.string()
46
+ .matches(
47
+ /^(?!.*\s{2})[A-Za-z]+(?: [A-Za-z]+)*$/,
48
+ "First name must contain only letters."
49
+ )
50
+ .required("Last name is required"),
51
+ email: Yup.string()
52
+ .email("Invalid email address")
53
+ .matches(
54
+ /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
55
+ "Email must have a valid domain"
56
+ )
57
+ .required("Email is required"),
58
+ date_of_birth: Yup.date()
59
+ // .max(new Date(Date.now() - 86400000), "Date of birth invalid")
60
+ .required("Date of birth is required"),
61
+ phone: Yup.string()
62
+ .matches(/^\+?[0-9]{1,4}[^\s]+$/, "Phone number must not be empty.")
63
+ .required("Phone number is required"),
64
+ about_me: Yup.string()
65
+ .required("About me is required")
66
+ .test("min-chars", "Must be at least 100 characters.", function (value) {
67
+ const charCount = value ? value.trim().length : 0;
68
+ return charCount >= 100;
69
+ })
70
+ .test("max-words", "Must be at most 150 words.", function (value) {
71
+ const wordCount = value ? value.trim().split(/\s+/).length : 0;
72
+ return wordCount <= 50;
73
+ }),
74
+
75
+ country: Yup.string()
76
+ .matches(
77
+ /^(?! )[^\s]*(?<! )$/,
78
+ "Country ID must not start or end with whitespace and may contain spaces between characters"
79
+ )
80
+ .required("Identification number is required"),
81
+
82
+ });
83
+
84
+ export const passwordSchema = Yup.object({
85
+ new_password: Yup.string()
86
+ .min(8, "Password must be at least 8 characters long")
87
+ .matches(
88
+ /^(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])/,
89
+ "Password must contain at least one uppercase letter, one number, and one special character"
90
+ )
91
+ .required("New password is required"),
92
+ confirm_password: Yup.string()
93
+ .oneOf([Yup.ref("new_password"), undefined], "Passwords must match")
94
+ .required("Confirm password is required"),
95
+ });
96
+
97
+ export const descriptionSchema = Yup.object({
98
+ title: Yup.string().required("Title is required"),
99
+ property_category: Yup.string().required("Property category is required"),
100
+ property_type: Yup.string().required("Property type is required"),
101
+ country: Yup.string().required("Country is required"),
102
+ city: Yup.string().required("City is required"),
103
+ address: Yup.string().required("Address is required"),
104
+ description: Yup.string().required("Description is required"),
105
+ });
106
+
107
+ export const emailValidationSchema = Yup.object({
108
+ email: Yup.string()
109
+ .email("Invalid email address")
110
+ .required("Email is required"),
111
+ });
112
+
113
+ export const editValidationSchema= Yup.object({
114
+ password: Yup.string()
115
+ .min(6, "Password must be at least 6 characters")
116
+ .required("Password is required"),
117
+ confirmPassword: Yup.string()
118
+ .oneOf([Yup.ref("password")], "Passwords must match")
119
+ .required("Confirm password is required"),
120
+ })
@@ -0,0 +1,55 @@
1
+ import axios from "axios";
2
+ import ErrorHandler from "./ErrorHandler";
3
+ import { logout } from "../../redux/slices/AuthSlice/AuthSlice";
4
+ import { API_BASE_URL } from "../../Api/apiConstants";
5
+
6
+ const API = axios.create({
7
+ baseURL: API_BASE_URL,
8
+ headers: {
9
+ "Content-Type": "application/json",
10
+ },
11
+ });
12
+
13
+ API.interceptors.request.use(
14
+ async (config) => {
15
+ const token = localStorage.getItem("authToken"); // Fetch token from localStorage
16
+ if (token) {
17
+ config.headers["Authorization"] = `Bearer ${token}`; // Set the Authorization header
18
+ }
19
+ if (config.data instanceof FormData) {
20
+ config.headers["Content-Type"] = "multipart/form-data"; // Set the content type for file uploads
21
+ }
22
+ return config;
23
+ },
24
+ (error) => {
25
+ return Promise.reject(error);
26
+ }
27
+ );
28
+
29
+ // Response interceptor to handle errors globally
30
+ API.interceptors.response.use(
31
+ (response) => response.data, // Return response data directly
32
+ (error) => {
33
+ const statusCode = error.response?.status;
34
+ if (statusCode === 401 || statusCode === 403) {
35
+ // Handle unauthorized or forbidden (e.g., invalid or expired token)
36
+ ErrorHandler("Unauthorized Error!");
37
+
38
+ const preserveKey = "theme"; // The key you want to preserve
39
+ const preserveValue = localStorage.getItem(preserveKey); // Store the value of the key
40
+ if (preserveValue) {
41
+ localStorage.setItem(preserveKey, preserveValue);
42
+ }
43
+
44
+ setTimeout(() => {
45
+ import("../../redux/store").then(({ store }) => {
46
+ store.dispatch(logout()); // Dynamically import store
47
+ window.location.href = "/login";
48
+ });
49
+ }, 2000);
50
+ }
51
+ return Promise.reject(error);
52
+ }
53
+ );
54
+
55
+ export default API;
@@ -0,0 +1,21 @@
1
+ import { toast } from "react-toastify";
2
+ import "react-toastify/dist/ReactToastify.css";
3
+
4
+ // Custom Error Handler for Axios and general errors
5
+ export default function errorHandler(error) {
6
+ const response = error?.response;
7
+
8
+ if (response) {
9
+ if (response.status !== 404) {
10
+ toast.error(response.data?.error || response.data?.message || "An error occurred.", {
11
+ position: "top-right",
12
+ autoClose: 5000,
13
+ });
14
+ }
15
+ } else {
16
+ toast.error("Internal server error", {
17
+ position: "top-right",
18
+ autoClose: 5000,
19
+ });
20
+ }
21
+ }
@@ -0,0 +1,15 @@
1
+ import { toast } from 'react-toastify';
2
+ import 'react-toastify/dist/ReactToastify.css';
3
+
4
+ // Custom Info Handler
5
+ export default function InfoHandler(message, autoClose = 5000) {
6
+ toast.info(message, {
7
+ position: 'top-right',
8
+ autoClose: autoClose, // Default auto close time is 5000 ms, can be customized
9
+ hideProgressBar: false,
10
+ closeOnClick: true,
11
+ pauseOnHover: true,
12
+ draggable: true,
13
+ progress: undefined,
14
+ });
15
+ }
@@ -0,0 +1,12 @@
1
+ import { toast } from "react-toastify";
2
+
3
+ export default function successHandler(message, autoClose = 5000) {
4
+ toast.success(message, {
5
+ position: "top-right",
6
+ autoClose,
7
+ hideProgressBar: false,
8
+ closeOnClick: true,
9
+ pauseOnHover: true,
10
+ draggable: true,
11
+ });
12
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @param {Object} params
3
+ * @param {() => void} params.callback - Function to call when element is in view
4
+ * @param {HTMLElement|null} params.target - DOM element to observe
5
+ * @param {IntersectionObserverInit} [params.options] - Intersection observer options
6
+ * @param {boolean} params.freezeOnceVisible - Whether to stop observing after visible
7
+ */
8
+ const checkInViewIntersectionObserver = ({
9
+ target,
10
+ options = { root: null, rootMargin: `0%`, threshold: 0 },
11
+ callback,
12
+ freezeOnceVisible = false,
13
+ }) => {
14
+ const _funCallback = (entries, observer) => {
15
+ entries.forEach((entry) => {
16
+ if (entry.isIntersecting) {
17
+ callback();
18
+ if (freezeOnceVisible) {
19
+ observer.unobserve(entry.target);
20
+ }
21
+ }
22
+ });
23
+ };
24
+
25
+ if (typeof window.IntersectionObserver === "undefined") {
26
+ console.error(
27
+ "window.IntersectionObserver === undefined! => Your Browser is Not supported"
28
+ );
29
+ return;
30
+ }
31
+
32
+ const observer = new IntersectionObserver(_funCallback, options);
33
+ if (target) {
34
+ observer.observe(target);
35
+ }
36
+ };
37
+
38
+ export default checkInViewIntersectionObserver;
39
+