stay_commerce-frontend 0.1.0 → 0.1.1

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/bundle.css +8665 -6069
  3. data/app/assets/builds/bundle.css.map +3 -3
  4. data/app/assets/builds/bundle.js +37877 -27557
  5. data/app/assets/builds/bundle.js.map +4 -4
  6. data/app/assets/builds/styles.css +6328 -5031
  7. data/app/assets/builds/styles.css.map +3 -3
  8. data/app/javascript/react/components/Accountpage/AccountInfo.jsx +2 -1
  9. data/app/javascript/react/components/AddNewProperty/CommonLayout.jsx +0 -2
  10. data/app/javascript/react/components/AddNewProperty/Description.jsx +51 -52
  11. data/app/javascript/react/components/AddNewProperty/Details.jsx +212 -129
  12. data/app/javascript/react/components/AddNewProperty/Images.jsx +122 -45
  13. data/app/javascript/react/components/AddNewProperty/Location.jsx +21 -14
  14. data/app/javascript/react/components/AddNewProperty/Room.jsx +639 -548
  15. data/app/javascript/react/components/AvatarDropdown/AvatarDropDown.jsx +9 -1
  16. data/app/javascript/react/components/FacilitiesSection/Facilities.jsx +18 -0
  17. data/app/javascript/react/components/FixedNavbar/FixedNav.jsx +20 -14
  18. data/app/javascript/react/components/HeroSectionDesign/BookingForm.jsx +136 -88
  19. data/app/javascript/react/components/HeroSectionDesign/MyPropertiesListing.jsx +79 -69
  20. data/app/javascript/react/components/Layout/Layout.js +8 -1
  21. data/app/javascript/react/components/Listing-stay-Detail/ApartmentCard.jsx +3 -3
  22. data/app/javascript/react/components/Listing-stay-Detail/BookingModal.jsx +167 -122
  23. data/app/javascript/react/components/Listing-stay-Detail/CardManager.jsx +285 -0
  24. data/app/javascript/react/components/Listing-stay-Detail/CheckoutForm.jsx +147 -84
  25. data/app/javascript/react/components/Listing-stay-Detail/ListingStayDetailPage.jsx +1 -7
  26. data/app/javascript/react/components/Listing-stay-Detail/PropertiesPage.jsx +464 -0
  27. data/app/javascript/react/components/MobileNav/MobileMenu.jsx +1 -4
  28. data/app/javascript/react/components/PropertyListing/MyProperties.jsx +45 -44
  29. data/app/javascript/react/components/PropertyListing/StayBooking/BookingDetails.jsx +4 -4
  30. data/app/javascript/react/components/PropertyListing/StayBooking/MyBooking.jsx +41 -29
  31. data/app/javascript/react/components/StayCard/StayCard.jsx +5 -3
  32. data/app/javascript/react/packs/index.jsx +1 -0
  33. data/app/javascript/react/packs/routes/Route.jsx +18 -1
  34. data/app/javascript/react/pages/Home.jsx +6 -4
  35. data/app/javascript/react/redux/slices/PropertySlice/PropertySlice.jsx +21 -21
  36. data/app/javascript/react/redux/slices/PropertySlice/Searchslice.jsx +53 -6
  37. data/app/javascript/react/redux/slices/UserSlice/UserSlice.jsx +1 -0
  38. data/app/javascript/react/shared/Avatar/Avatar.jsx +5 -8
  39. data/app/javascript/react/shared/Button/SecondryButton.jsx +9 -0
  40. data/app/javascript/react/shared/Loader.jsx +13 -0
  41. data/app/javascript/react/shared/Pagination.jsx +53 -0
  42. data/app/javascript/react/shared/Schema/FormSchema +143 -0
  43. data/app/javascript/react/styles/BookingDetails.scss +1 -0
  44. data/app/javascript/react/styles/CardManager.scss +608 -0
  45. data/app/javascript/react/styles/Loader.scss +30 -0
  46. data/app/javascript/react/styles/Pagination.scss +33 -0
  47. data/app/javascript/react/styles/PropertiesPage.scss +0 -4
  48. data/app/javascript/react/styles/RenderSection.scss +1 -0
  49. data/app/javascript/react/styles/accountpage.scss +3 -0
  50. data/app/javascript/react/styles/application.scss +13 -1
  51. data/app/javascript/react/styles/bookingform.scss +56 -28
  52. data/app/javascript/react/styles/buttonSecondry.scss +24 -0
  53. data/app/javascript/react/styles/checkbox.scss +34 -35
  54. data/app/javascript/react/styles/commonlayout.scss +7 -2
  55. data/app/javascript/react/styles/commonpage.scss +5 -1
  56. data/app/javascript/react/styles/description.scss +3 -0
  57. data/app/javascript/react/styles/facilities.scss +2 -1
  58. data/app/javascript/react/styles/fixednavbar.scss +8 -0
  59. data/app/javascript/react/styles/listingstaydetailpage.scss +5 -0
  60. data/app/javascript/react/styles/mobilemenu.scss +0 -1
  61. data/app/javascript/react/styles/mybooking.scss +20 -0
  62. data/app/javascript/react/styles/myproperty.scss +26 -0
  63. data/app/javascript/react/styles/propertydetailscard.scss +265 -267
  64. data/app/javascript/react/styles/react-datepicker/react-datepicker.css +869 -0
  65. data/app/javascript/react/styles/room.scss +13 -8
  66. data/app/javascript/react/utils/helpers/ToastErros.js +12 -0
  67. data/db/migrate/20250627101451_add_role_to_stay_users.rb +5 -0
  68. data/lib/stay_commerce/frontend/version.rb +1 -1
  69. metadata +15 -5
  70. data/app/javascript/react/components/HeroSectionDesign/PropertiesPage.jsx +0 -122
  71. data/app/javascript/react/shared/DateField/CustomDatePicker.jsx +0 -69
  72. data/app/javascript/react/styles/customdatepicker.scss +0 -120
@@ -73,6 +73,14 @@ export default function AvatarDropdown() {
73
73
  { name: "Contact", href: "/contact", icon: PhoneIcon },
74
74
  ];
75
75
 
76
+ if (!user?.is_host) {
77
+ options.push({
78
+ name: "AddCard",
79
+ href: "/AddCard",
80
+ icon: LifebuoyIcon,
81
+ });
82
+ }
83
+
76
84
  if (user?.is_host) {
77
85
  options.push({
78
86
  name: "My Properties",
@@ -100,7 +108,7 @@ export default function AvatarDropdown() {
100
108
  return (
101
109
  <div className="avatar-dropdown" ref={dropdownRef}>
102
110
  <button onClick={() => setIsOpen(!isOpen)} className="avatar-button">
103
- <Avatar />
111
+ <Avatar userData={user} />
104
112
  </button>
105
113
 
106
114
  {isOpen && (
@@ -37,6 +37,24 @@ const features = [
37
37
  description:
38
38
  "Enjoy premium beverages and cocktails in our elegant bar lounge.",
39
39
  },
40
+ {
41
+ icon: "🍽️",
42
+ title: "Restaurant",
43
+ description:
44
+ "Experience fine dining with our world-class restaurant offering exquisite cuisine.",
45
+ },
46
+ {
47
+ icon: "🚴",
48
+ title: "Sports Club",
49
+ description:
50
+ "Stay active with our premium sports facilities and professional equipment.",
51
+ },
52
+ {
53
+ icon: "👕",
54
+ title: "Swimming Pool",
55
+ description:
56
+ "Relax and unwind in our luxurious swimming pool with crystal clear water.",
57
+ },
40
58
  ];
41
59
 
42
60
  const FacilitiesSection = () => {
@@ -1,32 +1,34 @@
1
- import React from "react";
1
+ import React, { useEffect } from "react";
2
2
  import { Link, useLocation, useNavigate } from "react-router-dom";
3
3
  import { useSelector, useDispatch } from "react-redux";
4
- import { logout } from "../../redux/slices/AuthSlice/AuthSlice";
5
4
  import MobileMenu from "../MobileNav/MobileMenu";
6
5
  import "../../styles/fixednavbar.scss";
7
6
  import AvatarDropDown from "../AvatarDropdown/AvatarDropDown";
8
- import logo from "../../assets/logo_updated.png";
7
+ // import logo from "../../assets/logo_updated.png";
9
8
 
10
9
  // React Icons
11
10
  import { IoHomeOutline } from "react-icons/io5";
12
11
  import { MdInfoOutline } from "react-icons/md";
13
12
  import { FaBed, FaImages, FaBlogger } from "react-icons/fa";
13
+ import { getCurrentUser } from "../../redux/slices/UserSlice/UserSlice";
14
14
 
15
15
  function FixedNavbar() {
16
16
  const location = useLocation();
17
17
  const navigate = useNavigate();
18
18
  const dispatch = useDispatch();
19
19
  const { user } = useSelector((state) => state.auth);
20
+ const { data: currentUser, loading } = useSelector((state) => state.user);
20
21
 
21
- const handleLogout = () => {
22
- dispatch(logout());
23
- navigate("/");
24
- };
22
+ useEffect(() => {
23
+ if (currentUser) {
24
+ dispatch(getCurrentUser());
25
+ }
26
+ }, [dispatch]);
25
27
 
26
28
  const navItems = [
27
29
  { name: "Home", path: "/", icon: <IoHomeOutline /> },
28
30
  { name: "About us", path: "/about-us", icon: <MdInfoOutline /> },
29
- { name: "Accommodation", path: "/accommodation", icon: <FaBed /> },
31
+ // { name: "Accommodation", path: "/accommodation", icon: <FaBed /> },
30
32
  { name: "Gallery", path: "/gallery", icon: <FaImages /> },
31
33
  // { name: "Blog", path: "/blog", icon: <FaBlogger /> },
32
34
  ];
@@ -37,8 +39,16 @@ function FixedNavbar() {
37
39
  <div className="navContent">
38
40
  <div className="logo">
39
41
  <span className="logospan">
40
- <a href="/">
41
- <img src={logo} width={140} alt="Logo" />
42
+ <a
43
+ style={{
44
+ fontWeight: "bold",
45
+ textDecoration: "none",
46
+ color: "#081976",
47
+ }}
48
+ >
49
+ <h4 style={{ margin: 0, fontWeight: "bold", fontSize: "24px" }}>
50
+ STAY COMMERCE
51
+ </h4>
42
52
  </a>
43
53
  </span>
44
54
  </div>
@@ -61,9 +71,6 @@ function FixedNavbar() {
61
71
  <div className="authButtons">
62
72
  {user ? (
63
73
  <>
64
- <button onClick={handleLogout} className="logoutButton">
65
- LOGOUT
66
- </button>
67
74
  <AvatarDropDown />
68
75
  </>
69
76
  ) : (
@@ -77,7 +84,6 @@ function FixedNavbar() {
77
84
  </>
78
85
  )}
79
86
  </div>
80
-
81
87
  <MobileMenu />
82
88
  </div>
83
89
  </div>
@@ -4,67 +4,58 @@ import ButtonPrimary from "../../shared/Button/ButtonPrimary";
4
4
  import { useFormik } from "formik";
5
5
  import { useNavigate } from "react-router-dom";
6
6
  import moment from "moment";
7
- import { useDispatch } from "react-redux";
8
- import { searchProperties } from "../../redux/slices/PropertySlice/PropertySlice";
9
- import { setSearchMeta } from "../../redux/slices/PropertySlice/Searchslice";
7
+ import { useDispatch, useSelector } from "react-redux";
8
+ import {
9
+ searchProperties,
10
+ setSearchMeta,
11
+ } from "../../redux/slices/PropertySlice/Searchslice";
12
+ import { toast } from "react-toastify";
13
+ import DatePicker from "react-datepicker";
14
+ import "react-datepicker/dist/react-datepicker.css";
15
+ import Autocomplete from "react-google-autocomplete";
10
16
 
11
17
  function BookingForm() {
12
18
  const navigate = useNavigate();
13
19
  const dispatch = useDispatch();
14
20
  const [isLoading, setIsLoading] = useState(false);
15
- const [latLng, setLatLng] = useState({ lat: null, lng: null });
16
-
21
+ const { address, startDate, endDate, totalGuests, latitude, longitude } =
22
+ useSelector((state) => state.search);
17
23
  const initialValues = {
18
- address: "",
19
- arrivalDate: "",
20
- departureDate: "",
21
- adults: 1,
22
- };
23
-
24
- const getLatLngFromAddress = async (address) => {
25
- const response = await fetch(
26
- `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(
27
- address
28
- )}`
29
- );
30
- const data = await response.json();
31
- if (data.length > 0) {
32
- return {
33
- lat: data[0].lat,
34
- lng: data[0].lon,
35
- };
36
- }
37
- return { lat: null, lng: null };
24
+ address: address || "",
25
+ arrivalDate: startDate || "",
26
+ departureDate: endDate || "",
27
+ adults: totalGuests || 1,
28
+ latitude: latitude || null,
29
+ longitude: longitude || null,
38
30
  };
39
31
 
40
32
  const onSubmit = async (values) => {
41
33
  setIsLoading(true);
42
34
  try {
43
- const { lat, lng } = await getLatLngFromAddress(values.address);
44
- setLatLng({ lat, lng });
45
-
46
35
  const modifiedStartDate = moment(values.arrivalDate).format("YYYY-MM-DD");
47
36
  const modifiedEndDate = moment(values.departureDate).format("YYYY-MM-DD");
48
37
 
49
- const searchQuery = `q[availability_start_lteq]=${modifiedStartDate}&q[availability_end_gteq]=${modifiedEndDate}&q[guest_number_gteq]=${values.adults}&q[latitude]=${lat}&q[longitude]=${lng}`;
38
+ const searchQuery = `q[availability_start_lteq]=${modifiedStartDate}&q[availability_end_gteq]=${modifiedEndDate}&q[guest_number_gteq]=${values.adults}&q[latitude]=${values.latitude}&q[longitude]=${values.longitude}`;
50
39
 
51
40
  const action = await dispatch(searchProperties(searchQuery)).unwrap();
52
41
 
53
- if (action?.success) {
42
+ if (Array.isArray(action?.properties) && action.properties.length > 0) {
54
43
  dispatch(
55
44
  setSearchMeta({
56
45
  startDate: values.arrivalDate,
57
46
  endDate: values.departureDate,
58
47
  totalGuests: values.adults,
59
48
  address: values.address,
60
- latitude: lat,
61
- longitude: lng,
49
+ latitude: values.latitude,
50
+ longitude: values.longitude,
62
51
  })
63
52
  );
64
53
  navigate("/listingSearchPage");
54
+ } else {
55
+ toast.info("No properties found for the selected criteria.");
65
56
  }
66
57
  } catch (error) {
67
- console.error("Search error:", error);
58
+ console.error("Search error caught:", error);
68
59
  } finally {
69
60
  setIsLoading(false);
70
61
  }
@@ -75,10 +66,10 @@ function BookingForm() {
75
66
  onSubmit,
76
67
  validate: (values) => {
77
68
  const errors = {};
78
- if (!values.address) errors.address = "Required";
79
- if (!values.arrivalDate) errors.arrivalDate = "Required";
69
+ if (!values.address) errors.address = "Location is required";
70
+ if (!values.arrivalDate) errors.arrivalDate = "Arrival date is required";
80
71
  if (!values.departureDate) {
81
- errors.departureDate = "Required";
72
+ errors.departureDate = "Departure date is required";
82
73
  } else if (values.departureDate <= values.arrivalDate) {
83
74
  errors.departureDate = "Departure must be after arrival";
84
75
  }
@@ -93,48 +84,107 @@ function BookingForm() {
93
84
  <div className="booking-table">
94
85
  <form onSubmit={formik.handleSubmit} className="form-fields">
95
86
  <div className="form-row">
96
- <div className="input-group">
97
- <input
98
- type="text"
99
- className="form-control"
100
- placeholder="Enter Address"
101
- name="address"
102
- value={formik.values.address}
103
- onChange={formik.handleChange}
104
- onBlur={formik.handleBlur}
105
- />
87
+ <div className="input-wrapper">
88
+ <div
89
+ className={`input-group ${
90
+ formik.touched.address && formik.errors.address
91
+ ? "has-error"
92
+ : ""
93
+ }`}
94
+ >
95
+ <Autocomplete
96
+ apiKey="AIzaSyA-ZbTjLDeHfCHLbWtqpTOYY64PcwnH7bQ"
97
+ style={{
98
+ width: "100%",
99
+ padding: "8px",
100
+ border: "none",
101
+ outline: "none",
102
+ }}
103
+ value={formik.values.address}
104
+ onPlaceSelected={(place) => {
105
+ const address =
106
+ place.formatted_address || place.name || "";
107
+ const lat = place.geometry?.location?.lat();
108
+ const lng = place.geometry?.location?.lng();
109
+
110
+ formik.setFieldValue("address", address);
111
+ formik.setFieldValue("latitude", lat);
112
+ formik.setFieldValue("longitude", lng);
113
+ formik.setFieldTouched("address", true);
114
+ }}
115
+ onChange={(e) => {
116
+ formik.setFieldValue("address", e.target.value);
117
+ }}
118
+ />
119
+ </div>
106
120
  {formik.touched.address && formik.errors.address && (
107
121
  <div className="error-message">{formik.errors.address}</div>
108
122
  )}
109
123
  </div>
110
- <div className="input-group">
111
- <input
112
- type="date"
113
- className="form-control"
114
- name="arrivalDate"
115
- value={formik.values.arrivalDate}
116
- onChange={formik.handleChange}
117
- onBlur={formik.handleBlur}
118
- min={moment().format("YYYY-MM-DD")}
119
- />
124
+ <div className="input-wrapper">
125
+ <div
126
+ className={`input-group ${
127
+ formik.touched.arrivalDate && formik.errors.arrivalDate
128
+ ? "has-error"
129
+ : ""
130
+ }`}
131
+ >
132
+ <DatePicker
133
+ selected={
134
+ formik.values.arrivalDate
135
+ ? new Date(formik.values.arrivalDate)
136
+ : null
137
+ }
138
+ onChange={(date) => {
139
+ formik.setFieldValue("arrivalDate", date);
140
+ formik.setFieldValue("departureDate", null); // reset departure
141
+ }}
142
+ className="form-control"
143
+ name="arrivalDate"
144
+ dateFormat="yyyy-MM-dd"
145
+ minDate={new Date()}
146
+ placeholderText="Arrival Date"
147
+ isClearable
148
+ />
149
+ </div>
120
150
  {formik.touched.arrivalDate && formik.errors.arrivalDate && (
121
151
  <div className="error-message">
122
152
  {formik.errors.arrivalDate}
123
153
  </div>
124
154
  )}
125
155
  </div>
126
- <div className="input-group">
127
- <input
128
- type="date"
129
- className="form-control"
130
- name="departureDate"
131
- value={formik.values.departureDate}
132
- onChange={formik.handleChange}
133
- onBlur={formik.handleBlur}
134
- min={
135
- formik.values.arrivalDate || moment().format("YYYY-MM-DD")
136
- }
137
- />
156
+ <div className="input-wrapper">
157
+ <div
158
+ className={`input-group ${
159
+ formik.touched.departureDate &&
160
+ formik.errors.departureDate
161
+ ? "has-error"
162
+ : ""
163
+ }`}
164
+ >
165
+ <DatePicker
166
+ selected={
167
+ formik.values.departureDate
168
+ ? new Date(formik.values.departureDate)
169
+ : null
170
+ }
171
+ onChange={(date) => {
172
+ formik.setFieldValue("departureDate", date);
173
+ }}
174
+ className="form-control"
175
+ name="departureDate"
176
+ dateFormat="yyyy-MM-dd"
177
+ minDate={
178
+ formik.values.arrivalDate
179
+ ? moment(formik.values.arrivalDate)
180
+ .add(1, "days")
181
+ .toDate()
182
+ : moment().add(1, "days").toDate()
183
+ }
184
+ placeholderText="Departure Date"
185
+ isClearable
186
+ />
187
+ </div>
138
188
  {formik.touched.departureDate &&
139
189
  formik.errors.departureDate && (
140
190
  <div className="error-message">
@@ -142,28 +192,26 @@ function BookingForm() {
142
192
  </div>
143
193
  )}
144
194
  </div>
145
- <div className="input-group">
146
- <select
147
- className="form-control"
148
- name="adults"
149
- value={formik.values.adults}
150
- onChange={formik.handleChange}
151
- onBlur={formik.handleBlur}
152
- >
153
- <option value={1}>1 Adult</option>
154
- <option value={2}>2 Adults</option>
155
- <option value={3}>3 Adults</option>
156
- <option value={4}>4 Adults</option>
157
- <option value={5}>5+ Adults</option>
158
- </select>
195
+ <div className="input-wrapper">
196
+ <div className="input-group">
197
+ <select
198
+ className="form-control"
199
+ name="adults"
200
+ value={formik.values.adults}
201
+ onChange={formik.handleChange}
202
+ onBlur={formik.handleBlur}
203
+ >
204
+ <option value={1}>1 Adult</option>
205
+ <option value={2}>2 Adults</option>
206
+ <option value={3}>3 Adults</option>
207
+ <option value={4}>4 Adults</option>
208
+ <option value={5}>5+ Adults</option>
209
+ </select>
210
+ </div>
159
211
  </div>
160
212
  <div className="book-now-container">
161
- <ButtonPrimary
162
- className="book-now-btn"
163
- type="submit"
164
- loading={isLoading}
165
- >
166
- BOOK NOW
213
+ <ButtonPrimary type="submit" loading={isLoading}>
214
+ Search
167
215
  </ButtonPrimary>
168
216
  </div>
169
217
  </div>
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import GallerySlider from "../GallerySlider/GallerySlider";
3
3
  import { useNavigate } from "react-router-dom";
4
+ import SecondryButton from "../../shared/Button/SecondryButton";
4
5
 
5
6
  const MyPropertiesListing = ({
6
7
  heading = "Explore Travel Experiences",
@@ -12,89 +13,98 @@ const MyPropertiesListing = ({
12
13
  const handleClick = (id) => {
13
14
  navigate(`/listing-stay-detail/${id}`);
14
15
  };
15
- console.log("stayListings", stayListings);
16
16
  const handleViewAll = (slug) => navigate(`/property-1/${slug}`);
17
+
18
+ const truncateText = (text, maxLength) => {
19
+ if (!text) return "";
20
+ return text.length > maxLength ? text.slice(0, maxLength) + "..." : text;
21
+ };
22
+
17
23
  return (
18
24
  <div className="properties-page">
19
25
  <div className="container">
20
26
  <h2>{heading}</h2>
21
27
  <div className="property-grid grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
22
- {stayListings.map((property, index) => (
23
- <div key={property.id || index} className="property-card">
24
- <div className="card-image-section">
25
- {property.property_state && (
26
- <div className="discount-badge">
27
- {{
28
- approved: "Approved",
29
- waiting_for_approval: "Waiting for Approval",
30
- }[property.property_state] || "Unknown Status"}
31
- </div>
32
- )}
28
+ {stayListings && stayListings?.length > 0 ? (
29
+ stayListings.map((property, index) => (
30
+ <div key={property.id || index} className="property-card">
31
+ <div className="card-image-section">
32
+ {property.property_state && (
33
+ <div className="discount-badge">
34
+ {{
35
+ approved: "Approved",
36
+ waiting_for_approval: "Waiting for Approval",
37
+ }[property.property_state] || "Unknown Status"}
38
+ </div>
39
+ )}
33
40
 
34
- <GallerySlider
35
- images={property.place_images || []}
36
- alt={property.title}
37
- style={{ height: "220px" }}
38
- />
39
- </div>
40
- <div className="card-content">
41
- <div className="location-duration">
42
- <span className="location">
43
- {property.location || property.address}
44
- </span>
41
+ <GallerySlider
42
+ images={property.place_images || []}
43
+ alt={property.title}
44
+ style={{ height: "220px" }}
45
+ />
45
46
  </div>
46
- <h3 className="property-title">{property.title}</h3>
47
- <p className="description">{property.description}</p>
47
+ <div className="card-content">
48
+ <div className="location-duration">
49
+ <span className="location">
50
+ {property.location || property.address}
51
+ </span>
52
+ </div>
53
+ <h3 className="property-title">{property.title}</h3>
54
+ <p className="description">
55
+ {truncateText(property?.description, 170)}
56
+ </p>
48
57
 
49
- <div className="card-footer">
50
- <div className="features">
51
- {property.property_category && (
52
- <span className="feature-tag">
53
- {property.property_category}
54
- </span>
55
- )}
56
- {property.property_type && (
57
- <span className="feature-tag">
58
- {property.freeCancellation
59
- ? "Free Cancellation"
60
- : property.property_type}
61
- </span>
62
- )}
58
+ <div className="card-footer">
59
+ <div className="features">
60
+ {property.property_category && (
61
+ <span className="feature-tag">
62
+ {property.property_category}
63
+ </span>
64
+ )}
65
+ {property.property_type && (
66
+ <span className="feature-tag">
67
+ {property.freeCancellation
68
+ ? "Free Cancellation"
69
+ : property.property_type}
70
+ </span>
71
+ )}
72
+ </div>
63
73
  </div>
64
74
  </div>
65
- </div>
66
-
67
- <div className="custom-border"></div>
68
-
69
- <div className="price-section">
70
- <button
71
- className="view-details-btn"
72
- onClick={() => handleViewAll(property.slug)}
73
- >
74
- <svg className="icon" viewBox="0 0 24 24" fill="none">
75
- <path
76
- stroke="currentColor"
77
- strokeWidth="1.5"
78
- strokeLinecap="round"
79
- strokeLinejoin="round"
80
- d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
81
- />
82
- </svg>
83
- </button>
84
- <div className="price-info">
85
- <span className="price">
86
- From - ${property.price || "500"}
87
- </span>
88
- <button
89
- className="view-details-btn"
90
- onClick={() => handleClick(property.slug)}
75
+ <div className="custom-border"></div>
76
+ <div className="price-section">
77
+ <SecondryButton
78
+ // className="view-secondary-btn"
79
+ onClick={() => handleViewAll(property.slug)}
91
80
  >
92
- View Details
93
- </button>
81
+ <svg className="icon" viewBox="0 0 24 24" fill="none">
82
+ <path
83
+ stroke="currentColor"
84
+ strokeWidth="1.5"
85
+ strokeLinecap="round"
86
+ strokeLinejoin="round"
87
+ d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
88
+ />
89
+ </svg>
90
+ </SecondryButton>
91
+ <div className="price-info">
92
+ <span className="price">
93
+ From - ${property.price || "500"}
94
+ </span>
95
+ <button
96
+ className="view-details-btn"
97
+ onClick={() => handleClick(property.slug)}
98
+ >
99
+ View Details
100
+ </button>
101
+ </div>
94
102
  </div>
95
103
  </div>
96
- </div>
97
- ))}
104
+ ))
105
+ ) : (
106
+ <div className="no-property-message">No property found</div>
107
+ )}
98
108
  </div>
99
109
  </div>
100
110
  </div>
@@ -1,9 +1,16 @@
1
- import React from "react";
1
+ import React, { useEffect } from "react";
2
+ import { useLocation } from "react-router-dom";
2
3
  import FixedNavbar from "../FixedNavbar/FixedNav";
3
4
  import Footer from "../../shared/FooterSection/Footer";
4
5
  import { Outlet } from "react-router-dom";
5
6
 
6
7
  const Layout = () => {
8
+ const { pathname } = useLocation();
9
+
10
+ useEffect(() => {
11
+ window.scrollTo(0, 0); // Scroll to top on route change
12
+ }, [pathname]);
13
+
7
14
  return (
8
15
  <>
9
16
  <FixedNavbar />
@@ -16,8 +16,8 @@ const ApartmentCard = () => {
16
16
  const Address = `${bookingRequestDetails?.property?.city}, ${bookingRequestDetails?.property?.state}`;
17
17
  const period = `${bookingRequestDetails?.check_in_date} to ${bookingRequestDetails?.check_out_date}`;
18
18
  const requestedBy = bookingRequestDetails?.user?.full_name;
19
- const roomName = bookingRequestDetails?.line_items[0]?.rooms?.name;
20
- const roomImages = bookingRequestDetails?.line_items[0]?.rooms?.room_images;
19
+ const roomName = bookingRequestDetails?.rooms[0]?.name;
20
+ const roomImages = bookingRequestDetails?.rooms[0]?.room_images;
21
21
  const navigate = useNavigate();
22
22
 
23
23
  const fetchAllManageBooking = async () => {
@@ -68,7 +68,7 @@ const ApartmentCard = () => {
68
68
  style={{
69
69
  marginTop: 20,
70
70
  padding: "10px 24px",
71
- backgroundColor: "#6772e5",
71
+ backgroundColor: "var(--primary-color)",
72
72
  color: "#fff",
73
73
  fontSize: "16px",
74
74
  fontWeight: 600,