@anker-in/ui 0.3.2 → 0.3.3

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.mjs CHANGED
@@ -10853,7 +10853,9 @@ var QuestionnaireForm2 = ({
10853
10853
  error,
10854
10854
  initialResponses
10855
10855
  }) => {
10856
- const [responses, setResponses] = useState(() => initialResponses || {});
10856
+ const [responses, setResponses] = useState(
10857
+ () => initialResponses || {}
10858
+ );
10857
10859
  const [errors, setErrors] = useState({});
10858
10860
  const [agreements, setAgreements] = useState({});
10859
10861
  const [agreementError, setAgreementError] = useState("");
@@ -10875,8 +10877,12 @@ var QuestionnaireForm2 = ({
10875
10877
  });
10876
10878
  return seeded;
10877
10879
  });
10878
- const prevHasBookedBeforeRef = useRef(initialResponses?.["has_booked_before"] === "option2");
10879
- const hasBookedBeforeInitialized = useRef(!!initialResponses?.["has_booked_before"]);
10880
+ const prevHasBookedBeforeRef = useRef(
10881
+ initialResponses?.["has_booked_before"] === "option2"
10882
+ );
10883
+ const hasBookedBeforeInitialized = useRef(
10884
+ !!initialResponses?.["has_booked_before"]
10885
+ );
10880
10886
  const hasBookedBeforeQuestion = questions.find(
10881
10887
  (q) => (q.key || q.id) === "has_booked_before"
10882
10888
  );
@@ -10894,6 +10900,7 @@ var QuestionnaireForm2 = ({
10894
10900
  return true;
10895
10901
  });
10896
10902
  }, [questions, hasBookedBefore]);
10903
+ console.log(error, pageData);
10897
10904
  useEffect(() => {
10898
10905
  if (hasBookedBeforeInitialized.current) return;
10899
10906
  if (hasBookedBeforeQuestion && hasBookedBeforeQuestionId) {
@@ -11046,7 +11053,9 @@ var QuestionnaireForm2 = ({
11046
11053
  onSubmit?.(finalResponses);
11047
11054
  } else {
11048
11055
  setTimeout(() => {
11049
- const firstErrorElement = document.querySelector('[data-has-error="true"]');
11056
+ const firstErrorElement = document.querySelector(
11057
+ '[data-has-error="true"]'
11058
+ );
11050
11059
  if (firstErrorElement) {
11051
11060
  firstErrorElement.scrollIntoView({
11052
11061
  behavior: "smooth",
@@ -11402,7 +11411,7 @@ var QuestionnaireForm2 = ({
11402
11411
  children: loading ? pageData?.submitting || "Submitting..." : pageData?.submit || "Submit Booking"
11403
11412
  }
11404
11413
  ),
11405
- error && /* @__PURE__ */ jsx("div", { className: "text-center w-full p-4", children: /* @__PURE__ */ jsx("p", { className: "text-[#FF4D4D] font-bold", children: error.message }) })
11414
+ error && /* @__PURE__ */ jsx("div", { className: "text-center w-full p-4", children: /* @__PURE__ */ jsx("p", { className: "text-[#FF4D4D] font-bold", children: pageData?.errorMsg?.[String(error.code)] || pageData?.errorMsg?.[error.code || ""] || error.message }) })
11406
11415
  ] })
11407
11416
  ] });
11408
11417
  };
@@ -11564,22 +11573,34 @@ var DateTimePicker2 = ({
11564
11573
  return `${start} - ${end}`;
11565
11574
  };
11566
11575
  useEffect(() => {
11567
- if (!booking || hasResolvedBookingSlot || !timeslotsData?.timeslots?.length) return;
11576
+ if (!booking?.booking_date) return;
11577
+ setSelectedDate(dayjs4(booking.booking_date));
11578
+ setCalendarValue(dayjs4(booking.booking_date));
11579
+ setIsInitialized(true);
11580
+ if (booking.timeslot_id) {
11581
+ setSelectedTimeslotId(booking.timeslot_id);
11582
+ setHasResolvedBookingSlot(true);
11583
+ }
11584
+ }, [booking?.booking_date, booking?.timeslot_id]);
11585
+ useEffect(() => {
11586
+ if (!booking || hasResolvedBookingSlot || !dayTimeslots.length) return;
11568
11587
  if (booking.timeslot_id) {
11569
11588
  setSelectedTimeslotId(booking.timeslot_id);
11570
11589
  setHasResolvedBookingSlot(true);
11571
11590
  return;
11572
11591
  }
11573
- if (booking.time_slot) {
11574
- const match = timeslotsData.timeslots.find(
11575
- (slot) => formatTimeslot(slot) === booking.time_slot
11576
- );
11577
- if (match) {
11578
- setSelectedTimeslotId(match.id);
11579
- setHasResolvedBookingSlot(true);
11580
- }
11592
+ if (!booking.time_slot) return;
11593
+ const tz = demoRoom?.timezone || timezone5;
11594
+ const target = booking.time_slot.replace(/\s+/g, "");
11595
+ const match = dayTimeslots.find((slot) => {
11596
+ const toHm = (iso) => (tz ? dayjs4(iso).tz(tz) : dayjs4(iso)).format("HH:mm");
11597
+ return `${toHm(slot.start_time)}-${toHm(slot.end_time)}` === target;
11598
+ });
11599
+ if (match) {
11600
+ setSelectedTimeslotId(match.id);
11601
+ setHasResolvedBookingSlot(true);
11581
11602
  }
11582
- }, [booking, timeslotsData, hasResolvedBookingSlot]);
11603
+ }, [booking, dayTimeslots, hasResolvedBookingSlot, demoRoom?.timezone, timezone5]);
11583
11604
  const initialResponses = useMemo(() => {
11584
11605
  if (!booking) return void 0;
11585
11606
  return {
@@ -12634,7 +12655,7 @@ var BookingFormO2O = ({
12634
12655
  className: "mt-[12px] h-[220px] rounded-[8px] object-cover l:h-auto"
12635
12656
  }
12636
12657
  ),
12637
- !!selectedPodButtonText && /* @__PURE__ */ jsxs(
12658
+ !!selectedPodButtonText && (booking?.print_status === "unprinted" && booking?.design_project_id || !token) && /* @__PURE__ */ jsxs(
12638
12659
  "a",
12639
12660
  {
12640
12661
  href: selectedPodButtonLink || "#",
@@ -12733,10 +12754,14 @@ var BookingSuccessO2O = ({
12733
12754
  const [loading, setLoading] = useState(false);
12734
12755
  const [bookingDesign, setBookingDesign] = useState(null);
12735
12756
  const [isCancelled, setIsCancelled] = useState(false);
12757
+ const [isPending, setIsPending] = useState(false);
12736
12758
  const [showCancelDialog, setShowCancelDialog] = useState(false);
12737
12759
  const [cancelLoading, setCancelLoading] = useState(false);
12738
12760
  const [cancelError, setCancelError] = useState(null);
12761
+ const [checkinLoading, setCheckinLoading] = useState(false);
12762
+ const [checkinError, setCheckinError] = useState(null);
12739
12763
  const qrCodeContainerRef = useRef(null);
12764
+ const isStore = Boolean(isStoreUser);
12740
12765
  const handlePrintQRCode = () => {
12741
12766
  const canvas = qrCodeContainerRef.current?.querySelector("canvas");
12742
12767
  const qrImageSrc = canvas?.toDataURL("image/png");
@@ -12774,16 +12799,30 @@ var BookingSuccessO2O = ({
12774
12799
  const subtitle = iframeDoc.createElement("p");
12775
12800
  subtitle.textContent = pageData.podData?.QRCodeSubTitle || "";
12776
12801
  const image = iframeDoc.createElement("img");
12777
- image.src = qrImageSrc;
12778
12802
  image.alt = "QR Code";
12779
12803
  iframeDoc.body.appendChild(title);
12780
12804
  iframeDoc.body.appendChild(subtitle);
12781
12805
  iframeDoc.body.appendChild(image);
12782
- iframe.contentWindow?.focus();
12783
- iframe.contentWindow?.print();
12784
- setTimeout(() => {
12785
- document.body.removeChild(iframe);
12786
- }, 1e3);
12806
+ const doPrint = () => {
12807
+ iframe.contentWindow?.focus();
12808
+ iframe.contentWindow?.print();
12809
+ setTimeout(() => {
12810
+ document.body.removeChild(iframe);
12811
+ }, 1e3);
12812
+ };
12813
+ let printed = false;
12814
+ const triggerPrintOnce = () => {
12815
+ if (printed) return;
12816
+ printed = true;
12817
+ doPrint();
12818
+ };
12819
+ image.onload = triggerPrintOnce;
12820
+ image.onerror = triggerPrintOnce;
12821
+ setTimeout(triggerPrintOnce, 1500);
12822
+ image.src = qrImageSrc;
12823
+ if (image.complete) {
12824
+ triggerPrintOnce();
12825
+ }
12787
12826
  };
12788
12827
  useEffect(() => {
12789
12828
  if (token && apiConfig && !initialBookingData) {
@@ -12794,6 +12833,7 @@ var BookingSuccessO2O = ({
12794
12833
  const booking = await apiClient.getBooking(token, apiConfig.locale);
12795
12834
  setBookingData(booking);
12796
12835
  setIsCancelled(booking.status === "cancelled");
12836
+ setIsPending(booking.status === "pending");
12797
12837
  } catch (err) {
12798
12838
  console.error("Failed to fetch booking data:", err);
12799
12839
  } finally {
@@ -12857,6 +12897,33 @@ var BookingSuccessO2O = ({
12857
12897
  setCancelLoading(false);
12858
12898
  }
12859
12899
  };
12900
+ const handleCheckin = async () => {
12901
+ if (!token || !apiConfig) {
12902
+ setCheckinError(
12903
+ pageData.cancelError || "Unable to check in: Missing token or API configuration"
12904
+ );
12905
+ return;
12906
+ }
12907
+ setCheckinLoading(true);
12908
+ setCheckinError(null);
12909
+ try {
12910
+ const apiClient = createDemoRoomApi(apiConfig);
12911
+ const checkedInBooking = await apiClient.checkinBooking({
12912
+ booking_token: token
12913
+ });
12914
+ if (checkedInBooking) {
12915
+ setBookingData(checkedInBooking);
12916
+ window.location.reload();
12917
+ }
12918
+ } catch (err) {
12919
+ console.error("Failed to check in booking:", err);
12920
+ setCheckinError(
12921
+ pageData.cancelError || "Failed to check in. Please try again."
12922
+ );
12923
+ } finally {
12924
+ setCheckinLoading(false);
12925
+ }
12926
+ };
12860
12927
  if (loading) {
12861
12928
  return /* @__PURE__ */ jsx("div", { className: `min-h-screen py-12 px-6 ${className || ""}`, children: /* @__PURE__ */ jsx("div", { className: "mx-auto", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-6", children: [
12862
12929
  /* @__PURE__ */ jsx("div", { className: "h-8 bg-gray-200 rounded w-1/3" }),
@@ -12876,21 +12943,33 @@ var BookingSuccessO2O = ({
12876
12943
  bookingDesign?.order_code;
12877
12944
  return /* @__PURE__ */ jsx("div", { className: `min-h-screen l:py-0 l:px-0 py-12 px-6 ${className || ""}`, children: /* @__PURE__ */ jsxs("div", { className: "mx-auto", children: [
12878
12945
  /* @__PURE__ */ jsx("h1", { className: "text-[48px] xxl:text-[32px] font-bold text-[#080A0F] mb-8 print:hidden", children: pageData.yourAppointment }),
12879
- isCancelled && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-[16px] l:items-start p-6 mb-4 l:gap-2 flex l:flex-col items-center justify-between print:hidden", children: [
12946
+ isCancelled && !isStore && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-[16px] l:items-start l:p-3 p-6 mb-4 l:gap-2 flex l:flex-col items-center justify-between print:hidden", children: [
12880
12947
  /* @__PURE__ */ jsx("p", { className: "text-base text-[#080A0F]", children: pageData.appointmentCanceled }),
12881
- onScheduleAgain && bookingData && /* @__PURE__ */ jsx(
12882
- "button",
12883
- {
12884
- onClick: () => onScheduleAgain(bookingData.demoroom_code),
12885
- className: "px-6 py-3 text-[16px] bg-black text-white rounded-full hover:bg-gray-800 transition-colors whitespace-nowrap",
12886
- children: pageData.scheduleAgain
12887
- }
12888
- )
12948
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center l:gap-2 gap-4", children: [
12949
+ !!pageData.contactUs && /* @__PURE__ */ jsx(
12950
+ "a",
12951
+ {
12952
+ href: pageData?.contactUsLink,
12953
+ target: "_blank",
12954
+ className: "text-[14px] cursor-pointer w-fit rounded-full text-[#080A0F] border-2 border-[#080A0F] px-[20px] l:px-[12px] py-[10px] leading-[1] hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
12955
+ rel: "noreferrer",
12956
+ children: pageData.contactUs
12957
+ }
12958
+ ),
12959
+ onScheduleAgain && bookingData && /* @__PURE__ */ jsx(
12960
+ "button",
12961
+ {
12962
+ onClick: () => onScheduleAgain(bookingData.demoroom_code),
12963
+ className: "text-[14px] cursor-pointer w-fit bg-black text-white rounded-full hover:bg-gray-800 border-2 border-[#080A0F] px-[20px] l:px-[12px] py-[10px] leading-[1] transition-colors",
12964
+ children: pageData.scheduleAgain
12965
+ }
12966
+ )
12967
+ ] })
12889
12968
  ] }),
12890
12969
  /* @__PURE__ */ jsxs(
12891
12970
  "div",
12892
12971
  {
12893
- className: bookingData.business_type === "pod" ? "grid grid-cols-2 gap-[16px] l:grid-cols-1 print:grid-cols-1" : "",
12972
+ className: bookingData.business_type === "pod" && !isCancelled && !isStore ? "grid grid-cols-2 gap-[16px] l:grid-cols-1 print:grid-cols-1" : "",
12894
12973
  children: [
12895
12974
  /* @__PURE__ */ jsxs("div", { className: "space-y-8 bg-white px-[48px] l:px-[16px] l:py-[16px] py-[32px] rounded-[16px] print:hidden", children: [
12896
12975
  /* @__PURE__ */ jsxs("div", { children: [
@@ -13002,7 +13081,7 @@ var BookingSuccessO2O = ({
13002
13081
  ] })
13003
13082
  ] })
13004
13083
  ] }),
13005
- bookingData.business_type === "pod" && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-[16px] px-[48px] l:px-[16px] l:py-[16px] py-[32px] flex flex-col items-center justify-center text-center print:w-full", children: [
13084
+ bookingData.business_type === "pod" && !isStore && !isCancelled && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-[16px] px-[48px] l:px-[16px] l:py-[16px] py-[32px] flex flex-col items-center justify-center text-center print:w-full", children: [
13006
13085
  /* @__PURE__ */ jsx("h2", { className: "text-[24px] l:text-[20px] text-[#4A4C56] text-center", children: pageData.podData?.QRCodeTitle }),
13007
13086
  /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 text-center mt-2", children: pageData.podData?.QRCodeSubTitle }),
13008
13087
  /* @__PURE__ */ jsx(
@@ -13020,19 +13099,19 @@ var BookingSuccessO2O = ({
13020
13099
  }
13021
13100
  ),
13022
13101
  /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-3 mt-6 print:hidden", children: [
13023
- /* @__PURE__ */ jsx(
13102
+ !!pageData.podData?.btnToWallet && /* @__PURE__ */ jsx(
13024
13103
  "button",
13025
13104
  {
13026
13105
  onClick: () => onAddToWallet?.(bookingData),
13027
- className: "rounded-full border-2 border-[#080A0F] px-[20px] py-[10px] text-[14px] hover:bg-gray-50 transition-colors",
13106
+ className: "text-[14px] cursor-pointer w-fit rounded-full text-[#080A0F] border-2 border-[#080A0F] px-[20px] py-[10px] leading-[1] hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
13028
13107
  children: pageData.podData?.btnToWallet
13029
13108
  }
13030
13109
  ),
13031
- /* @__PURE__ */ jsx(
13110
+ !!pageData.podData?.btnToPrint && /* @__PURE__ */ jsx(
13032
13111
  "button",
13033
13112
  {
13034
13113
  onClick: handlePrintQRCode,
13035
- className: "rounded-full border-2 border-[#080A0F] px-[20px] py-[10px] text-[14px] hover:bg-gray-50 transition-colors",
13114
+ className: "text-[14px] cursor-pointer w-fit rounded-full text-[#080A0F] border-2 border-[#080A0F] px-[20px] py-[10px] leading-[1] hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
13036
13115
  children: pageData.podData?.btnToPrint
13037
13116
  }
13038
13117
  )
@@ -13041,8 +13120,8 @@ var BookingSuccessO2O = ({
13041
13120
  ]
13042
13121
  }
13043
13122
  ),
13044
- !isCancelled && /* @__PURE__ */ jsxs("div", { className: "mt-[64px] print:hidden", children: [
13045
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
13123
+ isPending && /* @__PURE__ */ jsxs("div", { className: "mt-[64px] pb-4 print:hidden", children: [
13124
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs("div", { className: "flex md:w-full gap-4 md:flex-col md:items-center md:justify-center", children: [
13046
13125
  onEditBooking && token && /* @__PURE__ */ jsx(
13047
13126
  "button",
13048
13127
  {
@@ -13051,7 +13130,7 @@ var BookingSuccessO2O = ({
13051
13130
  bookingData.demoroom_code,
13052
13131
  bookingData.business_type
13053
13132
  ),
13054
- className: "text-[14px] cursor-pointer w-fit rounded-full text-[#080A0F] border-2 border-[#080A0F] px-[20px] py-[10px] leading-[1] hover:bg-gray-50 transition-colors",
13133
+ className: "text-[14px] cursor-pointer w-fit bg-black text-white rounded-full hover:bg-gray-800 border-2 border-[#080A0F] l:px-[12px] px-[20px] py-[10px] leading-[1] transition-colors",
13055
13134
  children: pageData.editAppointment
13056
13135
  }
13057
13136
  ),
@@ -13060,13 +13139,25 @@ var BookingSuccessO2O = ({
13060
13139
  {
13061
13140
  onClick: () => setShowCancelDialog(true),
13062
13141
  disabled: cancelLoading,
13063
- className: "text-[14px] cursor-pointer w-fit rounded-full text-[#080A0F] border-2 border-[#080A0F] px-[20px] py-[10px] leading-[1] hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
13142
+ className: "text-[14px] cursor-pointer w-fit rounded-full text-[#080A0F] border-2 border-[#080A0F] px-[20px] l:px-[12px] py-[10px] leading-[1] hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
13064
13143
  children: pageData.cancelAppointment
13065
13144
  }
13066
13145
  )
13067
- ] }),
13146
+ ] }) }),
13068
13147
  cancelError && /* @__PURE__ */ jsx("p", { className: "text-sm mt-2", style: { color: "#FF4D4D" }, children: cancelError })
13069
13148
  ] }),
13149
+ isStore && bookingData?.print_status === "completed" && /* @__PURE__ */ jsxs("div", { className: "mt-[64px] pb-4 print:hidden", children: [
13150
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsx(
13151
+ "button",
13152
+ {
13153
+ onClick: handleCheckin,
13154
+ disabled: checkinLoading,
13155
+ className: "text-[14px] cursor-pointer w-fit rounded-full text-[#080A0F] border-2 border-[#080A0F] px-[20px] l:px-[12px] py-[10px] leading-[1] hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
13156
+ children: pageData.changeStatusButton || "Change Pickup Status"
13157
+ }
13158
+ ) }),
13159
+ checkinError && /* @__PURE__ */ jsx("p", { className: "text-sm mt-2", style: { color: "#FF4D4D" }, children: checkinError })
13160
+ ] }),
13070
13161
  showCancelDialog && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 px-4 print:hidden", children: /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-[24px] max-w-[600px] p-8 shadow-xl relative", children: [
13071
13162
  /* @__PURE__ */ jsx(
13072
13163
  "button",