@anker-in/ui 0.1.8 → 0.1.10

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.
package/dist/index.js CHANGED
@@ -73,7 +73,10 @@ var StudioCard = ({
73
73
  "div",
74
74
  {
75
75
  ...props,
76
- className: cn("p-6 cursor-pointer transition-colors duration-200", className),
76
+ className: cn(
77
+ "p-6 cursor-pointer transition-colors duration-200",
78
+ className
79
+ ),
77
80
  style: {
78
81
  backgroundColor: isHovered ? "#f3f4f6" : "transparent",
79
82
  ...style
@@ -95,7 +98,7 @@ var StudioCard = ({
95
98
  pageData.away
96
99
  ] })
97
100
  ] }),
98
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 mb-3", children: [
101
+ availableTime && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 mb-3", children: [
99
102
  /* @__PURE__ */ jsxRuntime.jsxs(
100
103
  "svg",
101
104
  {
@@ -149,7 +152,7 @@ var StudioCard = ({
149
152
  }
150
153
  ),
151
154
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-600", children: [
152
- pageData.available,
155
+ availableTime === pageData.noAvailableTime ? "" : pageData.available,
153
156
  " ",
154
157
  availableTime
155
158
  ] }) })
@@ -358,18 +361,22 @@ var StudioMap = ({
358
361
  validLocations.forEach((location) => {
359
362
  const lat = Number(location.lat);
360
363
  const lng = Number(location.lng);
364
+ const svgIcon = {
365
+ url: `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(`
366
+ <svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
367
+ <circle cx="24" cy="24" r="22" fill="#00000010"/>
368
+ <circle cx="24" cy="24" r="10" fill="#000000"/>
369
+ <circle cx="24" cy="24" r="5" fill="#3ADB67"/>
370
+ </svg>
371
+ `)}`,
372
+ scaledSize: { width: 48, height: 48 },
373
+ anchor: { x: 24, y: 24 }
374
+ };
361
375
  const marker = new google.maps.Marker({
362
376
  position: { lat, lng },
363
377
  map: googleMapRef.current,
364
378
  title: location.name,
365
- icon: {
366
- path: google.maps.SymbolPath.CIRCLE,
367
- scale: 10,
368
- fillColor: "#000000",
369
- fillOpacity: 1,
370
- strokeColor: "#ffffff",
371
- strokeWeight: 2
372
- }
379
+ icon: svgIcon
373
380
  });
374
381
  marker.addListener("click", () => {
375
382
  setSelectedLocation(location);
@@ -380,7 +387,7 @@ var StudioMap = ({
380
387
  <svg style="display: inline-block; width: 16px; height: 16px; margin-right: 4px; vertical-align: middle;" fill="currentColor" viewBox="0 0 20 20">
381
388
  <path d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z"/>
382
389
  </svg>
383
- <span style="vertical-align: middle;">${pageData.available} ${location.availableTime}</span>
390
+ <span style="vertical-align: middle;"> ${location.availableTime === pageData?.noAvailableTime ? "" : pageData.available} ${location.availableTime}</span>
384
391
  </div>` : ""}
385
392
  <div style="margin-bottom: 8px; color: #666;">
386
393
  <svg style="display: inline-block; width: 16px; height: 16px; margin-right: 4px; vertical-align: middle;" fill="currentColor" viewBox="0 0 20 20">
@@ -1081,6 +1088,7 @@ var defaultPageData = {
1081
1088
  title: "Find a Studio Near You",
1082
1089
  loadingText: "Loading demo rooms...",
1083
1090
  errorTitle: "Failed to load demo rooms",
1091
+ machine: "eufymake E1",
1084
1092
  locationFilter: {
1085
1093
  allLocations: "All Locations",
1086
1094
  clear: "Clear",
@@ -1263,13 +1271,13 @@ var RoomsList = ({
1263
1271
  state,
1264
1272
  zipCode: "",
1265
1273
  country,
1266
- lat: Number(room.latitude) || 34.0522,
1267
- lng: Number(room.longitude) || -118.2437,
1274
+ lat: Number(room.latitude) || 0,
1275
+ lng: Number(room.longitude) || 0,
1268
1276
  availableTime: nextAvailableTimeslot ? `${nextAvailableTimeslot.start_time}` : mergedPageData.noAvailableTime,
1269
1277
  euifyMakeModel: room?.description
1270
1278
  };
1271
1279
  });
1272
- }, [demoRooms]);
1280
+ }, [demoRooms, mergedPageData.defaultCountry, mergedPageData.noAvailableTime]);
1273
1281
  const filteredStudioLocations = React2.useMemo(() => {
1274
1282
  if (!selectedLocation) return studioLocations;
1275
1283
  return studioLocations.filter((location) => {
@@ -1351,7 +1359,7 @@ var RoomsList = ({
1351
1359
  }
1352
1360
  ),
1353
1361
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex text-[#767880] cursor-not-allowed", children: [
1354
- "eufymake E1",
1362
+ mergedPageData.machine,
1355
1363
  /* @__PURE__ */ jsxRuntime.jsx(
1356
1364
  "svg",
1357
1365
  {
@@ -1391,7 +1399,10 @@ var RoomsList = ({
1391
1399
  onSchedule,
1392
1400
  onMouseEnter: () => setHoveredRoomId(item.id),
1393
1401
  onMouseLeave: () => setHoveredRoomId(null),
1394
- pageData: mergedPageData.studioCard
1402
+ pageData: {
1403
+ ...mergedPageData.studioCard,
1404
+ noAvailableTime: mergedPageData?.noAvailableTime
1405
+ }
1395
1406
  },
1396
1407
  item.id
1397
1408
  );
@@ -1424,7 +1435,10 @@ var RoomsList = ({
1424
1435
  hoveredLocationId: hoveredRoomId,
1425
1436
  onSchedule,
1426
1437
  mapHeight: "794px",
1427
- pageData: mergedPageData.map
1438
+ pageData: {
1439
+ ...mergedPageData.map,
1440
+ noAvailableTime: pageData?.noAvailableTime
1441
+ }
1428
1442
  }
1429
1443
  ) })
1430
1444
  ] })
@@ -1639,6 +1653,21 @@ var QuestionnaireForm = ({
1639
1653
  const [errors, setErrors] = React2.useState({});
1640
1654
  const [agreements, setAgreements] = React2.useState({});
1641
1655
  const [agreementError, setAgreementError] = React2.useState("");
1656
+ const [phoneCountryCodes, setPhoneCountryCodes] = React2.useState({});
1657
+ const defaultCountryCodes = [
1658
+ { code: "+1", country: "US/CA" },
1659
+ { code: "+86", country: "CN" },
1660
+ { code: "+44", country: "UK" },
1661
+ { code: "+81", country: "JP" },
1662
+ { code: "+82", country: "KR" },
1663
+ { code: "+65", country: "SG" },
1664
+ { code: "+852", country: "HK" },
1665
+ { code: "+886", country: "TW" },
1666
+ { code: "+61", country: "AU" },
1667
+ { code: "+49", country: "DE" },
1668
+ { code: "+33", country: "FR" }
1669
+ ];
1670
+ const countryCodes = pageData?.countryCodes || defaultCountryCodes;
1642
1671
  const getQuestionId = (question) => {
1643
1672
  return question.id || question.key || "";
1644
1673
  };
@@ -1655,6 +1684,22 @@ var QuestionnaireForm = ({
1655
1684
  });
1656
1685
  }
1657
1686
  };
1687
+ const handleEmailBlur = (questionId, value) => {
1688
+ if (!value) return;
1689
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1690
+ if (!emailRegex.test(value)) {
1691
+ setErrors((prev) => ({
1692
+ ...prev,
1693
+ [questionId]: "Please enter a valid email address"
1694
+ }));
1695
+ }
1696
+ };
1697
+ const handleCountryCodeChange = (questionId, code) => {
1698
+ setPhoneCountryCodes((prev) => ({
1699
+ ...prev,
1700
+ [questionId]: code
1701
+ }));
1702
+ };
1658
1703
  const handleCheckboxChange = (questionId, optionValue, checked) => {
1659
1704
  const currentValues = responses[questionId] || [];
1660
1705
  const newValues = checked ? [...currentValues, optionValue] : currentValues.filter((v) => v !== optionValue);
@@ -1700,7 +1745,22 @@ var QuestionnaireForm = ({
1700
1745
  const handleSubmit = (e) => {
1701
1746
  e.preventDefault();
1702
1747
  if (validateForm()) {
1703
- onSubmit?.(responses);
1748
+ const finalResponses = { ...responses };
1749
+ questions.forEach((question) => {
1750
+ if (question.type === "tel" || question.type === "phone") {
1751
+ const questionId = getQuestionId(question);
1752
+ const countryCode = phoneCountryCodes[questionId] || "+1";
1753
+ const phoneNumber = responses[questionId];
1754
+ if (phoneNumber) {
1755
+ finalResponses[questionId] = phoneNumber;
1756
+ if (questionId === "phone" || questionId === "customer_phone_number") {
1757
+ finalResponses["phone_code"] = countryCode;
1758
+ finalResponses["customer_phone_code"] = countryCode;
1759
+ }
1760
+ }
1761
+ }
1762
+ });
1763
+ onSubmit?.(finalResponses);
1704
1764
  }
1705
1765
  };
1706
1766
  const renderQuestion = (question) => {
@@ -1708,8 +1768,6 @@ var QuestionnaireForm = ({
1708
1768
  const hasError = !!errors[questionId];
1709
1769
  switch (question.type) {
1710
1770
  case "text":
1711
- case "email":
1712
- case "tel":
1713
1771
  return /* @__PURE__ */ jsxRuntime.jsx(
1714
1772
  "input",
1715
1773
  {
@@ -1724,6 +1782,76 @@ var QuestionnaireForm = ({
1724
1782
  )
1725
1783
  }
1726
1784
  );
1785
+ case "email":
1786
+ return /* @__PURE__ */ jsxRuntime.jsx(
1787
+ "input",
1788
+ {
1789
+ type: "email",
1790
+ value: responses[questionId] || "",
1791
+ onChange: (e) => handleChange(questionId, e.target.value),
1792
+ onBlur: (e) => handleEmailBlur(questionId, e.target.value),
1793
+ placeholder: question.placeholder,
1794
+ className: cn(
1795
+ "w-full px-4 py-3 rounded-lg border text-base",
1796
+ "focus:outline-none focus:ring-2 focus:ring-[#3ADB67] focus:border-transparent",
1797
+ hasError ? "border-red-500" : "border-[#E4E5E6]"
1798
+ )
1799
+ }
1800
+ );
1801
+ case "tel":
1802
+ case "phone":
1803
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
1804
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1805
+ /* @__PURE__ */ jsxRuntime.jsx(
1806
+ "select",
1807
+ {
1808
+ value: phoneCountryCodes[questionId] || "+1",
1809
+ onChange: (e) => handleCountryCodeChange(questionId, e.target.value),
1810
+ className: cn(
1811
+ "appearance-none pl-3 pr-8 py-3 rounded-lg border text-base",
1812
+ "focus:outline-none focus:ring-2 focus:ring-[#3ADB67] focus:border-transparent",
1813
+ "bg-white cursor-pointer w-[80px]",
1814
+ hasError ? "border-red-500" : "border-[#E4E5E6]"
1815
+ ),
1816
+ children: countryCodes.map((item) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: item.code, children: item.code }, item.code))
1817
+ }
1818
+ ),
1819
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx(
1820
+ "svg",
1821
+ {
1822
+ width: "12",
1823
+ height: "8",
1824
+ viewBox: "0 0 12 8",
1825
+ fill: "none",
1826
+ xmlns: "http://www.w3.org/2000/svg",
1827
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1828
+ "path",
1829
+ {
1830
+ d: "M1 1.5L6 6.5L11 1.5",
1831
+ stroke: "#9CA3AF",
1832
+ strokeWidth: "1.5",
1833
+ strokeLinecap: "round",
1834
+ strokeLinejoin: "round"
1835
+ }
1836
+ )
1837
+ }
1838
+ ) })
1839
+ ] }),
1840
+ /* @__PURE__ */ jsxRuntime.jsx(
1841
+ "input",
1842
+ {
1843
+ type: "tel",
1844
+ value: responses[questionId] || "",
1845
+ onChange: (e) => handleChange(questionId, e.target.value),
1846
+ placeholder: question.placeholder,
1847
+ className: cn(
1848
+ "flex-1 px-4 py-3 rounded-lg border text-base",
1849
+ "focus:outline-none focus:ring-2 focus:ring-[#3ADB67] focus:border-transparent",
1850
+ hasError ? "border-red-500" : "border-[#E4E5E6]"
1851
+ )
1852
+ }
1853
+ )
1854
+ ] });
1727
1855
  case "textarea":
1728
1856
  return /* @__PURE__ */ jsxRuntime.jsx(
1729
1857
  "textarea",
@@ -1829,7 +1957,8 @@ var QuestionnaireForm = ({
1829
1957
  question.label,
1830
1958
  question.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-1", children: "*" })
1831
1959
  ] }),
1832
- question.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm text-gray-600 mt-1", children: question.description })
1960
+ question.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm text-gray-600 mt-1", children: question.description }),
1961
+ question.type === "email" && questionId === "email" && pageData?.emailDescription && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm text-gray-600 mt-1", children: pageData.emailDescription })
1833
1962
  ] }),
1834
1963
  renderQuestion(question),
1835
1964
  question.hint && !errors[questionId] && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: question.hint }),
@@ -1903,11 +2032,12 @@ var DateTimePicker = ({
1903
2032
  onBookingSuccess
1904
2033
  }) => {
1905
2034
  const { token } = antd.theme.useToken();
1906
- const [selectMonth, setSelectMonth] = React2.useState("");
1907
- const [selectedDate, setSelectedDate] = React2.useState(dayjs__default.default());
2035
+ const [selectedDate, setSelectedDate] = React2.useState(null);
2036
+ const [calendarValue, setCalendarValue] = React2.useState(dayjs__default.default());
1908
2037
  const [selectedTimeslotId, setSelectedTimeslotId] = React2.useState(
1909
2038
  null
1910
2039
  );
2040
+ const [isInitialized, setIsInitialized] = React2.useState(false);
1911
2041
  const {
1912
2042
  createBooking,
1913
2043
  loading: bookingLoading,
@@ -1926,8 +2056,8 @@ var DateTimePicker = ({
1926
2056
  locale,
1927
2057
  { enabled: !!demoRoomCode && !!demoRoom?.questionnaire_id }
1928
2058
  );
1929
- const startDate = selectedDate.startOf("month").format("YYYY-MM-DD");
1930
- const endDate = selectedDate.endOf("month").format("YYYY-MM-DD");
2059
+ const startDate = calendarValue.startOf("month").format("YYYY-MM-DD");
2060
+ const endDate = calendarValue.endOf("month").format("YYYY-MM-DD");
1931
2061
  const {
1932
2062
  data: timeslotsData,
1933
2063
  loading: timeslotsLoading,
@@ -1943,30 +2073,81 @@ var DateTimePicker = ({
1943
2073
  { enabled: !!demoRoomCode }
1944
2074
  );
1945
2075
  const dayTimeslots = React2.useMemo(() => {
1946
- if (!timeslotsData?.timeslots) return [];
2076
+ if (!timeslotsData?.timeslots || !selectedDate) return [];
1947
2077
  const selectedDateStr = selectedDate.format("YYYY-MM-DD");
1948
2078
  return timeslotsData.timeslots.filter((slot) => {
1949
2079
  const slotDate = dayjs__default.default(slot.start_time).format("YYYY-MM-DD");
1950
2080
  return slotDate === selectedDateStr;
1951
2081
  });
1952
2082
  }, [timeslotsData, selectedDate]);
2083
+ const availableDates = React2.useMemo(() => {
2084
+ if (!timeslotsData?.timeslots) return /* @__PURE__ */ new Set();
2085
+ const dates = /* @__PURE__ */ new Set();
2086
+ timeslotsData.timeslots.forEach((slot) => {
2087
+ if (slot.status === "available") {
2088
+ const dateStr = dayjs__default.default(slot.start_time).format("YYYY-MM-DD");
2089
+ dates.add(dateStr);
2090
+ }
2091
+ });
2092
+ return dates;
2093
+ }, [timeslotsData]);
2094
+ React2.useEffect(() => {
2095
+ if (!timeslotsData?.timeslots || isInitialized) return;
2096
+ const now = dayjs__default.default();
2097
+ const availableTimeslots = timeslotsData.timeslots.filter(
2098
+ (slot) => slot.status === "available" && dayjs__default.default(slot.start_time).isAfter(now)
2099
+ );
2100
+ if (availableTimeslots.length > 0) {
2101
+ const sortedSlots = [...availableTimeslots].sort(
2102
+ (a, b) => dayjs__default.default(a.start_time).unix() - dayjs__default.default(b.start_time).unix()
2103
+ );
2104
+ const nearestSlot = sortedSlots[0];
2105
+ const nearestDate = dayjs__default.default(nearestSlot.start_time);
2106
+ setSelectedDate(nearestDate);
2107
+ setCalendarValue(nearestDate);
2108
+ setSelectedTimeslotId(nearestSlot.id);
2109
+ setIsInitialized(true);
2110
+ } else if (!selectedDate) {
2111
+ setSelectedDate(now);
2112
+ setCalendarValue(now);
2113
+ setIsInitialized(true);
2114
+ }
2115
+ }, [timeslotsData, isInitialized, selectedDate]);
2116
+ React2.useEffect(() => {
2117
+ if (!timeslotsData?.timeslots || !isInitialized) return;
2118
+ if (selectedDate && selectedDate.isSame(calendarValue, "month")) {
2119
+ return;
2120
+ }
2121
+ const currentMonthStart = calendarValue.startOf("month");
2122
+ const currentMonthEnd = calendarValue.endOf("month");
2123
+ const now = dayjs__default.default();
2124
+ const availableTimeslots = timeslotsData.timeslots.filter((slot) => {
2125
+ const slotDate = dayjs__default.default(slot.start_time);
2126
+ return slot.status === "available" && slotDate.isAfter(now) && (slotDate.isAfter(currentMonthStart) || slotDate.isSame(currentMonthStart, "day")) && (slotDate.isBefore(currentMonthEnd) || slotDate.isSame(currentMonthEnd, "day"));
2127
+ });
2128
+ if (availableTimeslots.length > 0) {
2129
+ const sortedSlots = [...availableTimeslots].sort(
2130
+ (a, b) => dayjs__default.default(a.start_time).unix() - dayjs__default.default(b.start_time).unix()
2131
+ );
2132
+ const firstSlot = sortedSlots[0];
2133
+ const firstDate = dayjs__default.default(firstSlot.start_time);
2134
+ setSelectedDate(firstDate);
2135
+ setSelectedTimeslotId(firstSlot.id);
2136
+ }
2137
+ }, [calendarValue, timeslotsData, isInitialized, selectedDate]);
1953
2138
  const formatTimeslot = (slot) => {
1954
2139
  const start = dayjs__default.default(slot.start_time).format("h:mm A");
1955
2140
  const end = dayjs__default.default(slot.end_time).format("h:mm A");
1956
2141
  return `${start} - ${end}`;
1957
2142
  };
1958
- const onPanelChange = (value, mode) => {
1959
- console.log(value.format("YYYY-MM-DD"), mode);
1960
- };
1961
2143
  const wrapperStyle = {
1962
- width: 824,
1963
2144
  background: "#fff",
1964
2145
  border: `1px solid ${token.colorBorderSecondary}`,
1965
2146
  borderRadius: token.borderRadiusLG
1966
2147
  };
1967
2148
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1968
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[48px] py-[64px] font-bold text-center", children: pageData.scheduleYourVisit }),
1969
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
2149
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[48px] l:text-[32px] py-[64px] l:py-[24px] font-bold text-center", children: pageData.scheduleYourVisit }),
2150
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 l:flex-col", children: [
1970
2151
  /* @__PURE__ */ jsxRuntime.jsx(
1971
2152
  antd.ConfigProvider,
1972
2153
  {
@@ -1982,34 +2163,79 @@ var DateTimePicker = ({
1982
2163
  }
1983
2164
  }
1984
2165
  },
1985
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: wrapperStyle, className: "calendar-custom-cell", children: [
1986
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
2166
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
2167
+ "div",
2168
+ {
2169
+ style: wrapperStyle,
2170
+ className: "calendar-custom-cell w-[calc(824/1920*100vw)] min-l:max-w-[824px] l:w-full",
2171
+ children: [
2172
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
1987
2173
  .calendar-custom-cell .ant-picker-cell {
1988
2174
  padding: 6px !important;
2175
+ text-align: center !important;
2176
+ }
2177
+ .calendar-custom-cell .ant-picker-cell .ant-picker-cell-inner {
2178
+ margin: 0 auto !important;
1989
2179
  }
1990
2180
  .calendar-custom-cell .ant-picker-cell-inner {
1991
- width: 100px !important;
1992
- height: 100px !important;
2181
+ width: 38px !important;
2182
+ height: 38px !important;
1993
2183
  display: flex !important;
1994
2184
  align-items: center !important;
1995
2185
  justify-content: center !important;
1996
- border-radius: 20px !important;
2186
+ border-radius: 8px !important;
1997
2187
  border: 1px solid #E4E5E6 !important;
2188
+ aspect-ratio: 1 / 1 !important;
2189
+ }
2190
+ @media (min-width: 1024px) and (max-width: 1919px) {
2191
+ .calendar-custom-cell .ant-picker-cell-inner {
2192
+ width: 54px !important;
2193
+ height: 54px !important;
2194
+ border-radius: 12px !important;
2195
+ }
2196
+ .calendar-custom-cell .ant-picker-calendar-date-value {
2197
+ line-height: 54px !important;
2198
+ }
2199
+ }
2200
+ @media (min-width: 1920px) {
2201
+ .calendar-custom-cell .ant-picker-cell-inner {
2202
+ width: 100px !important;
2203
+ height: 100px !important;
2204
+ border-radius: 20px !important;
2205
+ }
2206
+ .calendar-custom-cell .ant-picker-calendar-date-value {
2207
+ line-height: 100px !important;
2208
+ }
1998
2209
  }
1999
- .calendar-custom-cell .ant-picker-cell-selected .ant-picker-cell-inner {
2210
+ .calendar-custom-cell .ant-picker-cell-selected .ant-picker-cell-inner,
2211
+ .calendar-custom-cell .ant-picker-cell-selected:not(.ant-picker-cell-disabled) .ant-picker-cell-inner {
2000
2212
  background-color: #3ADB67 !important;
2001
2213
  color: white !important;
2002
2214
  border-color: #3ADB67 !important;
2003
2215
  }
2216
+ .calendar-custom-cell .ant-picker-cell-in-view.ant-picker-cell-selected .ant-picker-cell-inner {
2217
+ background-color: #3ADB67 !important;
2218
+ color: white !important;
2219
+ }
2004
2220
  .calendar-custom-cell .ant-picker-cell-today .ant-picker-cell-inner {
2005
2221
  border-color: #3ADB67 !important;
2006
- border-radius: 20px !important;
2222
+ border-radius: 8px !important;
2223
+ }
2224
+ @media (min-width: 1024px) and (max-width: 1919px) {
2225
+ .calendar-custom-cell .ant-picker-cell-today .ant-picker-cell-inner {
2226
+ border-radius: 12px !important;
2227
+ }
2228
+ }
2229
+ @media (min-width: 1920px) {
2230
+ .calendar-custom-cell .ant-picker-cell-today .ant-picker-cell-inner {
2231
+ border-radius: 20px !important;
2232
+ }
2007
2233
  }
2008
2234
  .calendar-custom-cell .ant-picker-cell-today .ant-picker-cell-inner::before {
2009
2235
  display: none !important;
2010
2236
  }
2011
2237
  .calendar-custom-cell .ant-picker-calendar-date-value {
2012
- line-height: 100px !important;
2238
+ line-height: 38px !important;
2013
2239
  }
2014
2240
  .calendar-custom-cell .ant-picker-content {
2015
2241
  width: 100% !important;
@@ -2017,135 +2243,181 @@ var DateTimePicker = ({
2017
2243
  .calendar-custom-cell .ant-picker-content thead tr th {
2018
2244
  line-height: 48px !important;
2019
2245
  }
2246
+ .calendar-custom-cell .ant-picker-cell-disabled .ant-picker-cell-inner {
2247
+ background-color: #F5F5F5 !important;
2248
+ color: #BDBDBD !important;
2249
+ border-color: #E4E5E6 !important;
2250
+ cursor: not-allowed !important;
2251
+ box-shadow: none !important;
2252
+ }
2253
+ .calendar-custom-cell .ant-picker-cell-disabled:hover .ant-picker-cell-inner {
2254
+ background-color: #F5F5F5 !important;
2255
+ border-color: #E4E5E6 !important;
2256
+ box-shadow: none !important;
2257
+ }
2258
+ .calendar-custom-cell .ant-picker-cell-disabled::before {
2259
+ display: none !important;
2260
+ }
2261
+ .calendar-custom-cell .ant-picker-cell-disabled::after {
2262
+ display: none !important;
2263
+ }
2020
2264
  ` }),
2021
- /* @__PURE__ */ jsxRuntime.jsx(
2022
- antd.Calendar,
2023
- {
2024
- fullscreen: false,
2025
- value: selectedDate,
2026
- onChange: (date) => setSelectedDate(date),
2027
- headerRender: ({ value, onChange }) => {
2028
- const year = value.year();
2029
- const month = value.month();
2030
- const yearOptions = Array.from({ length: 20 }, (_, i) => {
2031
- const label = year - 10 + i;
2032
- return { label, value: label };
2033
- });
2034
- const monthOptions = value.localeData().months().map((label, index) => ({
2035
- label,
2036
- value: index
2037
- }));
2038
- const monthText = monthOptions?.find((item) => {
2039
- return item?.value === month;
2040
- });
2041
- setSelectMonth(monthText?.label || "");
2042
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [
2043
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
2044
- /* @__PURE__ */ jsxRuntime.jsx(
2045
- antd.Select,
2265
+ /* @__PURE__ */ jsxRuntime.jsx(
2266
+ antd.Calendar,
2267
+ {
2268
+ fullscreen: false,
2269
+ value: calendarValue,
2270
+ onSelect: (date) => {
2271
+ setSelectedDate(date);
2272
+ setCalendarValue(date);
2273
+ },
2274
+ onPanelChange: (date) => {
2275
+ setCalendarValue(date);
2276
+ },
2277
+ disabledDate: (current) => {
2278
+ if (!current) return false;
2279
+ if (current.isSame(dayjs__default.default(), "day")) return false;
2280
+ if (current.isBefore(dayjs__default.default(), "day")) return true;
2281
+ const dateStr = current.format("YYYY-MM-DD");
2282
+ return !availableDates.has(dateStr);
2283
+ },
2284
+ fullCellRender: (date) => {
2285
+ const isSelected = selectedDate && date.isSame(selectedDate, "day");
2286
+ const isToday = date.isSame(dayjs__default.default(), "day");
2287
+ const dateStr = date.format("YYYY-MM-DD");
2288
+ const isDisabled = !isToday && (date.isBefore(dayjs__default.default(), "day") || !availableDates.has(dateStr));
2289
+ return /* @__PURE__ */ jsxRuntime.jsx(
2290
+ "div",
2046
2291
  {
2047
- value: month,
2048
- options: monthOptions,
2049
- onChange: (newMonth) => {
2050
- const now = value.clone().month(newMonth);
2051
- onChange(now);
2052
- },
2053
- variant: "borderless",
2054
- className: "text-2xl font-medium",
2055
- popupMatchSelectWidth: false,
2292
+ className: `ant-picker-cell-inner ${isSelected ? "ant-picker-cell-inner-selected" : ""} ${isToday ? "ant-picker-cell-inner-today" : ""}`,
2056
2293
  style: {
2057
- fontSize: "24px",
2058
- fontWeight: 500
2059
- }
2060
- }
2061
- ),
2062
- /* @__PURE__ */ jsxRuntime.jsx(
2063
- antd.Select,
2064
- {
2065
- value: year,
2066
- options: yearOptions,
2067
- onChange: (newYear) => {
2068
- const now = value.clone().year(newYear);
2069
- onChange(now);
2294
+ backgroundColor: isSelected ? "#3ADB67" : void 0,
2295
+ color: isSelected ? "white" : isDisabled ? "#BDBDBD" : void 0,
2296
+ borderColor: isSelected ? "#3ADB67" : isToday ? "#3ADB67" : void 0
2070
2297
  },
2071
- variant: "borderless",
2072
- className: "text-2xl font-medium",
2073
- popupMatchSelectWidth: false,
2074
- style: {
2075
- fontSize: "24px",
2076
- fontWeight: 500
2077
- }
2298
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ant-picker-calendar-date-value", children: date.date() })
2078
2299
  }
2079
- )
2080
- ] }),
2081
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2082
- /* @__PURE__ */ jsxRuntime.jsx(
2083
- "button",
2084
- {
2085
- onClick: () => {
2086
- const newDate = value.subtract(1, "month");
2087
- onChange(newDate);
2088
- },
2089
- className: "w-10 h-10 flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors",
2090
- children: /* @__PURE__ */ jsxRuntime.jsx(
2091
- "svg",
2300
+ );
2301
+ },
2302
+ headerRender: ({ value, onChange }) => {
2303
+ const year = value.year();
2304
+ const month = value.month();
2305
+ const yearOptions = Array.from({ length: 20 }, (_, i) => {
2306
+ const label = year - 10 + i;
2307
+ return { label, value: label };
2308
+ });
2309
+ const monthOptions = value.localeData().months().map((label, index) => ({
2310
+ label,
2311
+ value: index
2312
+ }));
2313
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [
2314
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
2315
+ /* @__PURE__ */ jsxRuntime.jsx(
2316
+ antd.Select,
2092
2317
  {
2093
- width: "20",
2094
- height: "20",
2095
- viewBox: "0 0 20 20",
2096
- fill: "none",
2097
- xmlns: "http://www.w3.org/2000/svg",
2318
+ value: month,
2319
+ options: monthOptions,
2320
+ onChange: (newMonth) => {
2321
+ const now = value.clone().month(newMonth);
2322
+ onChange(now);
2323
+ },
2324
+ variant: "borderless",
2325
+ className: "text-2xl font-medium",
2326
+ popupMatchSelectWidth: false,
2327
+ style: {
2328
+ fontSize: "24px",
2329
+ fontWeight: 500
2330
+ }
2331
+ }
2332
+ ),
2333
+ /* @__PURE__ */ jsxRuntime.jsx(
2334
+ antd.Select,
2335
+ {
2336
+ value: year,
2337
+ options: yearOptions,
2338
+ onChange: (newYear) => {
2339
+ const now = value.clone().year(newYear);
2340
+ onChange(now);
2341
+ },
2342
+ variant: "borderless",
2343
+ className: "text-2xl font-medium",
2344
+ popupMatchSelectWidth: false,
2345
+ style: {
2346
+ fontSize: "24px",
2347
+ fontWeight: 500
2348
+ }
2349
+ }
2350
+ )
2351
+ ] }),
2352
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2353
+ /* @__PURE__ */ jsxRuntime.jsx(
2354
+ "button",
2355
+ {
2356
+ onClick: () => {
2357
+ const newDate = value.subtract(1, "month");
2358
+ onChange(newDate);
2359
+ },
2360
+ className: "w-10 h-10 flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors",
2098
2361
  children: /* @__PURE__ */ jsxRuntime.jsx(
2099
- "path",
2362
+ "svg",
2100
2363
  {
2101
- d: "M12 16L6 10L12 4",
2102
- stroke: "currentColor",
2103
- strokeWidth: "2",
2104
- strokeLinecap: "round",
2105
- strokeLinejoin: "round"
2364
+ width: "20",
2365
+ height: "20",
2366
+ viewBox: "0 0 20 20",
2367
+ fill: "none",
2368
+ xmlns: "http://www.w3.org/2000/svg",
2369
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2370
+ "path",
2371
+ {
2372
+ d: "M12 16L6 10L12 4",
2373
+ stroke: "currentColor",
2374
+ strokeWidth: "2",
2375
+ strokeLinecap: "round",
2376
+ strokeLinejoin: "round"
2377
+ }
2378
+ )
2106
2379
  }
2107
2380
  )
2108
2381
  }
2109
- )
2110
- }
2111
- ),
2112
- /* @__PURE__ */ jsxRuntime.jsx(
2113
- "button",
2114
- {
2115
- onClick: () => {
2116
- const newDate = value.add(1, "month");
2117
- onChange(newDate);
2118
- },
2119
- className: "w-10 h-10 flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors",
2120
- children: /* @__PURE__ */ jsxRuntime.jsx(
2121
- "svg",
2382
+ ),
2383
+ /* @__PURE__ */ jsxRuntime.jsx(
2384
+ "button",
2122
2385
  {
2123
- width: "20",
2124
- height: "20",
2125
- viewBox: "0 0 20 20",
2126
- fill: "none",
2127
- xmlns: "http://www.w3.org/2000/svg",
2386
+ onClick: () => {
2387
+ const newDate = value.add(1, "month");
2388
+ onChange(newDate);
2389
+ },
2390
+ className: "w-10 h-10 flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors",
2128
2391
  children: /* @__PURE__ */ jsxRuntime.jsx(
2129
- "path",
2392
+ "svg",
2130
2393
  {
2131
- d: "M8 4L14 10L8 16",
2132
- stroke: "currentColor",
2133
- strokeWidth: "2",
2134
- strokeLinecap: "round",
2135
- strokeLinejoin: "round"
2394
+ width: "20",
2395
+ height: "20",
2396
+ viewBox: "0 0 20 20",
2397
+ fill: "none",
2398
+ xmlns: "http://www.w3.org/2000/svg",
2399
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2400
+ "path",
2401
+ {
2402
+ d: "M8 4L14 10L8 16",
2403
+ stroke: "currentColor",
2404
+ strokeWidth: "2",
2405
+ strokeLinecap: "round",
2406
+ strokeLinejoin: "round"
2407
+ }
2408
+ )
2136
2409
  }
2137
2410
  )
2138
2411
  }
2139
2412
  )
2140
- }
2141
- )
2142
- ] })
2143
- ] });
2144
- },
2145
- onPanelChange
2146
- }
2147
- )
2148
- ] })
2413
+ ] })
2414
+ ] });
2415
+ }
2416
+ }
2417
+ )
2418
+ ]
2419
+ }
2420
+ )
2149
2421
  }
2150
2422
  ),
2151
2423
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white p-[24px] rounded-[12px] flex-1", children: [
@@ -2156,10 +2428,16 @@ var DateTimePicker = ({
2156
2428
  "button",
2157
2429
  {
2158
2430
  onClick: () => {
2159
- const newDate = selectedDate.subtract(1, "day");
2160
- setSelectedDate(newDate);
2431
+ if (selectedDate) {
2432
+ const newDate = selectedDate.subtract(1, "day");
2433
+ if (!newDate.isBefore(dayjs__default.default(), "day")) {
2434
+ setSelectedDate(newDate);
2435
+ setCalendarValue(newDate);
2436
+ }
2437
+ }
2161
2438
  },
2162
- className: "w-10 h-10 flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors",
2439
+ disabled: !selectedDate || selectedDate.isSame(dayjs__default.default(), "day") || selectedDate.isBefore(dayjs__default.default(), "day"),
2440
+ className: "w-10 h-10 flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
2163
2441
  children: /* @__PURE__ */ jsxRuntime.jsx(
2164
2442
  "svg",
2165
2443
  {
@@ -2179,15 +2457,19 @@ var DateTimePicker = ({
2179
2457
  )
2180
2458
  }
2181
2459
  ),
2182
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: selectMonth }),
2460
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: selectedDate ? selectedDate.format("MMMM D, YYYY") : "" }),
2183
2461
  /* @__PURE__ */ jsxRuntime.jsx(
2184
2462
  "button",
2185
2463
  {
2186
2464
  onClick: () => {
2187
- const newDate = selectedDate.add(1, "day");
2188
- setSelectedDate(newDate);
2465
+ if (selectedDate) {
2466
+ const newDate = selectedDate.add(1, "day");
2467
+ setSelectedDate(newDate);
2468
+ setCalendarValue(newDate);
2469
+ }
2189
2470
  },
2190
- className: "w-10 h-10 flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors",
2471
+ disabled: !selectedDate,
2472
+ className: "w-10 h-10 flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
2191
2473
  children: /* @__PURE__ */ jsxRuntime.jsx(
2192
2474
  "svg",
2193
2475
  {
@@ -2244,7 +2526,11 @@ var DateTimePicker = ({
2244
2526
  },
2245
2527
  slot.id
2246
2528
  );
2247
- }) })
2529
+ }) }),
2530
+ !timeslotsLoading && dayTimeslots?.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-4 text-right", children: pageData?.timezone?.replace(
2531
+ "{{timezone}}",
2532
+ demoRoom?.timezone || timezone || ""
2533
+ ) })
2248
2534
  ] })
2249
2535
  ] }),
2250
2536
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-12", children: [
@@ -2365,12 +2651,9 @@ var DemoRoomDetail = ({
2365
2651
  data: demoRoom,
2366
2652
  loading,
2367
2653
  error
2368
- } = useDemoRoom(
2369
- apiClient,
2370
- demoRoomCode || "",
2371
- locale,
2372
- { enabled: !!apiClient && !!demoRoomCode }
2373
- );
2654
+ } = useDemoRoom(apiClient, demoRoomCode || "", locale, {
2655
+ enabled: !!apiClient && !!demoRoomCode
2656
+ });
2374
2657
  const title = demoRoom?.name || titleProp || "Design District Demo Room";
2375
2658
  const descriptions = demoRoom?.description ? [demoRoom.description] : descriptionsProp || defaultDescriptions;
2376
2659
  const devices = demoRoom?.description || devicesProp || "eufyMake E1, eufyMake M5";
@@ -2399,8 +2682,8 @@ var DemoRoomDetail = ({
2399
2682
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mt-2", children: error.message })
2400
2683
  ] }) });
2401
2684
  }
2402
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-8 items-start", children: [
2403
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
2685
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-8 l:flex l:flex-col items-start py-[24px]", children: [
2686
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 py-[24px]", children: [
2404
2687
  /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-[40px] font-bold text-gray-900 leading-tight", children: title }),
2405
2688
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: descriptions.map((desc, index) => /* @__PURE__ */ jsxRuntime.jsx(
2406
2689
  "p",
@@ -2527,7 +2810,7 @@ var DemoRoomDetail = ({
2527
2810
  ] })
2528
2811
  ] })
2529
2812
  ] }),
2530
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-[400px] rounded-2xl overflow-hidden", children: images.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2813
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative l:w-full h-[400px] rounded-2xl overflow-hidden", children: images.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2531
2814
  react.Swiper,
2532
2815
  {
2533
2816
  ...swiperVersion === "11+" && Navigation && Pagination && Autoplay ? { modules: [Navigation, Pagination, Autoplay] } : {},