stay_commerce 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 (496) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +53 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/stay_manifest.js +1 -0
  6. data/app/assets/fonts/bootstrap-icons.woff +0 -0
  7. data/app/assets/fonts/bootstrap-icons.woff2 +0 -0
  8. data/app/assets/images/chevron-down.svg +3 -0
  9. data/app/assets/images/circle-fill.svg +3 -0
  10. data/app/assets/images/circle.svg +3 -0
  11. data/app/assets/images/plus-circle.svg +4 -0
  12. data/app/assets/images/save.svg +3 -0
  13. data/app/assets/images/store.svg +3 -0
  14. data/app/assets/javascripts/stay/admin/address.js +165 -0
  15. data/app/assets/javascripts/stay/admin/ckeditor.min.js +7 -0
  16. data/app/assets/javascripts/stay/admin/flatpickr.min.js +2 -0
  17. data/app/assets/javascripts/stay/admin/index.js +28 -0
  18. data/app/assets/javascripts/stay/admin/property.js +37 -0
  19. data/app/assets/javascripts/stay/admin/select2.min.js +2 -0
  20. data/app/assets/javascripts/stay/application.js +14 -0
  21. data/app/assets/javascripts/stay/bootstrap.bundle.min.js +7 -0
  22. data/app/assets/javascripts/stay/ckeditor.js +11 -0
  23. data/app/assets/javascripts/stay/custom.js +56 -0
  24. data/app/assets/javascripts/stay/jquery-ui.min.js +13 -0
  25. data/app/assets/javascripts/stay/jquery.min.js +2 -0
  26. data/app/assets/stylesheets/stay/admin/flatpickr.min.css +13 -0
  27. data/app/assets/stylesheets/stay/admin/index.css +100 -0
  28. data/app/assets/stylesheets/stay/admin/select2.min.css +1 -0
  29. data/app/assets/stylesheets/stay/application.css +24 -0
  30. data/app/assets/stylesheets/stay/badges.css +72 -0
  31. data/app/assets/stylesheets/stay/bootstrap-icons.min.css +5 -0
  32. data/app/assets/stylesheets/stay/bootstrap-icons_fix.css +5 -0
  33. data/app/assets/stylesheets/stay/common.css +283 -0
  34. data/app/assets/stylesheets/stay/jquery-ui.css +1311 -0
  35. data/app/assets/stylesheets/stay/webpixels.css +7 -0
  36. data/app/channels/chat_channel.rb +13 -0
  37. data/app/controllers/concerns/stay/booking_validations.rb +86 -0
  38. data/app/controllers/concerns/stay/stripe_concern.rb +72 -0
  39. data/app/controllers/stay/admin/addresses_controller.rb +76 -0
  40. data/app/controllers/stay/admin/amenities_controller.rb +52 -0
  41. data/app/controllers/stay/admin/amenity_categories_controller.rb +52 -0
  42. data/app/controllers/stay/admin/base_controller.rb +38 -0
  43. data/app/controllers/stay/admin/bed_types_controller.rb +51 -0
  44. data/app/controllers/stay/admin/bookings_controller.rb +54 -0
  45. data/app/controllers/stay/admin/cancellation_policies_controller.rb +51 -0
  46. data/app/controllers/stay/admin/chats_controller.rb +53 -0
  47. data/app/controllers/stay/admin/cities_controller.rb +66 -0
  48. data/app/controllers/stay/admin/confirmations_controller.rb +30 -0
  49. data/app/controllers/stay/admin/countries_controller.rb +53 -0
  50. data/app/controllers/stay/admin/dashboard_controller.rb +8 -0
  51. data/app/controllers/stay/admin/features_controller.rb +54 -0
  52. data/app/controllers/stay/admin/home_controller.rb +15 -0
  53. data/app/controllers/stay/admin/house_rules_controller.rb +51 -0
  54. data/app/controllers/stay/admin/messages_controller.rb +53 -0
  55. data/app/controllers/stay/admin/passwords_controller.rb +32 -0
  56. data/app/controllers/stay/admin/payment_methods_controller.rb +53 -0
  57. data/app/controllers/stay/admin/payments_controller.rb +63 -0
  58. data/app/controllers/stay/admin/properties_controller.rb +118 -0
  59. data/app/controllers/stay/admin/property_categories_controller.rb +51 -0
  60. data/app/controllers/stay/admin/property_types_controller.rb +51 -0
  61. data/app/controllers/stay/admin/registrations_controller.rb +19 -0
  62. data/app/controllers/stay/admin/reviews_Controller.rb +63 -0
  63. data/app/controllers/stay/admin/roles_controller.rb +54 -0
  64. data/app/controllers/stay/admin/room_amenities_controller.rb +43 -0
  65. data/app/controllers/stay/admin/room_types_controller.rb +58 -0
  66. data/app/controllers/stay/admin/rooms_controller.rb +62 -0
  67. data/app/controllers/stay/admin/sessions_controller.rb +29 -0
  68. data/app/controllers/stay/admin/states_controller.rb +68 -0
  69. data/app/controllers/stay/admin/stores_controller.rb +132 -0
  70. data/app/controllers/stay/admin/taxes_controller.rb +51 -0
  71. data/app/controllers/stay/admin/users_controller.rb +85 -0
  72. data/app/controllers/stay/api/v1/amenities_controller.rb +13 -0
  73. data/app/controllers/stay/api/v1/amenity_categories_controller.rb +13 -0
  74. data/app/controllers/stay/api/v1/bed_types_controller.rb +9 -0
  75. data/app/controllers/stay/api/v1/booking_queries_controller.rb +205 -0
  76. data/app/controllers/stay/api/v1/bookings_controller.rb +299 -0
  77. data/app/controllers/stay/api/v1/cancellation_policies_controller.rb +10 -0
  78. data/app/controllers/stay/api/v1/chats_controller.rb +116 -0
  79. data/app/controllers/stay/api/v1/credit_cards_controller.rb +62 -0
  80. data/app/controllers/stay/api/v1/features_controller.rb +21 -0
  81. data/app/controllers/stay/api/v1/house_rules_controller.rb +9 -0
  82. data/app/controllers/stay/api/v1/invoices_controller.rb +47 -0
  83. data/app/controllers/stay/api/v1/messages_controller.rb +144 -0
  84. data/app/controllers/stay/api/v1/payments_controller.rb +61 -0
  85. data/app/controllers/stay/api/v1/profiles_controller.rb +23 -0
  86. data/app/controllers/stay/api/v1/properties_controller.rb +233 -0
  87. data/app/controllers/stay/api/v1/property_categories_controller.rb +14 -0
  88. data/app/controllers/stay/api/v1/property_types_controller.rb +14 -0
  89. data/app/controllers/stay/api/v1/room_types_controller.rb +14 -0
  90. data/app/controllers/stay/api/v1/rooms_controller.rb +23 -0
  91. data/app/controllers/stay/api/v1/user_paypal_controller.rb +53 -0
  92. data/app/controllers/stay/api/v1/users_controller.rb +17 -0
  93. data/app/controllers/stay/application_controller.rb +44 -0
  94. data/app/controllers/stay/base_api_controller.rb +14 -0
  95. data/app/controllers/stay/bookings_controller.rb +29 -0
  96. data/app/controllers/stay/payments_controller.rb +50 -0
  97. data/app/controllers/stay/profiles_controller.rb +26 -0
  98. data/app/controllers/stay/properties_controller.rb +15 -0
  99. data/app/controllers/stay/rooms_controller.rb +22 -0
  100. data/app/controllers/stay/users/confirmations_controller.rb +30 -0
  101. data/app/controllers/stay/users/omniauth_callbacks_controller.rb +30 -0
  102. data/app/controllers/stay/users/passwords_controller.rb +51 -0
  103. data/app/controllers/stay/users/registrations_controller.rb +62 -0
  104. data/app/controllers/stay/users/sessions_controller.rb +27 -0
  105. data/app/controllers/stay/users/unlocks_controller.rb +30 -0
  106. data/app/helpers/stay/admin/cities_helper.rb +4 -0
  107. data/app/helpers/stay/admin/countries_helper.rb +4 -0
  108. data/app/helpers/stay/admin/states_helper.rb +4 -0
  109. data/app/helpers/stay/admin/stores_helper.rb +25 -0
  110. data/app/helpers/stay/application_helper.rb +63 -0
  111. data/app/helpers/stay/currency_helper.rb +34 -0
  112. data/app/helpers/stay/locale_helper.rb +107 -0
  113. data/app/jobs/stay/application_job.rb +4 -0
  114. data/app/mailers/stay/application_mailer.rb +6 -0
  115. data/app/mailers/stay/user_mailer.rb +13 -0
  116. data/app/models/concerns/stay/translatable_resource.rb +25 -0
  117. data/app/models/stay/additional_rule.rb +5 -0
  118. data/app/models/stay/address.rb +40 -0
  119. data/app/models/stay/amenity.rb +13 -0
  120. data/app/models/stay/amenity_category.rb +6 -0
  121. data/app/models/stay/application_record.rb +5 -0
  122. data/app/models/stay/bed_type.rb +7 -0
  123. data/app/models/stay/booking.rb +199 -0
  124. data/app/models/stay/booking_query.rb +23 -0
  125. data/app/models/stay/cancellation_policy.rb +6 -0
  126. data/app/models/stay/chat.rb +23 -0
  127. data/app/models/stay/city.rb +9 -0
  128. data/app/models/stay/country.rb +23 -0
  129. data/app/models/stay/credit_card.rb +6 -0
  130. data/app/models/stay/discount.rb +4 -0
  131. data/app/models/stay/expense.rb +4 -0
  132. data/app/models/stay/feature.rb +11 -0
  133. data/app/models/stay/house_rule.rb +4 -0
  134. data/app/models/stay/invoice.rb +23 -0
  135. data/app/models/stay/line_item.rb +7 -0
  136. data/app/models/stay/message.rb +30 -0
  137. data/app/models/stay/payment.rb +54 -0
  138. data/app/models/stay/payment_method.rb +13 -0
  139. data/app/models/stay/price.rb +18 -0
  140. data/app/models/stay/property.rb +243 -0
  141. data/app/models/stay/property_amenity.rb +6 -0
  142. data/app/models/stay/property_category.rb +6 -0
  143. data/app/models/stay/property_feature.rb +6 -0
  144. data/app/models/stay/property_house_rule.rb +6 -0
  145. data/app/models/stay/property_tax.rb +6 -0
  146. data/app/models/stay/property_type.rb +15 -0
  147. data/app/models/stay/review.rb +5 -0
  148. data/app/models/stay/role.rb +11 -0
  149. data/app/models/stay/role_user.rb +6 -0
  150. data/app/models/stay/room.rb +93 -0
  151. data/app/models/stay/room_amenity.rb +6 -0
  152. data/app/models/stay/room_feature.rb +6 -0
  153. data/app/models/stay/room_type.rb +7 -0
  154. data/app/models/stay/state.rb +13 -0
  155. data/app/models/stay/store.rb +139 -0
  156. data/app/models/stay/store_property.rb +9 -0
  157. data/app/models/stay/tax.rb +8 -0
  158. data/app/models/stay/user.rb +111 -0
  159. data/app/models/stay/user_paypal.rb +5 -0
  160. data/app/serializers/amenity_category_serializer.rb +13 -0
  161. data/app/serializers/amenity_serializer.rb +3 -0
  162. data/app/serializers/bed_type_serializer.rb +5 -0
  163. data/app/serializers/booking_query_serializer.rb +6 -0
  164. data/app/serializers/booking_serializer.rb +68 -0
  165. data/app/serializers/cancellation_policy_serializer.rb +3 -0
  166. data/app/serializers/chat_serializer.rb +63 -0
  167. data/app/serializers/credit_card_serializer.rb +7 -0
  168. data/app/serializers/house_rules_serializer.rb +3 -0
  169. data/app/serializers/invoice_serializer.rb +41 -0
  170. data/app/serializers/last_5_messages_serializer.rb +7 -0
  171. data/app/serializers/line_item_serializer.rb +6 -0
  172. data/app/serializers/message_serializer.rb +44 -0
  173. data/app/serializers/property_category_serializer.rb +7 -0
  174. data/app/serializers/property_feature_serializer.rb +5 -0
  175. data/app/serializers/property_listing_serializer.rb +13 -0
  176. data/app/serializers/property_serializer.rb +77 -0
  177. data/app/serializers/property_type_serializer.rb +7 -0
  178. data/app/serializers/room_serializer.rb +36 -0
  179. data/app/serializers/room_type_serializer.rb +5 -0
  180. data/app/serializers/user_listing_serializer.rb +23 -0
  181. data/app/serializers/user_serializer.rb +41 -0
  182. data/app/services/stay/bookings/create_booking_service.rb +49 -0
  183. data/app/services/stay/bookings/create_line_item_service.rb +15 -0
  184. data/app/services/stay/bookings/existing_booking_service.rb +50 -0
  185. data/app/services/stay/chat/chat_messaging_service.rb +82 -0
  186. data/app/services/stay/chat/query_messaging_service.rb +56 -0
  187. data/app/services/stay/seeds/all.rb +27 -0
  188. data/app/services/stay/seeds/cancellation_policy.rb +21 -0
  189. data/app/services/stay/seeds/countries.rb +33 -0
  190. data/app/services/stay/seeds/roles.rb +9 -0
  191. data/app/services/stay/seeds/states.rb +63 -0
  192. data/app/services/stay/seeds/stores.rb +34 -0
  193. data/app/views/devise/mailer/reset_password_instructions.html.rb +10 -0
  194. data/app/views/kaminari/_first_page.html.erb +3 -0
  195. data/app/views/kaminari/_gap.html.erb +3 -0
  196. data/app/views/kaminari/_last_page.html.erb +3 -0
  197. data/app/views/kaminari/_next_page.html.erb +3 -0
  198. data/app/views/kaminari/_page.html.erb +9 -0
  199. data/app/views/kaminari/_paginator.html.erb +17 -0
  200. data/app/views/kaminari/_prev_page.html.erb +3 -0
  201. data/app/views/layouts/stay/admin.html.erb +45 -0
  202. data/app/views/layouts/stay/application.html.erb +34 -0
  203. data/app/views/stay/admin/addresses/_form.html.erb +49 -0
  204. data/app/views/stay/admin/addresses/edit.html.erb +5 -0
  205. data/app/views/stay/admin/addresses/index.html.erb +68 -0
  206. data/app/views/stay/admin/addresses/new.html.erb +5 -0
  207. data/app/views/stay/admin/addresses/show.html.erb +40 -0
  208. data/app/views/stay/admin/amenities/_form.html.erb +38 -0
  209. data/app/views/stay/admin/amenities/edit.html.erb +14 -0
  210. data/app/views/stay/admin/amenities/index.html.erb +58 -0
  211. data/app/views/stay/admin/amenities/new.html.erb +14 -0
  212. data/app/views/stay/admin/amenities/show.html.erb +19 -0
  213. data/app/views/stay/admin/amenity_categories/_form.html.erb +29 -0
  214. data/app/views/stay/admin/amenity_categories/edit.html.erb +14 -0
  215. data/app/views/stay/admin/amenity_categories/index.html.erb +53 -0
  216. data/app/views/stay/admin/amenity_categories/new.html.erb +14 -0
  217. data/app/views/stay/admin/amenity_categories/show.html.erb +18 -0
  218. data/app/views/stay/admin/bed_types/_form.html.erb +29 -0
  219. data/app/views/stay/admin/bed_types/edit.html.erb +14 -0
  220. data/app/views/stay/admin/bed_types/index.html.erb +56 -0
  221. data/app/views/stay/admin/bed_types/new.html.erb +14 -0
  222. data/app/views/stay/admin/bed_types/show.html.erb +0 -0
  223. data/app/views/stay/admin/bookings/_booking_invoice.html.erb +37 -0
  224. data/app/views/stay/admin/bookings/_booking_summary.html.erb +61 -0
  225. data/app/views/stay/admin/bookings/_form.html.erb +59 -0
  226. data/app/views/stay/admin/bookings/edit.html.erb +14 -0
  227. data/app/views/stay/admin/bookings/index.html.erb +74 -0
  228. data/app/views/stay/admin/bookings/new.html.erb +14 -0
  229. data/app/views/stay/admin/bookings/show.html.erb +80 -0
  230. data/app/views/stay/admin/cancellation_policies/_form.html.erb +38 -0
  231. data/app/views/stay/admin/cancellation_policies/edit.html.erb +14 -0
  232. data/app/views/stay/admin/cancellation_policies/index.html.erb +58 -0
  233. data/app/views/stay/admin/cancellation_policies/new.html.erb +14 -0
  234. data/app/views/stay/admin/cancellation_policies/show.html.erb +0 -0
  235. data/app/views/stay/admin/chats/_form.html.erb +31 -0
  236. data/app/views/stay/admin/chats/edit.html.erb +5 -0
  237. data/app/views/stay/admin/chats/index.html.erb +58 -0
  238. data/app/views/stay/admin/chats/new.html.erb +5 -0
  239. data/app/views/stay/admin/chats/show.html.erb +19 -0
  240. data/app/views/stay/admin/cities/_form.html.erb +30 -0
  241. data/app/views/stay/admin/cities/edit.html.erb +14 -0
  242. data/app/views/stay/admin/cities/index.html.erb +62 -0
  243. data/app/views/stay/admin/cities/new.html.erb +14 -0
  244. data/app/views/stay/admin/countries/_form.html.erb +64 -0
  245. data/app/views/stay/admin/countries/edit.html.erb +14 -0
  246. data/app/views/stay/admin/countries/index.html.erb +62 -0
  247. data/app/views/stay/admin/countries/new.html.erb +14 -0
  248. data/app/views/stay/admin/countries/show.html.erb +23 -0
  249. data/app/views/stay/admin/dashboard/index.html.erb +1 -0
  250. data/app/views/stay/admin/features/_form.html.erb +38 -0
  251. data/app/views/stay/admin/features/edit.html.erb +14 -0
  252. data/app/views/stay/admin/features/index.html.erb +58 -0
  253. data/app/views/stay/admin/features/new.html.erb +14 -0
  254. data/app/views/stay/admin/features/show.html.erb +19 -0
  255. data/app/views/stay/admin/house_rules/_form.html.erb +29 -0
  256. data/app/views/stay/admin/house_rules/edit.html.erb +14 -0
  257. data/app/views/stay/admin/house_rules/index.html.erb +54 -0
  258. data/app/views/stay/admin/house_rules/new.html.erb +14 -0
  259. data/app/views/stay/admin/house_rules/show.html.erb +18 -0
  260. data/app/views/stay/admin/mailer/confirmation_instructions.html.erb +5 -0
  261. data/app/views/stay/admin/mailer/email_changed.html.erb +7 -0
  262. data/app/views/stay/admin/mailer/password_change.html.erb +3 -0
  263. data/app/views/stay/admin/mailer/reset_password_instructions.html.erb +7 -0
  264. data/app/views/stay/admin/messages/_form.html.erb +36 -0
  265. data/app/views/stay/admin/messages/edit.html.erb +5 -0
  266. data/app/views/stay/admin/messages/index.html.erb +60 -0
  267. data/app/views/stay/admin/messages/new.html.erb +5 -0
  268. data/app/views/stay/admin/messages/show.html.erb +24 -0
  269. data/app/views/stay/admin/passwords/edit.html.erb +37 -0
  270. data/app/views/stay/admin/passwords/new.html.erb +28 -0
  271. data/app/views/stay/admin/payment_methods/_form.html.erb +22 -0
  272. data/app/views/stay/admin/payment_methods/edit.html.erb +14 -0
  273. data/app/views/stay/admin/payment_methods/index.html.erb +54 -0
  274. data/app/views/stay/admin/payment_methods/new.html.erb +14 -0
  275. data/app/views/stay/admin/payment_methods/show.html.erb +18 -0
  276. data/app/views/stay/admin/payments/_form.html.erb +36 -0
  277. data/app/views/stay/admin/payments/edit.html.erb +5 -0
  278. data/app/views/stay/admin/payments/index.html.erb +60 -0
  279. data/app/views/stay/admin/payments/new.html.erb +5 -0
  280. data/app/views/stay/admin/payments/show.html.erb +24 -0
  281. data/app/views/stay/admin/properties/_amenities.html.erb +38 -0
  282. data/app/views/stay/admin/properties/_calendar.html.erb +37 -0
  283. data/app/views/stay/admin/properties/_description.html.erb +126 -0
  284. data/app/views/stay/admin/properties/_details.html.erb +75 -0
  285. data/app/views/stay/admin/properties/_features.html.erb +39 -0
  286. data/app/views/stay/admin/properties/_form.html.erb +118 -0
  287. data/app/views/stay/admin/properties/_images.html.erb +48 -0
  288. data/app/views/stay/admin/properties/_location.html.erb +55 -0
  289. data/app/views/stay/admin/properties/_price.html.erb +88 -0
  290. data/app/views/stay/admin/properties/_sidebar.html.erb +47 -0
  291. data/app/views/stay/admin/properties/edit.html.erb +17 -0
  292. data/app/views/stay/admin/properties/index.html.erb +82 -0
  293. data/app/views/stay/admin/properties/new.html.erb +14 -0
  294. data/app/views/stay/admin/properties/show.html.erb +149 -0
  295. data/app/views/stay/admin/property_categories/_form.html.erb +29 -0
  296. data/app/views/stay/admin/property_categories/edit.html.erb +14 -0
  297. data/app/views/stay/admin/property_categories/index.html.erb +57 -0
  298. data/app/views/stay/admin/property_categories/new.html.erb +14 -0
  299. data/app/views/stay/admin/property_categories/show.html.erb +18 -0
  300. data/app/views/stay/admin/property_types/_form.html.erb +29 -0
  301. data/app/views/stay/admin/property_types/edit.html.erb +14 -0
  302. data/app/views/stay/admin/property_types/index.html.erb +56 -0
  303. data/app/views/stay/admin/property_types/new.html.erb +14 -0
  304. data/app/views/stay/admin/property_types/show.html.erb +18 -0
  305. data/app/views/stay/admin/registrations/edit.html.erb +43 -0
  306. data/app/views/stay/admin/registrations/new.html.erb +35 -0
  307. data/app/views/stay/admin/reviews/_form.html.erb +37 -0
  308. data/app/views/stay/admin/reviews/edit.html.erb +14 -0
  309. data/app/views/stay/admin/reviews/index.html.erb +58 -0
  310. data/app/views/stay/admin/reviews/new.html.erb +14 -0
  311. data/app/views/stay/admin/reviews/show.html.erb +20 -0
  312. data/app/views/stay/admin/roles/_form.html.erb +24 -0
  313. data/app/views/stay/admin/roles/edit.html.erb +14 -0
  314. data/app/views/stay/admin/roles/index.html.erb +55 -0
  315. data/app/views/stay/admin/roles/new.html.erb +14 -0
  316. data/app/views/stay/admin/roles/show.html.erb +18 -0
  317. data/app/views/stay/admin/room_types/_form.html.erb +37 -0
  318. data/app/views/stay/admin/room_types/edit.html.erb +14 -0
  319. data/app/views/stay/admin/room_types/index.html.erb +58 -0
  320. data/app/views/stay/admin/room_types/new.html.erb +14 -0
  321. data/app/views/stay/admin/room_types/show.html.erb +19 -0
  322. data/app/views/stay/admin/rooms/_form.html.erb +136 -0
  323. data/app/views/stay/admin/rooms/edit.html.erb +14 -0
  324. data/app/views/stay/admin/rooms/index.html.erb +69 -0
  325. data/app/views/stay/admin/rooms/new.html.erb +14 -0
  326. data/app/views/stay/admin/rooms/show.html.erb +25 -0
  327. data/app/views/stay/admin/sessions/new.html.erb +36 -0
  328. data/app/views/stay/admin/shared/_common-table.html.erb +334 -0
  329. data/app/views/stay/admin/shared/_error_messages.html.erb +15 -0
  330. data/app/views/stay/admin/shared/_header.html.erb +55 -0
  331. data/app/views/stay/admin/shared/_links.html.erb +15 -0
  332. data/app/views/stay/admin/shared/_sidebar.html.erb +154 -0
  333. data/app/views/stay/admin/shared/_store_switcher.html.erb +30 -0
  334. data/app/views/stay/admin/states/_form.html.erb +39 -0
  335. data/app/views/stay/admin/states/edit.html.erb +14 -0
  336. data/app/views/stay/admin/states/index.html.erb +61 -0
  337. data/app/views/stay/admin/states/new.html.erb +14 -0
  338. data/app/views/stay/admin/states/show.html.erb +0 -0
  339. data/app/views/stay/admin/stores/_form.html.erb +30 -0
  340. data/app/views/stay/admin/stores/_tabs.html.erb +17 -0
  341. data/app/views/stay/admin/stores/edit.html.erb +14 -0
  342. data/app/views/stay/admin/stores/form/_basic.html.erb +35 -0
  343. data/app/views/stay/admin/stores/form/_emails.html.erb +34 -0
  344. data/app/views/stay/admin/stores/form/_footer.html.erb +28 -0
  345. data/app/views/stay/admin/stores/form/_internationalization.html.erb +52 -0
  346. data/app/views/stay/admin/stores/form/_seo.html.erb +42 -0
  347. data/app/views/stay/admin/stores/form/_social.html.erb +34 -0
  348. data/app/views/stay/admin/stores/index.html.erb +66 -0
  349. data/app/views/stay/admin/stores/new.html.erb +14 -0
  350. data/app/views/stay/admin/stores/translations.html.erb +8 -0
  351. data/app/views/stay/admin/taxes/_form.html.erb +29 -0
  352. data/app/views/stay/admin/taxes/edit.html.erb +14 -0
  353. data/app/views/stay/admin/taxes/index.html.erb +56 -0
  354. data/app/views/stay/admin/taxes/new.html.erb +14 -0
  355. data/app/views/stay/admin/taxes/show.html.erb +18 -0
  356. data/app/views/stay/admin/users/_address.html.erb +57 -0
  357. data/app/views/stay/admin/users/_address_form.html.erb +29 -0
  358. data/app/views/stay/admin/users/_form.html.erb +73 -0
  359. data/app/views/stay/admin/users/_sidebar.html.erb +12 -0
  360. data/app/views/stay/admin/users/addresses.html.erb +17 -0
  361. data/app/views/stay/admin/users/edit.html.erb +17 -0
  362. data/app/views/stay/admin/users/index.html.erb +74 -0
  363. data/app/views/stay/admin/users/new.html.erb +14 -0
  364. data/app/views/stay/admin/users/show.html.erb +23 -0
  365. data/app/views/stay/bookings/new.html.erb +92 -0
  366. data/app/views/stay/payments/_payment.js.erb +127 -0
  367. data/app/views/stay/payments/new.html.erb +187 -0
  368. data/app/views/stay/properties/index.html.erb +56 -0
  369. data/app/views/stay/properties/show.html.erb +137 -0
  370. data/app/views/stay/shared/_navbar.html.erb +35 -0
  371. data/app/views/stay/user_mailer/new_host_signup.html.erb +12 -0
  372. data/app/views/stay/user_mailer/welcome_email.html.erb +9 -0
  373. data/app/views/stay/users/confirmations/new.html.erb +16 -0
  374. data/app/views/stay/users/mailer/confirmation_instructions.html.erb +5 -0
  375. data/app/views/stay/users/mailer/email_changed.html.erb +7 -0
  376. data/app/views/stay/users/mailer/password_change.html.erb +3 -0
  377. data/app/views/stay/users/mailer/reset_password_instructions.html.erb +7 -0
  378. data/app/views/stay/users/mailer/unlock_instructions.html.erb +7 -0
  379. data/app/views/stay/users/passwords/edit.html.erb +37 -0
  380. data/app/views/stay/users/passwords/new.html.erb +28 -0
  381. data/app/views/stay/users/registrations/edit.html.erb +43 -0
  382. data/app/views/stay/users/registrations/new.html.erb +42 -0
  383. data/app/views/stay/users/sessions/new.html.erb +43 -0
  384. data/app/views/stay/users/shared/_error_messages.html.erb +15 -0
  385. data/app/views/stay/users/shared/_links.html.erb +25 -0
  386. data/app/views/stay/users/unlocks/new.html.erb +16 -0
  387. data/config/initializers/devise.rb +358 -0
  388. data/config/initializers/friendly_id.rb +107 -0
  389. data/config/initializers/geocoder.rb +4 -0
  390. data/config/initializers/kaminari_config.rb +14 -0
  391. data/config/initializers/mobility.rb +17 -0
  392. data/config/initializers/stripe.rb +8 -0
  393. data/config/locales/devise.en.yml +65 -0
  394. data/config/locales/devise_api.en.yml +23 -0
  395. data/config/locales/en.yml +38 -0
  396. data/config/routes.rb +187 -0
  397. data/db/migrate/20240912073149_devise_create_stay_users.rb +50 -0
  398. data/db/migrate/20240912073248_create_devise_api_tables.rb +29 -0
  399. data/db/migrate/20240912092842_create_stay_roles.rb +9 -0
  400. data/db/migrate/20240912093003_create_stay_role_users.rb +10 -0
  401. data/db/migrate/20240912093151_create_stay_properties.rb +16 -0
  402. data/db/migrate/20240912093213_create_stay_rooms.rb +12 -0
  403. data/db/migrate/20240912093240_create_stay_bookings.rb +15 -0
  404. data/db/migrate/20240912093346_create_stay_payment_methods.rb +9 -0
  405. data/db/migrate/20240912093408_create_stay_payments.rb +12 -0
  406. data/db/migrate/20240912093603_create_stay_reviews.rb +11 -0
  407. data/db/migrate/20240912093644_create_stay_chats.rb +11 -0
  408. data/db/migrate/20240912093717_create_stay_messages.rb +12 -0
  409. data/db/migrate/20240912093759_create_stay_countries.rb +14 -0
  410. data/db/migrate/20240912093824_create_stay_states.rb +11 -0
  411. data/db/migrate/20240912093903_create_stay_cities.rb +10 -0
  412. data/db/migrate/20240912094149_create_stay_addresses.rb +19 -0
  413. data/db/migrate/20240916071141_create_active_storage_tables.rb +57 -0
  414. data/db/migrate/20240918080551_add_columns_to_stay_bookings.rb +12 -0
  415. data/db/migrate/20240918101502_add_columns_to_stay_payments.rb +16 -0
  416. data/db/migrate/20240918110958_create_stay_prices.rb +13 -0
  417. data/db/migrate/20240918112045_add_columns_to_stay_rooms.rb +5 -0
  418. data/db/migrate/20240918114609_add_payment_intent_in_bookings.rb +6 -0
  419. data/db/migrate/20240919045205_add_user_to_stay_addresses.rb +5 -0
  420. data/db/migrate/20240919063400_create_stay_room_types.rb +10 -0
  421. data/db/migrate/20240919070423_rename_room_type_to_room_type_id_in_stay_rooms.rb +5 -0
  422. data/db/migrate/20240919071642_rename_status_to_state_in_stay_payments.rb +5 -0
  423. data/db/migrate/20240919100508_remove_room_id_from_stay_properties.rb +5 -0
  424. data/db/migrate/20240919111801_create_stay_line_items.rb +16 -0
  425. data/db/migrate/20240919124704_remove_room_id_from_stay_bookings.rb +5 -0
  426. data/db/migrate/20240924053658_add_is_master_in_stay_rooms.rb +5 -0
  427. data/db/migrate/20240925063733_add_zipcode_required_in_countries.rb +5 -0
  428. data/db/migrate/20240926055951_remove_city_reference_from_stay_addresses.rb +5 -0
  429. data/db/migrate/20240927055935_change_price_per_night_to_decimal_in_stay_rooms.rb +5 -0
  430. data/db/migrate/20240927063023_add_first_name_to_stay_addresses.rb +8 -0
  431. data/db/migrate/20240927070538_change_description_to_text_in_stay_properties.rb +6 -0
  432. data/db/migrate/20240927111110_create_stay_stores.rb +33 -0
  433. data/db/migrate/20240930095921_create_stay_cancellation_policies.rb +9 -0
  434. data/db/migrate/20240930100157_add_cancellation_id_to_stay_properties.rb +5 -0
  435. data/db/migrate/20240930152331_create_stay_store_translations.rb +22 -0
  436. data/db/migrate/20240930162337_create_stay_store_properties.rb +10 -0
  437. data/db/migrate/20241001101816_create_stay_property_categories.rb +8 -0
  438. data/db/migrate/20241001102646_add_property_category_id_to_property.rb +5 -0
  439. data/db/migrate/20241001103758_create_stay_property_types.rb +9 -0
  440. data/db/migrate/20241001111306_add_store_id_to_stay_bookings.rb +5 -0
  441. data/db/migrate/20241001160330_add_deleted_at_to_stay_store_translations.rb +5 -0
  442. data/db/migrate/20241004061647_add_field_to_stay_properties.rb +20 -0
  443. data/db/migrate/20241004062057_create_stay_bed_types.rb +9 -0
  444. data/db/migrate/20241004062251_add_details_to_stay_rooms.rb +9 -0
  445. data/db/migrate/20241004070456_add_property_type_id_to_stay_property_categories.rb +6 -0
  446. data/db/migrate/20241004105821_create_stay_amenity_categories.rb +8 -0
  447. data/db/migrate/20241004112600_create_stay_amenities.rb +9 -0
  448. data/db/migrate/20241004115207_create_stay_house_rules.rb +8 -0
  449. data/db/migrate/20241004115317_create_stay_additional_rules.rb +9 -0
  450. data/db/migrate/20241004115608_create_stay_property_amenities.rb +9 -0
  451. data/db/migrate/20241004115615_create_stay_room_amenities.rb +9 -0
  452. data/db/migrate/20241007051646_add_preferences_to_stay_users.rb +5 -0
  453. data/db/migrate/20241007165530_create_stay_creates.rb +10 -0
  454. data/db/migrate/20241008111346_add_deleted_at_to_stay_users.rb +7 -0
  455. data/db/migrate/20241008151958_add_price_per_night_in_stay_properties.rb +5 -0
  456. data/db/migrate/20241010071855_add_zipcode_to_stay_property.rb +8 -0
  457. data/db/migrate/20241014085441_add_amenity_type_in_amenities.rb +5 -0
  458. data/db/migrate/20241015055940_create_stay_features.rb +10 -0
  459. data/db/migrate/20241015060804_create_stay_property_features.rb +9 -0
  460. data/db/migrate/20241015060854_create_stay_room_features.rb +9 -0
  461. data/db/migrate/20241016055948_create_stay_tax.rb +9 -0
  462. data/db/migrate/20241016060354_create_stay_property_tax.rb +11 -0
  463. data/db/migrate/20241016091120_remove_column_from_stay_properties_categories.rb +6 -0
  464. data/db/migrate/20241016091829_add_column_to_stay_property.rb +5 -0
  465. data/db/migrate/20241016112707_add_country_to_stay_properties.rb +6 -0
  466. data/db/migrate/20241016153847_add_state_to_properties.rb +7 -0
  467. data/db/migrate/20241016170528_up_date_price_column_in_stay_property.rb +5 -0
  468. data/db/migrate/20241017031520_add_new_field_to_stay_properties.rb +8 -0
  469. data/db/migrate/20241017051450_add_column_to_stay_chat.rb +7 -0
  470. data/db/migrate/20241018090158_create_stay_stay_credit_cards.rb +16 -0
  471. data/db/migrate/20241021090444_create_stay_stay_user_paypals.rb +9 -0
  472. data/db/migrate/20241024065949_add_stay_property_to_stay_b0okings.rb +5 -0
  473. data/db/migrate/20241027062126_add_events_to_stay_messages.rb +8 -0
  474. data/db/migrate/20241028105007_create_stay_invoices.rb +15 -0
  475. data/db/migrate/20241028105323_create_stay_expenses.rb +10 -0
  476. data/db/migrate/20241028105331_create_stay_discounts.rb +10 -0
  477. data/db/migrate/20241101044618_create_stay_booking_queries.rb +17 -0
  478. data/db/migrate/20241101093057_add_read_at_to_stay_messages.rb +5 -0
  479. data/db/migrate/20241113061248_modify_cancellation_policy_on_properties.rb +7 -0
  480. data/db/migrate/20241118064033_rename_columns_in_stay_properties.rb +7 -0
  481. data/db/migrate/20241127060541_add_new_fields_to_property.rb +11 -0
  482. data/db/migrate/20241128111832_add_name_to_stay_rooms.rb +5 -0
  483. data/db/migrate/20241129063922_change_amenity_category_null_on_stay_amenities.rb +5 -0
  484. data/db/migrate/20241205092935_add_slug_to_stay_properties.rb +6 -0
  485. data/db/migrate/20241205092943_create_friendly_id_slugs.rb +21 -0
  486. data/db/migrate/20241217044817_add_deleted_atto_stay_property.rb +6 -0
  487. data/db/migrate/20241230064432_modify_property_category_on_properties.rb +7 -0
  488. data/db/seeds.rb +1 -0
  489. data/lib/stay/controller_helpers/currency.rb +54 -0
  490. data/lib/stay/controller_helpers/store.rb +37 -0
  491. data/lib/stay/engine.rb +16 -0
  492. data/lib/stay/money.rb +77 -0
  493. data/lib/stay/version.rb +3 -0
  494. data/lib/stay.rb +16 -0
  495. data/lib/tasks/stay_tasks.rake +4 -0
  496. metadata +967 -0
@@ -0,0 +1,21 @@
1
+ class Stay::Api::V1::FeaturesController < Stay::BaseApiController
2
+ before_action :authenticate_devise_api_token!
3
+
4
+ def property
5
+ features = Stay::Feature.property
6
+ if features.any?
7
+ render json: { data:ActiveModelSerializers::SerializableResource.new(features, each_serializer: PropertyFeatureSerializer) ,success: true }, status: :ok
8
+ else
9
+ render json: { error:"no feature found", success: false }, status: :unprocessable_entity
10
+ end
11
+ end
12
+
13
+ def room
14
+ features = Stay::Feature.room
15
+ if features.any?
16
+ render json: { data:ActiveModelSerializers::SerializableResource.new(features, each_serializer: PropertyFeatureSerializer) ,success: true }, status: :ok
17
+ else
18
+ render json: { error:"no feature found", success: false }, status: :unprocessable_entity
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ class Stay::Api::V1::HouseRulesController < Stay::BaseApiController
2
+ before_action :authenticate_devise_api_token!
3
+
4
+ def index
5
+ @rules = Stay::HouseRule.all
6
+ return render json: { error: "no data found", success: false }, status: :unprocessable_entity unless @rules.any?
7
+ render json: { message: "house rule found", data: ActiveModelSerializers::SerializableResource.new(@rules, each_serializer: HouseRulesSerializer), success: true }, status: :ok
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ class Stay::Api::V1::InvoicesController < ApplicationController
2
+ before_action :authenticate_devise_api_token!
3
+
4
+ def index
5
+ invoices = Stay::Invoice.joins(booking: :property)
6
+ .where(stay_properties: { user: current_devise_api_user })
7
+
8
+ if params[:start_date].present? && params[:end_date].present?
9
+ start_date = Date.parse(params[:start_date])
10
+ end_date = Date.parse(params[:end_date])
11
+ invoices = invoices.where(
12
+ "stay_bookings.check_in_date >= :start_date AND stay_bookings.check_out_date <= :end_date",
13
+ start_date: start_date,
14
+ end_date: end_date
15
+ )
16
+ end
17
+
18
+ if params[:type].present?
19
+ invoices = invoices.where("invoice_type LIKE ?", "%#{params[:type]}%")
20
+ end
21
+
22
+ if params[:status].present?
23
+ case params[:status]
24
+ when "confirmed"
25
+ invoices = invoices.where("stay_bookings.status = ?", "confirmed")
26
+ when "any"
27
+ invoices = invoices.where("stay_bookings.status = ?", "invoice_sent")
28
+ end
29
+ end
30
+
31
+ if invoices.any?
32
+ render json: { data: ActiveModelSerializers::SerializableResource.new(invoices, each_serializer: InvoiceSerializer), success: true }, status: :ok
33
+ else
34
+ render json: { error: "no invoice found", success: false }, status: :unprocessable_entity
35
+ end
36
+ end
37
+
38
+
39
+ def show
40
+ invoice = Stay::Invoice.find_by(id: params[:id])
41
+ if invoice.present?
42
+ render json: { data: ActiveModelSerializers::SerializableResource.new(invoice, serializer: InvoiceSerializer), success: true }, status: :ok
43
+ else
44
+ render json: { error: "no invoice found", success: false }, status: :unprocessable_entity
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,144 @@
1
+ class Stay::Api::V1::MessagesController < Stay::BaseApiController
2
+ protect_from_forgery with: :null_session, if: -> { request.format.json? }
3
+ before_action :authenticate_devise_api_token!
4
+ before_action :set_chat
5
+ before_action :set_message, only: [ :mark_as_read ]
6
+
7
+ def index
8
+ begin
9
+ page = params[:page].to_i > 0 ? params[:page].to_i : 1
10
+ per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 20
11
+ cumulative_limit = page * per_page
12
+
13
+ @chat.messages
14
+ .where("sender_id = :user_id OR receiver_id = :user_id", user_id: current_devise_api_user.id)
15
+ .where(read_at: nil)
16
+ .update_all(read_at: DateTime.now)
17
+
18
+ total_count = @chat.messages.count
19
+ total_pages = (total_count.to_f / per_page).ceil
20
+
21
+ messages = @chat.messages
22
+ .order(created_at: :asc)
23
+ .limit(cumulative_limit)
24
+
25
+ chat_json = ChatSerializer.new(
26
+ @chat,
27
+ scope: { current_user: current_devise_api_user }
28
+ ).as_json
29
+
30
+ messages_json = messages.map do |message|
31
+ MessageSerializer.new(message, scope: current_devise_api_user).as_json
32
+ end
33
+
34
+ render json: {
35
+ data: "Messages Found",
36
+ chat: chat_json,
37
+ message: messages_json,
38
+ success: true,
39
+ meta: {
40
+ total_pages: total_pages,
41
+ current_page: page,
42
+ next_page: page < total_pages ? page + 1 : nil,
43
+ prev_page: page > 1 ? page - 1 : nil,
44
+ total_count: total_count
45
+ }
46
+ }, status: :ok
47
+ rescue StandardError => e
48
+ render json: { error: e.message, success: false }, status: :internal_server_error
49
+ end
50
+ end
51
+ def new
52
+ @message = @chat.messages.new
53
+ render json: { data: "Message form loaded", message: @message, success: true }, status: :ok
54
+ rescue StandardError => e
55
+ render json: { error: e.message, success: false }, status: :internal_server_error
56
+ end
57
+
58
+ def create
59
+ begin
60
+ sender_id = @chat.sender_id
61
+ receiver_id = @chat.receiver_id
62
+
63
+ message = @chat.messages.new(message_params)
64
+ message.sender_id = current_devise_api_user.id
65
+ message.chat = @chat
66
+ message.event_for= Stay::Message.event_fors["both"]
67
+
68
+ if message.sender_id == sender_id
69
+ message.receiver_id = receiver_id
70
+ elsif message.sender_id == receiver_id
71
+ message.receiver_id = sender_id
72
+ else
73
+ return render json: { error: "Invalid sender or receiver", success: false }, status: :unprocessable_entity
74
+ end
75
+
76
+ return render json: { error: "You cannot send a message to yourself", success: false }, status: :unprocessable_entity if message.sender_id == message.receiver_id
77
+
78
+ if message.save
79
+ ActionCable.server.broadcast "ChatChannel", message
80
+ render json: {
81
+ data: "Message Created",
82
+ chat: ActiveModelSerializers::SerializableResource.new(@chat, serializer: ChatSerializer, scope: { current_user: current_devise_api_user }),
83
+ message: ActiveModelSerializers::SerializableResource.new(message, each_serializer: MessageSerializer),
84
+ success: true
85
+ }, status: :created
86
+ else
87
+ render json: { error: message.errors.full_messages.join(", "), success: false }, status: :unprocessable_entity
88
+ end
89
+ rescue ActiveRecord::RecordNotFound => e
90
+ render json: { error: "Chat not found: #{e.message}", success: false }, status: :not_found
91
+ rescue StandardError => e
92
+ render json: { error: e.message, success: false }, status: :internal_server_error
93
+ end
94
+ end
95
+
96
+ def mark_as_read
97
+ if @message.receiver_id == current_devise_api_user.id
98
+ @chat.messages.where(receiver_id: current_devise_api_user.id).update_all(read_at: DateTime.now)
99
+ render json: { message: "Message marked as read", success: true }, status: :ok
100
+ elsif @message.sender_id == current_devise_api_user.id
101
+ @chat.messages.where(sender_id: current_devise_api_user.id).update_all(read_at: DateTime.now)
102
+ render json: { message: "Message marked as read", success: true }, status: :ok
103
+ else
104
+ render json: { error: "You are not authorized to read this message" }, status: :unauthorized
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def set_message
111
+ begin
112
+ @message = Stay::Message.find(params[:id])
113
+ rescue ActiveRecord::RecordNotFound => e
114
+ render json: { success: false, error: "message not found" }, status: :not_found
115
+ end
116
+ end
117
+
118
+ def set_chat
119
+ begin
120
+ @chat = Stay::Chat.find(params[:chat_id])
121
+ unless @chat.sender_id == current_devise_api_user.id || @chat.receiver_id == current_devise_api_user.id
122
+ render json: { error: "not authorized to view this chat", success: false }, status: :unprocessable_entity
123
+ end
124
+ rescue ActiveRecord::RecordNotFound => e
125
+ render json: { error: "Chat not found: #{e.message}", success: false }, status: :not_found
126
+ rescue StandardError => e
127
+ render json: { error: e.message, success: false }, status: :internal_server_error
128
+ end
129
+ end
130
+
131
+ def formatted_date(date)
132
+ if date.to_date == Date.today
133
+ "Today"
134
+ elsif date.to_date == Date.yesterday
135
+ "Yesterday"
136
+ else
137
+ date.to_date.strftime("%B %d, %Y")
138
+ end
139
+ end
140
+
141
+ def message_params
142
+ params.require(:message).permit(:body, :sender_id, :receiver_id, attachments: [])
143
+ end
144
+ end
@@ -0,0 +1,61 @@
1
+ class Stay::Api::V1::PaymentsController < Stay::BaseApiController
2
+ include Stay::StripeConcern
3
+
4
+ before_action :set_booking, except: :payment_method
5
+ before_action :authenticate_devise_api_token!
6
+
7
+
8
+ def payment_method
9
+ methods = Stay::PaymentMethod.all
10
+ if methods.any?
11
+ render json: { message: "Payment Method Found", data: methods, success: true }, status: :ok
12
+ else
13
+ render json: { error: "no method found", success: false }, status: :unprocessable_entity
14
+ end
15
+ end
16
+
17
+ def create
18
+ begin
19
+ customer = create_or_retrieve_customer
20
+ payment_intent = @booking.payment_intent_id ? get_payment_intent : create_payment_intent.tap { |pi| @booking.update(payment_intent_id: pi.id) }
21
+ if params[:confirm]
22
+ if payment_intent.status == 'succeeded'
23
+ render json: { message: "Payment successful", payment_intent: payment_intent }, status: :ok
24
+ elsif payment_intent.status == 'requires_action'
25
+ render json: { message: "Payment requires further action", client_secret: payment_intent.client_secret, payment_intent_id: payment_intent["id"] }, status: :ok
26
+ else
27
+ render json: { message: "Payment failed", error: payment_intent.last_payment_error }, status: :unprocessable_entity
28
+ end
29
+ else
30
+ render json: {payment_intent: payment_intent, client_secret: payment_intent.client_secret}, status: :ok
31
+ end
32
+ rescue Stripe::CardError => e
33
+ render json: { error: e.message }, status: :unprocessable_entity
34
+ rescue => e
35
+ render json: { error: "Something went wrong" }, status: :internal_server_error
36
+ end
37
+ end
38
+
39
+ def confirm
40
+ payment_intent = get_payment_intent
41
+ if payment_intent.status == 'succeeded'
42
+ @booking.update(status: 'completed')
43
+ render json: { success: true, redirect_url: params[:redirect_url] }
44
+ else
45
+ render json: { error: payment_intent.last_payment_error.message }, status: 422
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+
52
+ def payment_params
53
+ params.require(:payment).permit(:amount, :currency, :payment_method_id, :description, :customer_email)
54
+ end
55
+
56
+ def set_booking
57
+ @booking = Stay::Booking.find(params[:booking_id])
58
+ end
59
+
60
+ end
61
+
@@ -0,0 +1,23 @@
1
+ class Stay::Api::V1::ProfilesController < Stay::BaseApiController
2
+ before_action :set_user, only: [:show, :update]
3
+
4
+ def show
5
+ render json: { profile: @profile }
6
+ end
7
+
8
+ def update
9
+ @profile.update(profile_params)
10
+ render json: { profile: @profile }, status: :ok
11
+ end
12
+
13
+ private
14
+
15
+ def set_user
16
+ @profile = current_devise_api_user || Stay::Profile.find(params[:id])
17
+ end
18
+
19
+ def profile_params
20
+ params.require(:profile).permit(:first_name, :last_name, :phone, :date_of_birth, :gender )
21
+ end
22
+
23
+ end
@@ -0,0 +1,233 @@
1
+ class Stay::Api::V1::PropertiesController < Stay::BaseApiController
2
+ before_action :authenticate_devise_api_token!
3
+ before_action :set_property, only: [ :show, :update, :destroy ]
4
+ before_action :check_create_access, only: [ :create, :update ]
5
+ before_action :check_update_access, only: [ :update ]
6
+
7
+ def index
8
+ begin
9
+ page = params[:page].to_i > 0 ? params[:page].to_i : 1
10
+ per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 10
11
+
12
+ cumulative_per_page = page * per_page
13
+
14
+ @data = Stay::Property.approved.active.joins(:rooms).distinct
15
+ @properties = @data.order(created_at: :desc).limit(cumulative_per_page)
16
+ total_count = @data.count
17
+ total_pages = (total_count.to_f / per_page).ceil
18
+
19
+ return render json: { data: "No properties found", properties: [], success: false }, status: :ok if @properties.empty?
20
+
21
+ render json: {
22
+ data: "Data Found",
23
+ properties: ActiveModelSerializers::SerializableResource.new(@properties, each_serializer: PropertyListingSerializer),
24
+ success: true,
25
+ meta: {
26
+ total_pages: total_pages,
27
+ current_page: page,
28
+ next_page: page < total_pages ? page + 1 : nil,
29
+ prev_page: page > 1 ? page - 1 : nil,
30
+ total_count: total_count
31
+ }
32
+ }, status: :ok
33
+ rescue ActiveRecord::RecordNotFound => e
34
+ render json: { success: false, error: "Properties not found", message: e.message }, status: :not_found
35
+ rescue ArgumentError => e
36
+ render json: { success: false, error: "Invalid pagination parameters", message: e.message }, status: :bad_request
37
+ rescue StandardError => e
38
+ render json: { success: false, error: "Internal server error", message: e.message }, status: :internal_server_error
39
+ end
40
+ end
41
+
42
+ def my_properties
43
+ begin
44
+ page = params[:page].to_i > 0 ? params[:page].to_i : 1
45
+ per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 10
46
+
47
+ cumulative_per_page = page * per_page
48
+ @data = current_devise_api_user.properties
49
+ @properties = @data.order(created_at: :asc).limit(cumulative_per_page)
50
+ total_count = @data.count
51
+ total_pages = (total_count.to_f / per_page).ceil
52
+ return render json: { data: "No properties found", properties: [], success: false }, status: :ok if @properties.empty?
53
+ render json: {
54
+ data: "Property Found",
55
+ properties: ActiveModelSerializers::SerializableResource.new(@properties, each_serializer: PropertyListingSerializer),
56
+ success: true,
57
+ meta: {
58
+ total_pages: total_pages,
59
+ current_page: page,
60
+ next_page: page < total_pages ? page + 1 : nil,
61
+ prev_page: page > 1 ? page - 1 : nil,
62
+ total_count: total_count
63
+ }
64
+ }, status: :ok
65
+ rescue ActiveRecord::RecordNotFound => e
66
+ render json: { success: false, error: "Properties not found", message: e.message }, status: :not_found
67
+ rescue ArgumentError => e
68
+ render json: { success: false, error: "Invalid pagination parameters", message: e.message }, status: :bad_request
69
+ rescue StandardError => e
70
+ render json: { success: false, error: "Internal server error", message: e.message }, status: :internal_server_error
71
+ end
72
+ end
73
+
74
+ def show
75
+ render json: { data: "Data Found", property: PropertySerializer.new(@property), success: true }, status: :ok
76
+ end
77
+
78
+ def create
79
+ ActiveRecord::Base.transaction do
80
+ begin
81
+ @property = current_devise_api_user.properties.new(property_params)
82
+ if @property.save
83
+ render json: { message: "Property created", property: PropertySerializer.new(@property), success: true }, status: :created
84
+ else
85
+ raise ActiveRecord::RecordInvalid.new(@property)
86
+ end
87
+ rescue ActiveRecord::RecordInvalid => e
88
+ render json: { error: @property.errors.full_messages.to_sentence, success: false }, status: :unprocessable_entity
89
+ raise ActiveRecord::Rollback
90
+ rescue StandardError => e
91
+ render json: { error: "Something went wrong: #{e.message}", success: false }, status: :unprocessable_entity
92
+ raise ActiveRecord::Rollback
93
+ end
94
+ end
95
+ end
96
+
97
+ def update
98
+ ActiveRecord::Base.transaction do
99
+ if @property.update(property_params)
100
+ render json: {
101
+ message: "property updated",
102
+ property: PropertySerializer.new(@property),
103
+ success: true
104
+ }, status: :created
105
+ else
106
+ raise ActiveRecord::Rollback
107
+ end
108
+ rescue ActiveRecord::RecordInvalid
109
+ render json: {
110
+ message: @property.errors.full_messages,
111
+ success: false
112
+ }, status: :unprocessable_entity
113
+ end
114
+ end
115
+
116
+ def similar_property
117
+ begin
118
+ properties = Stay::Property.similar_properties(params[:property_type_id], params[:property_category_id], params[:property_id])
119
+
120
+ if properties.exists?
121
+ render json: {
122
+ data: "Data Found",
123
+ properties: ActiveModelSerializers::SerializableResource.new(properties, each_serializer: PropertyListingSerializer),
124
+ success: true
125
+ }, status: :ok
126
+ else
127
+ render json: { error: "No property found", success: false }, status: :unprocessable_entity
128
+ end
129
+ rescue StandardError => e
130
+ render json: { error: "No property found ", message: e.message, success: false }, status: :internal_server_error
131
+ end
132
+ end
133
+
134
+
135
+ def search
136
+ amenity_ids = parse_to_array(params[:q][:amenity_ids])
137
+ feature_ids = parse_to_array(params[:q][:feature_ids])
138
+ latitude, longitude = params[:q].values_at(:latitude, :longitude)
139
+
140
+ @q = Stay::Property.approved.active.ransack(params[:q])
141
+ @properties = @q.result.distinct
142
+
143
+ @properties = @properties.with_amenities(amenity_ids) if amenity_ids.any?
144
+ @properties = @properties.with_features(feature_ids) if feature_ids.any?
145
+ @properties = @properties.nearby(latitude, longitude, params[:distance] || 10) if latitude && longitude
146
+ @properties = @properties.by_property_type(params[:q][:property_type_id]) if params[:q][:property_type_id].present?
147
+ @properties = @properties.price_filter(params[:q][:min_price], params[:q][:max_price]) if params[:q][:min_price] && params[:q][:max_price].present?
148
+ @properties = @properties.by_property_category(params[:q][:property_category_id]) if params[:q][:property_category_id].present?
149
+
150
+ @properties = @properties.page(params[:page]).per(params[:per_page] || 10)
151
+
152
+ if @properties.any?
153
+ render json: {
154
+ message: "data found",
155
+ properties: ActiveModelSerializers::SerializableResource.new(@properties, each_serializer: PropertyListingSerializer),
156
+ total_pages: @properties.total_pages,
157
+ current_page: @properties.current_page,
158
+ next_page: @properties.next_page,
159
+ prev_page: @properties.prev_page,
160
+ total_count: @properties.total_count,
161
+ success: true
162
+ }, status: :ok
163
+ else
164
+ render json: { message: "No properties found" }, status: :not_found
165
+ end
166
+ end
167
+
168
+ def property_tax
169
+ @taxes = Stay::Tax.all
170
+ if @taxes.any?
171
+ render json: { message: "tax found", tax: @taxes, success: true }, status: :ok
172
+ else
173
+ render json: { message: "No properties found" }, status: :not_found
174
+ end
175
+ end
176
+
177
+ def resubmit
178
+ render json: { message: "Property resubmitted for approval", data: PropertyListingSerializer.new(@property), success: :true }, status: :ok if @property.resubmit!
179
+ render json: { error: "Property not approved", success: :false }, status: :unprocessable_entity
180
+ end
181
+
182
+ def destroy
183
+ if @property.destroy
184
+ render json: { message: "Property destroyed successfully", success: true }, status: :ok
185
+ else
186
+ render json: { error: "Property not destroyed", success: :false }, status: :unprocessable_entity
187
+ end
188
+ end
189
+
190
+ private
191
+
192
+ def property_params
193
+ params.require(:property).permit(:active, :title, :description, :user_id, :guest_number, :availability_start, :availability_end, :bedroom_description, :cancellation_policy_id,
194
+ :university_nearby, :about_neighbourhoods, :instant_booking, :minimum_months_of_booking, :security_deposit,
195
+ :extra_guest, :allow_extra_guest, :city, :address, :latitude, :longitude, :total_rooms, :total_bathrooms, :state, :country, :zipcode, :property_state,
196
+ :property_size, :property_category_id, :property_type_id, :cover_image, :price_per_month, :taxes_in_percentage, :cleaning_fee, :city_fee,
197
+ :early_bird_discount, :advance_days, :is_city_fee_percentage, :unlimited_availability, place_images: [],
198
+ additional_rules_attributes: [ :id, :name, :_destroy ],
199
+ property_house_rules_attributes: [ :id, :house_rule_id, :value, :_destroy ],
200
+ property_amenities_attributes: [ :id, :amenity_id, :_destroy ],
201
+ property_features_attributes: [ :id, :name, :feature_id, :_destroy ],
202
+ rooms_attributes: [ :id, :max_guests, :price_per_month, :status, :booking_start, :booking_end, :description, :size, :bed_type_id, :room_type_id, :_destroy, room_images: [],
203
+ room_features_attributes: [ :id, :feature_id, :_destroy ],
204
+ room_amenities_attributes: [ :id, :amenity_id, :_destroy ]
205
+ ],
206
+ property_taxes_attributes: [ :id, :tax_id, :value, :_destroy ],
207
+ )
208
+ end
209
+
210
+ def set_property
211
+ begin
212
+ @property = Stay::Property.friendly.find(params[:id])
213
+ rescue ActiveRecord::RecordNotFound => e
214
+ render json: { success: false, error: "Properties not found" }, status: :not_found
215
+ end
216
+ end
217
+
218
+ def parse_to_array(param)
219
+ return [] unless param.present?
220
+ param = JSON.parse(param) if param.is_a?(String)
221
+ Array(param)
222
+ rescue JSON::ParserError
223
+ []
224
+ end
225
+
226
+ def check_create_access
227
+ render json: { error: "You don't have access to create property", success: false }, status: :unprocessable_entity unless current_devise_api_user.stay_host?
228
+ end
229
+
230
+ def check_update_access
231
+ render json: { error: "You don't have access to update this property", success: false }, status: :unprocessable_entity if current_devise_api_user != @property.user
232
+ end
233
+ end
@@ -0,0 +1,14 @@
1
+ class Stay::Api::V1::PropertyCategoriesController < Stay::BaseApiController
2
+ before_action :authenticate_devise_api_token!
3
+
4
+ def index
5
+ @type = Stay::PropertyCategory.all
6
+ render json: { data: ActiveModelSerializers::SerializableResource.new(@type, each_serializer: PropertyCategorySerializer), message: "data found", success: true }, status: :ok
7
+ end
8
+
9
+ def show
10
+ @type = Stay::PropertyCategory.find_by(id: params[:id])
11
+ return render json: { error: "no data found", success: false }, status: :unprocessable_entity if @type.nil?
12
+ render json: { data: PropertyCategorySerializer.new(@type), message: "data found", success: true }, status: :ok
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ class Stay::Api::V1::PropertyTypesController < Stay::BaseApiController
2
+ before_action :authenticate_devise_api_token!
3
+
4
+ def index
5
+ @type = Stay::PropertyType.all
6
+ render json: { data: ActiveModelSerializers::SerializableResource.new(@type, each_serializer: PropertyTypeSerializer), message: "data found", success: true }, status: :ok
7
+ end
8
+
9
+ def show
10
+ @type = Stay::PropertyType.find_by(id: params[:id])
11
+ return render json: { error: "no data found", success: false }, status: :unprocessable_entity if @type.nil?
12
+ render json: { data: PropertyTypeSerializer.new(@type), message: "data found", success: true }, status: :ok
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ class Stay::Api::V1::RoomTypesController < Stay::BaseApiController
2
+ before_action :authenticate_devise_api_token!
3
+
4
+ def index
5
+ @type = Stay::RoomType.all
6
+ render json: { data: ActiveModelSerializers::SerializableResource.new(@type, each_serializer: RoomTypeSerializer), message: "data found", success: true }, status: :ok
7
+ end
8
+
9
+ def show
10
+ @type = Stay::RoomType.find_by(id: params[:id])
11
+ return render json: { error: "no data found", success: false }, status: :unprocessable_entity if @type.nil?
12
+ render json: { data: RoomTypeSerializer.new(@type), message: "data found", success: true }, status: :ok
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ class Stay::Api::V1::RoomsController < Stay::BaseApiController
2
+ before_action :authenticate_devise_api_token!
3
+ before_action :set_property
4
+ before_action :set_room, only: [ :show ]
5
+
6
+ def index
7
+ @rooms = @property.rooms
8
+ render json: { rooms: @rooms }
9
+ end
10
+
11
+ def show
12
+ render json: { room: @room }
13
+ end
14
+
15
+ private
16
+ def set_property
17
+ @property = Stay::Property.find(params[:property_id])
18
+ end
19
+
20
+ def set_room
21
+ @room = @property.rooms.find(params[:id])
22
+ end
23
+ end
@@ -0,0 +1,53 @@
1
+ class Stay::Api::V1::UserPaypalController < Stay::BaseApiController
2
+ before_action :authenticate_devise_api_token!
3
+ before_action :set_paypal, only: %i[show edit update]
4
+
5
+ def index
6
+ @paypal = current_devise_api_user.user_paypal
7
+ if @paypal.present?
8
+ render json: {
9
+ message: "paypal account found",
10
+ data: @paypal,
11
+ success: true },
12
+ status: :ok
13
+ else
14
+ render json: { error: "No paypal account found", success: false }, status: :unprocessable_entity
15
+ end
16
+ end
17
+
18
+ def show
19
+ render json: { data: @paypal, success: true }, status: :ok
20
+ end
21
+
22
+ def create
23
+ paypal = current_devise_api_user.build_user_paypal(user_paypal_params)
24
+ if paypal.save
25
+ render json: { message: "PayPal account saved successfully", data: paypal, success: true }, status: :ok
26
+ else
27
+ render json: { error: "PayPal account not saved", success: false, errors: paypal.errors.full_messages }, status: :unprocessable_entity
28
+ end
29
+ end
30
+
31
+
32
+ def edit
33
+ render json: { data: paypal, success: true }, status: :ok
34
+ end
35
+
36
+ def update
37
+ if @paypal.update(user_paypal_params)
38
+ render json: { message: "Credit card updated successfully", data: @paypal, success: true }, status: :ok
39
+ else
40
+ render json: { error: "Credit card not updated", success: false, errors: paypal.errors.full_messages }, status: :unprocessable_entity
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def set_paypal
47
+ @paypal = current_devise_api_user.user_paypal
48
+ end
49
+
50
+ def user_paypal_params
51
+ params.require(:user_paypal).permit(:email, :user_id)
52
+ end
53
+ end