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,722 @@
1
+ import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
2
+ import API from "../../../utils/helpers/APIHelper";
3
+ import { ENDPOINTS } from "../../../Api/apiConstants";
4
+ import ErrorHandler from "../../../utils/helpers/ErrorHandler";
5
+ import { PhilippinePesoIcon } from "lucide-react";
6
+ PhilippinePesoIcon;
7
+
8
+ export const createProperties = createAsyncThunk(
9
+ "property/createProperties",
10
+ async (payload, { rejectWithValue }) => {
11
+ try {
12
+ const token = localStorage.getItem("authToken");
13
+
14
+ if (!token) throw new Error("No authentication token found");
15
+ const response = await API.post(ENDPOINTS.CREATE_PROPERTIES, payload, {
16
+ headers: {
17
+ Authorization: `Bearer ${token}`,
18
+ "Content-Type": "application/json",
19
+ },
20
+ });
21
+
22
+ return response;
23
+ } catch (error) {
24
+ ErrorHandler(error);
25
+ return rejectWithValue(error.response?.data || error.message);
26
+ }
27
+ }
28
+ );
29
+
30
+ export const updateProperties = createAsyncThunk(
31
+ "property/updateProperties",
32
+ async (payload, { rejectWithValue }) => {
33
+ try {
34
+ const token = localStorage.getItem("authToken");
35
+ if (!token) throw new Error("No authentication token found");
36
+ const response = await API.put(
37
+ `${ENDPOINTS.UPDATE_PROPERTIES}/${payload?.property?.id}`,
38
+ payload.property,
39
+ {
40
+ headers: {
41
+ Authorization: `Bearer ${token}`,
42
+ "Content-Type": "application/json",
43
+ },
44
+ }
45
+ );
46
+
47
+ return response; // Return only the data if needed
48
+ } catch (error) {
49
+ ErrorHandler(error);
50
+ return rejectWithValue(error.response?.data || error.message);
51
+ }
52
+ }
53
+ );
54
+
55
+ export const getUserBookingsDetails = createAsyncThunk(
56
+ "properties/bookings",
57
+ async ({ page }, { rejectWithValue }) => {
58
+ try {
59
+ const response = await API.get(ENDPOINTS.GET_BOOKING_DEATAILS(page));
60
+ return response;
61
+ } catch (error) {
62
+ ErrorHandler(error);
63
+ return rejectWithValue(error);
64
+ }
65
+ }
66
+ );
67
+
68
+ export const getHostBookingsDetails = createAsyncThunk(
69
+ "properties/hostBookings",
70
+ async ({ page }, { rejectWithValue }) => {
71
+ try {
72
+ const response = await API.get(ENDPOINTS.HOST_BOOKING_DETAILS(page));
73
+ return response;
74
+ } catch (error) {
75
+ ErrorHandler(error);
76
+ return rejectWithValue(error);
77
+ }
78
+ }
79
+ );
80
+
81
+ export const uploadImageProperties = createAsyncThunk(
82
+ "property/uploadImageProperties",
83
+ async (formData, { rejectWithValue }) => {
84
+ try {
85
+ let propertyId = formData.get("property[id]");
86
+
87
+ if (!propertyId) {
88
+ propertyId = formData.get("id");
89
+ }
90
+
91
+ if (!propertyId) {
92
+ return rejectWithValue("Property ID is required");
93
+ }
94
+
95
+ const response = await API.put(
96
+ `${ENDPOINTS.UPDATE_PROPERTIES}/${propertyId}`,
97
+ formData,
98
+ {
99
+ headers: {
100
+ "Content-Type": "multipart/form-data",
101
+ },
102
+ }
103
+ );
104
+ return { ...response.data, success: true };
105
+ } catch (error) {
106
+ ErrorHandler(error);
107
+ return rejectWithValue(error.response?.data || error.message);
108
+ }
109
+ }
110
+ );
111
+
112
+ export const getallupdateProperties = createAsyncThunk(
113
+ "property/PropertyToEdit",
114
+ async (payload, { rejectWithValue }) => {
115
+ try {
116
+ const response = await API.get(
117
+ `${ENDPOINTS.GET_ALL_UPDATE_PROPERTY_DETAILS}/${payload?.propertyId}`
118
+ );
119
+ return response.property; // ✅ Return only the nested property
120
+ } catch (error) {
121
+ ErrorHandler(error);
122
+ return rejectWithValue(error.response?.data || error.message);
123
+ }
124
+ }
125
+ );
126
+
127
+ export const getPropertyCategories = createAsyncThunk(
128
+ "properties/propertiesCategories",
129
+ async (_, { rejectWithValue }) => {
130
+ try {
131
+ const token = localStorage.getItem("authToken");
132
+ if (!token) throw new Error("No authentication token found");
133
+ const response = await API.get(ENDPOINTS.PROPERTY_CATEGORY, {
134
+ headers: {
135
+ Authorization: `Bearer ${token}`,
136
+ },
137
+ });
138
+ return response.data;
139
+ } catch (error) {
140
+ ErrorHandler(error);
141
+ return rejectWithValue(error.response?.data || error.message);
142
+ }
143
+ }
144
+ );
145
+
146
+ export const getPropertyType = createAsyncThunk(
147
+ "properties/propertyTypes",
148
+ async (_, { rejectWithValue }) => {
149
+ try {
150
+ const token = localStorage.getItem("authToken");
151
+ if (!token) throw new Error("No authentication token found");
152
+ const response = await API.get(ENDPOINTS.GET_ALL_PROPERTY_TYPE, {
153
+ headers: {
154
+ Authorization: `Bearer ${token}`,
155
+ },
156
+ });
157
+ return response.data;
158
+ } catch (error) {
159
+ ErrorHandler(error);
160
+ return rejectWithValue(error.response?.data || error.message);
161
+ }
162
+ }
163
+ );
164
+
165
+ export const getCard = createAsyncThunk(
166
+ "payment/getCard",
167
+ async (_, { rejectWithValue }) => {
168
+ try {
169
+ const token = localStorage.getItem("authToken");
170
+ if (!token) throw new Error("No authentication token found");
171
+
172
+ const response = await fetch(
173
+ "http://localhost:5000/stay/api/v1/credit_cards",
174
+ {
175
+ headers: {
176
+ "Content-Type": "application/json",
177
+ Authorization: `Bearer ${token}`,
178
+ },
179
+ }
180
+ );
181
+
182
+ const data = await response.json();
183
+ if (response.status === 422 && data?.error === "No credit cards found") {
184
+ return null;
185
+ }
186
+
187
+ if (!response.ok)
188
+ throw new Error(data.message || "Failed to fetch cards");
189
+
190
+ return data.data;
191
+ } catch (error) {
192
+ return rejectWithValue(error?.message || "An unexpected error occurred");
193
+ }
194
+ }
195
+ );
196
+
197
+ export const searchProperties = createAsyncThunk(
198
+ "properties/searchProperties",
199
+ async (searchQuery, { rejectWithValue }) => {
200
+ try {
201
+ const response = await API.get(ENDPOINTS.SEARCH_PROPERTIES(searchQuery));
202
+ return {
203
+ success: true,
204
+ data: response.data,
205
+ };
206
+ } catch (error) {
207
+ if (error.response && error.response.status === 404) {
208
+ toast.error(error.response.data.error || error.response.data.message, {
209
+ position: "top-right",
210
+ });
211
+ return rejectWithValue(error.response.data);
212
+ }
213
+ ErrorHandler(error);
214
+ return rejectWithValue(error.message);
215
+ }
216
+ }
217
+ );
218
+
219
+ export const getPaymentmethods = createAsyncThunk(
220
+ "payment/getCard",
221
+ async (_, thunkAPI) => {
222
+ try {
223
+ const token = localStorage.getItem("authToken");
224
+ const response = await fetch(
225
+ "http://localhost:5000/stay/api/v1/payments/payment_method",
226
+ {
227
+ headers: {
228
+ "Content-Type": "application/json",
229
+ Authorization: `Bearer ${token}`,
230
+ },
231
+ }
232
+ );
233
+ const data = await response.json();
234
+ if (!response.ok) throw new Error(data.message);
235
+ return data.data;
236
+ } catch (error) {
237
+ ErrorHandler(error);
238
+ return rejectWithValue(
239
+ error.response?.data || error.message || "An error occurred"
240
+ );
241
+ }
242
+ }
243
+ );
244
+
245
+ export const deleteCard = createAsyncThunk(
246
+ "payment/deleteCard",
247
+ async (id, thunkAPI) => {
248
+ try {
249
+ const token = localStorage.getItem("authToken");
250
+ const response = await fetch(
251
+ `http://localhost:5000/stay/api/v1/credit_cards/${id}`,
252
+ {
253
+ method: "DELETE",
254
+ headers: {
255
+ "Content-Type": "application/json",
256
+ Authorization: `Bearer ${token}`,
257
+ },
258
+ body: JSON.stringify({ credit_card: { id } }),
259
+ }
260
+ );
261
+ const data = await response.json();
262
+ if (!response.ok) throw new Error(data.message);
263
+ return id;
264
+ } catch (error) {
265
+ ErrorHandler(error);
266
+ return rejectWithValue(
267
+ error.response?.data || error.message || "An error occurred"
268
+ );
269
+ }
270
+ }
271
+ );
272
+
273
+ export const saveCard = createAsyncThunk(
274
+ "payment/saveCard",
275
+ async (cardDetails, thunkAPI) => {
276
+ try {
277
+ const token = localStorage.getItem("authToken");
278
+ const response = await fetch(
279
+ "http://localhost:5000/stay/api/v1/credit_cards",
280
+ {
281
+ method: "POST",
282
+ headers: {
283
+ "Content-Type": "application/json",
284
+ Authorization: `Bearer ${token}`,
285
+ },
286
+ body: JSON.stringify({
287
+ credit_card: {
288
+ cc_number: cardDetails.cc_number,
289
+ month: cardDetails.month,
290
+ year: cardDetails.year,
291
+ card_token: cardDetails.card_token,
292
+ },
293
+ }),
294
+ }
295
+ );
296
+ const data = await response.json();
297
+ if (!response.ok) throw new Error(data.message);
298
+ return data.data;
299
+ } catch (error) {
300
+ return thunkAPI.rejectWithValue(
301
+ error?.response?.data || error.message || "An error occurred"
302
+ );
303
+ }
304
+ }
305
+ );
306
+
307
+ export const createPayment = createAsyncThunk(
308
+ "payment/createPayment",
309
+ async ({ bookingId, paymentMethodId }, thunkAPI) => {
310
+ const token = localStorage.getItem("authToken");
311
+ const response = await fetch("http://localhost:5000/stay/api/v1/payments", {
312
+ method: "POST",
313
+ headers: {
314
+ "Content-Type": "application/json",
315
+ Authorization: `Bearer ${token}`,
316
+ },
317
+ body: JSON.stringify({
318
+ booking_id: bookingId.toString(),
319
+ confirm: "true",
320
+ currency: "usd",
321
+ payment_method_id: paymentMethodId,
322
+ }),
323
+ });
324
+ const data = await response.json();
325
+ if (!response.ok) throw new Error(data.message);
326
+ return data;
327
+ }
328
+ );
329
+
330
+ export const confirmBooking = createAsyncThunk(
331
+ "booking/confirmBooking",
332
+ async ({ bookingId, paymentMethodId, amount }, thunkAPI) => {
333
+ const token = localStorage.getItem("authToken");
334
+ const response = await fetch(
335
+ `http://localhost:5000/stay/api/v1/bookings/${bookingId}`,
336
+ {
337
+ method: "PUT",
338
+ headers: {
339
+ "Content-Type": "application/json",
340
+ Authorization: `Bearer ${token}`,
341
+ },
342
+ body: JSON.stringify({
343
+ booking: {
344
+ status: "confirmed",
345
+ payments_attributes: [
346
+ {
347
+ payment_method_id: paymentMethodId,
348
+ amount: amount,
349
+ state: "paid",
350
+ },
351
+ ],
352
+ },
353
+ }),
354
+ }
355
+ );
356
+
357
+ const data = await response.json();
358
+ if (!response.ok)
359
+ throw new Error(data.message || "Failed to confirm booking");
360
+ return data;
361
+ }
362
+ );
363
+
364
+ export const getallPropertieslisting = createAsyncThunk(
365
+ "property/getAllPropertiesListing",
366
+ async (payload, { rejectWithValue }) => {
367
+ try {
368
+ const token = localStorage.getItem("authToken");
369
+ if (!token) throw new Error("No authentication token found");
370
+
371
+ // Build the URL with query parameters
372
+ let url = ENDPOINTS.GET_PROPERTY_Listing;
373
+
374
+ // Add query parameters
375
+ const queryParams = [];
376
+ if (payload?.page) {
377
+ queryParams.push(`page=${payload.page}`);
378
+ }
379
+ if (payload?.query) {
380
+ queryParams.push(`query=${encodeURIComponent(payload.query)}`);
381
+ }
382
+
383
+ // Append query parameters if they exist
384
+ if (queryParams.length > 0) {
385
+ url += `?${queryParams.join("&")}`;
386
+ }
387
+
388
+ const response = await API.get(url);
389
+ return response;
390
+ } catch (error) {
391
+ ErrorHandler(error);
392
+ return rejectWithValue(error.response?.data || error.message);
393
+ }
394
+ }
395
+ );
396
+
397
+ export const getAmenitiesProperty = createAsyncThunk(
398
+ "properties/amenitiesProperty",
399
+ async (_, { rejectWithValue }) => {
400
+ try {
401
+ const response = await API.get(ENDPOINTS.AMENITIES_PROPERTIES);
402
+ return response; // Adjust if your API wraps this in .data
403
+ } catch (error) {
404
+ ErrorHandler(error);
405
+ return rejectWithValue(error.response?.data || error.message);
406
+ }
407
+ }
408
+ );
409
+
410
+ export const getFeaturesProperty = createAsyncThunk(
411
+ "properties/featuresCategories",
412
+ async (_, { rejectWithValue }) => {
413
+ try {
414
+ const response = await API.get(ENDPOINTS.GET_ALL_FEATURES_STATUS);
415
+ return response; // Adjust if your API wraps this in .data
416
+ } catch (error) {
417
+ ErrorHandler(error);
418
+ return rejectWithValue(error.response?.data || error.message);
419
+ }
420
+ }
421
+ );
422
+
423
+ // GET: Room Amenities
424
+ export const getRoomAmenitiesProperty = createAsyncThunk(
425
+ "properties/getRoomAmenitiesProperty",
426
+ async (_, { rejectWithValue }) => {
427
+ try {
428
+ const response = await API.get(ENDPOINTS.ROOM_AMENITIES_PROPERTIES);
429
+ return response;
430
+ } catch (error) {
431
+ ErrorHandler(error);
432
+ return rejectWithValue(error.response?.data || error.message);
433
+ }
434
+ }
435
+ );
436
+
437
+ // GET: Room Features
438
+ export const getRoomFeaturesProperty = createAsyncThunk(
439
+ "properties/getRoomFeaturesProperty",
440
+ async (_, { rejectWithValue }) => {
441
+ try {
442
+ const response = await API.get(ENDPOINTS.ROOM_FEATURES_PROPERTIES);
443
+ return response;
444
+ } catch (error) {
445
+ return rejectWithValue(error.response?.data || error.message);
446
+ }
447
+ }
448
+ );
449
+
450
+ // GET: Bed Type
451
+ export const getBedType = createAsyncThunk(
452
+ "properties/getBedType",
453
+ async (_, { rejectWithValue }) => {
454
+ try {
455
+ const response = await API.get(ENDPOINTS.ROOM_BED_TYPE);
456
+ return response;
457
+ } catch (error) {
458
+ return rejectWithValue(error.response?.data || error.message);
459
+ }
460
+ }
461
+ );
462
+
463
+ // GET: Room Type
464
+ export const getRoomType = createAsyncThunk(
465
+ "properties/getRoomType",
466
+ async (_, { rejectWithValue }) => {
467
+ try {
468
+ const response = await API.get(ENDPOINTS.ROOM_TYPE);
469
+ return response;
470
+ } catch (error) {
471
+ return rejectWithValue(error.response?.data || error.message);
472
+ }
473
+ }
474
+ );
475
+
476
+ export const deleteImage = createAsyncThunk(
477
+ "properties/deleteImage",
478
+ async ({ id }, { rejectWithValue }) => {
479
+ try {
480
+ // The id parameter might be an array, but your endpoint expects a different format
481
+ const response = await API.delete(ENDPOINTS.DELETEIMAGE, {
482
+ data: { id },
483
+ });
484
+ return response;
485
+ } catch (error) {
486
+ ErrorHandler(error);
487
+ return rejectWithValue(error);
488
+ }
489
+ }
490
+ );
491
+
492
+ export const reserveBooking = createAsyncThunk(
493
+ "payment/reserveBooking",
494
+ async (payload, { rejectWithValue }) => {
495
+ try {
496
+ const response = await API.post(ENDPOINTS.BOOKING, payload);
497
+ return response.data;
498
+ } catch (error) {
499
+ ErrorHandler(error);
500
+ return rejectWithValue(error);
501
+ }
502
+ }
503
+ );
504
+
505
+ export const similar_Properties = createAsyncThunk(
506
+ "properties/similarProperties",
507
+ async (
508
+ { property_type_id, property_category_id, property_id },
509
+ { rejectWithValue }
510
+ ) => {
511
+ try {
512
+ const url = `${ENDPOINTS.SIMILAR_PROPERTIES}?property_type_id=${property_type_id}&property_category_id=${property_category_id}&property_id=${property_id}`;
513
+ const response = await API.get(url);
514
+ return response;
515
+ } catch (error) {
516
+ return rejectWithValue(error);
517
+ }
518
+ }
519
+ );
520
+
521
+ export const getAllProperties = createAsyncThunk(
522
+ "properties/allProperties",
523
+ async (page, { rejectWithValue }) => {
524
+ try {
525
+ const response = await API.get(ENDPOINTS.GET_ALL_PROPERTIES(page));
526
+ return response; // Returning data directly, which contains user info
527
+ } catch (error) {
528
+ ErrorHandler(error);
529
+ return rejectWithValue(error);
530
+ }
531
+ }
532
+ );
533
+ export const getBookingDetails = createAsyncThunk(
534
+ "properties/bookings",
535
+ async (id, { rejectWithValue }) => {
536
+ try {
537
+ const response = await API.get(`${ENDPOINTS.BOOKING_DETAILS}/${id}`);
538
+ return response; // Returning data directly, which contains user info
539
+ } catch (error) {
540
+ ErrorHandler(error);
541
+ return rejectWithValue(error);
542
+ }
543
+ }
544
+ );
545
+
546
+ const initialState = {
547
+ property: null,
548
+ globalId: null,
549
+ propertyToCreate: {},
550
+ allProperties: [],
551
+ metaData: {},
552
+ searchedData: {},
553
+ PropertyToEdit: null,
554
+ propertiesCategories: [],
555
+ propertyTypes: [],
556
+ amenities: [],
557
+ featureCategories: [],
558
+ roomamenitiesCategories: [],
559
+ roomfeaturesCategories: [],
560
+ bedType: [],
561
+ roomType: [],
562
+ loading: false,
563
+ };
564
+
565
+ const propertiesSlice = createSlice({
566
+ name: "properties",
567
+ initialState,
568
+ reducers: {
569
+ setId: (state, action) => {
570
+ state.globalId = action.payload;
571
+ },
572
+ setPropertyToCreate: (state, action) => {
573
+ state.propertyToCreate = action.payload;
574
+ },
575
+ setProperties: (state, action) => {
576
+ state.allProperties = action.payload;
577
+ },
578
+ clearPropertyToEdit: (state) => {
579
+ state.PropertyToEdit = null;
580
+ },
581
+ setSearchData: (state, action) => {
582
+ const {
583
+ startDate,
584
+ endDate,
585
+ totalGuests,
586
+ latitude,
587
+ longitude,
588
+ label,
589
+ locationData,
590
+ searchedResult,
591
+ } = action.payload;
592
+ state.searchedData = {
593
+ ...state.searchedData,
594
+ startDate,
595
+ endDate,
596
+ totalGuests,
597
+ latitude,
598
+ longitude,
599
+ label,
600
+ locationData,
601
+ searchedResult,
602
+ };
603
+ },
604
+ },
605
+ extraReducers: (builder) => {
606
+ builder
607
+
608
+ .addCase(createProperties.fulfilled, (state, action) => {
609
+ state.loading = false;
610
+ state.property = action.payload;
611
+ })
612
+
613
+ .addCase(updateProperties.fulfilled, (state, action) => {
614
+ state.loading = false;
615
+ state.property = action.payload;
616
+ })
617
+ .addCase(uploadImageProperties.fulfilled, (state, action) => {
618
+ state.loading = false;
619
+ state.property = action.payload;
620
+ })
621
+ .addCase(getallupdateProperties.fulfilled, (state, action) => {
622
+ state.PropertyToEdit = action.payload || null;
623
+ state.loading = false;
624
+ })
625
+ .addCase(getallPropertieslisting.fulfilled, (state, action) => {
626
+ const data = action.payload;
627
+ state.allProperties = data?.properties || [];
628
+ state.metaData = data?.meta || {};
629
+ state.loading = false;
630
+ })
631
+ .addCase(getPropertyCategories.fulfilled, (state, action) => {
632
+ // state.propertiesCategories = action.payload?.data || [];
633
+ state.propertiesCategories = action.payload;
634
+ state.loading = false;
635
+ })
636
+ .addCase(getPropertyType.fulfilled, (state, action) => {
637
+ // state.propertyTypes = action.payload?.data || [];
638
+ state.propertyTypes = action.payload;
639
+ state.loading = false;
640
+ })
641
+ .addCase(getAmenitiesProperty.fulfilled, (state, action) => {
642
+ state.amenities = action.payload?.data || [];
643
+ state.loading = false;
644
+ })
645
+ .addCase(getFeaturesProperty.fulfilled, (state, action) => {
646
+ state.featureCategories = action.payload?.data || [];
647
+ state.loading = false;
648
+ })
649
+ .addCase(getRoomAmenitiesProperty.fulfilled, (state, action) => {
650
+ state.roomamenitiesCategories = action.payload;
651
+ state.loading = false;
652
+ })
653
+ .addCase(getRoomFeaturesProperty.fulfilled, (state, action) => {
654
+ state.roomfeaturesCategories = action.payload;
655
+ state.loading = false;
656
+ })
657
+ .addCase(getBedType.fulfilled, (state, action) => {
658
+ state.bedType = action.payload;
659
+ state.loading = false;
660
+ })
661
+ .addCase(getRoomType.fulfilled, (state, action) => {
662
+ state.roomType = action.payload;
663
+ state.loading = false;
664
+ })
665
+ .addCase(getAllProperties.fulfilled, (state, action) => {
666
+ state.PropertyToEdit = action.payload || null;
667
+ state.loading = false;
668
+ })
669
+ .addMatcher(
670
+ (action) =>
671
+ [
672
+ createProperties.pending.type,
673
+ updateProperties.pending.type,
674
+ uploadImageProperties.pending.type,
675
+ getallupdateProperties.pending.type,
676
+ getallPropertieslisting.pending.type,
677
+ getPropertyCategories.pending.type,
678
+ getPropertyType.pending.type,
679
+ getAmenitiesProperty.pending.type,
680
+ getFeaturesProperty.pending.type,
681
+ getRoomAmenitiesProperty.pending.type,
682
+ getRoomFeaturesProperty.pending.type,
683
+ getBedType.pending.type,
684
+ getRoomType.pending.type,
685
+ ].includes(action.type),
686
+ (state) => {
687
+ state.loading = true;
688
+ }
689
+ )
690
+ .addMatcher(
691
+ (action) =>
692
+ [
693
+ createProperties.rejected.type,
694
+ updateProperties.rejected.type,
695
+ uploadImageProperties.rejected.type,
696
+ getallupdateProperties.rejected.type,
697
+ getallPropertieslisting.rejected.type,
698
+ getPropertyCategories.rejected.type,
699
+ getPropertyType.rejected.type,
700
+ getAmenitiesProperty.rejected.type,
701
+ getFeaturesProperty.rejected.type,
702
+ getRoomAmenitiesProperty.rejected.type,
703
+ getRoomFeaturesProperty.rejected.type,
704
+ getBedType.rejected.type,
705
+ getRoomType.rejected.type,
706
+ ].includes(action.type),
707
+ (state) => {
708
+ state.loading = false;
709
+ }
710
+ );
711
+ },
712
+ });
713
+
714
+ export const {
715
+ setId,
716
+ setProperties,
717
+ setPropertyToCreate,
718
+ setSearchData,
719
+ clearPropertyToEdit,
720
+ } = propertiesSlice.actions;
721
+
722
+ export default propertiesSlice.reducer;