pih-appointment-widget 0.0.29 → 0.0.31

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.
@@ -544,6 +544,39 @@ const AppointmentPage = _ref => {
544
544
  }
545
545
  };
546
546
 
547
+ // Returns true if the current time is within 2 hours after the appointment's scheduled slot time.
548
+ // Handles date format: "Sun, 15 Mar 2026" and time format: "12:15 PM"
549
+ const isWithinJoinWindow = appointment => {
550
+ const dateStr = appointment?.date || appointment?.appointmentDate;
551
+ const timeStr = appointment?.time || appointment?.appointmentTime;
552
+ if (!dateStr || !timeStr) return false;
553
+ try {
554
+ // Parse "12:15 PM" or "9:30 AM" into 24-hour h/m values
555
+ const ampmMatch = String(timeStr).trim().match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i);
556
+ let h, m;
557
+ if (ampmMatch) {
558
+ h = parseInt(ampmMatch[1], 10);
559
+ m = parseInt(ampmMatch[2], 10);
560
+ const period = ampmMatch[3].toUpperCase();
561
+ if (period === "AM" && h === 12) h = 0;
562
+ if (period === "PM" && h !== 12) h += 12;
563
+ } else {
564
+ // Already 24-hour "HH:MM"
565
+ const parts = String(timeStr).trim().split(":");
566
+ h = parseInt(parts[0], 10);
567
+ m = parseInt(parts[1], 10);
568
+ }
569
+ if (isNaN(h) || isNaN(m)) return false;
570
+ // "Sun, 15 Mar 2026 12:15:00" — space-separated; JS parses RFC-like date strings correctly
571
+ const appointmentDate = new Date(`${dateStr} ${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:00`);
572
+ if (isNaN(appointmentDate.getTime())) return false;
573
+ const windowEnd = new Date(appointmentDate.getTime() + 2 * 60 * 60 * 1000);
574
+ return new Date() <= windowEnd;
575
+ } catch {
576
+ return false;
577
+ }
578
+ };
579
+
547
580
  // Handle join call — call initiate API to get LiveKit token+url, then open PiP
548
581
  const handleJoinCall = async () => {
549
582
  if (!selectedAppointment || !appToken) return;
@@ -616,25 +649,6 @@ const AppointmentPage = _ref => {
616
649
  fetchAppointments();
617
650
  };
618
651
 
619
- // End call silently when user presses browser back button during an active call.
620
- (0, _react.useEffect)(() => {
621
- if (!showPipVideo) return;
622
- window.history.pushState({
623
- pipActive: true
624
- }, "");
625
- const handlePopState = () => {
626
- setShowPipVideo(false);
627
- setIsPipMinimized(false);
628
- setIsPipFullscreen(false);
629
- setCallToken(null);
630
- setCallUrl(null);
631
- setCallError(null);
632
- window.history.back();
633
- };
634
- window.addEventListener("popstate", handlePopState);
635
- return () => window.removeEventListener("popstate", handlePopState);
636
- }, [showPipVideo]);
637
-
638
652
  // Handle PiP minimize
639
653
  const handleTogglePipSize = () => {
640
654
  if (isPipFullscreen) {
@@ -2096,7 +2110,7 @@ const AppointmentPage = _ref => {
2096
2110
  fontSize: isMobile ? "11px" : "12px",
2097
2111
  lineHeight: "1.4"
2098
2112
  }
2099
- }, selectedAppointment?.reason || selectedAppointment?.reasonForAppointment || "No reason provided"))), activeTab === "upcoming" && /*#__PURE__*/_react.default.createElement("div", {
2113
+ }, selectedAppointment?.reason || selectedAppointment?.reasonForAppointment || "No reason provided"))), (activeTab === "upcoming" || activeTab === "completed" && isWithinJoinWindow(selectedAppointment)) && /*#__PURE__*/_react.default.createElement("div", {
2100
2114
  style: {
2101
2115
  display: "flex",
2102
2116
  flexDirection: isMobile ? "column" : "row",
@@ -2105,7 +2119,7 @@ const AppointmentPage = _ref => {
2105
2119
  }
2106
2120
  }, /*#__PURE__*/_react.default.createElement("button", {
2107
2121
  type: "button",
2108
- onClick: handleJoinCall,
2122
+ onClick: !callLoading ? handleJoinCall : undefined,
2109
2123
  disabled: callLoading,
2110
2124
  style: {
2111
2125
  flex: 1,
@@ -2119,7 +2133,7 @@ const AppointmentPage = _ref => {
2119
2133
  fontSize: isMobile ? "11px" : "12px",
2120
2134
  cursor: callLoading ? "not-allowed" : "pointer"
2121
2135
  }
2122
- }, callLoading ? "Connecting..." : "Join Call >")), activeTab === "upcoming" && callError && /*#__PURE__*/_react.default.createElement("div", {
2136
+ }, callLoading ? "Connecting..." : "Join Call >")), (activeTab === "upcoming" || activeTab === "completed") && callError && /*#__PURE__*/_react.default.createElement("div", {
2123
2137
  style: {
2124
2138
  fontSize: "11px",
2125
2139
  color: "#e53935",
@@ -2445,21 +2459,14 @@ const AppointmentPage = _ref => {
2445
2459
  color: "#1a1a1a",
2446
2460
  margin: "0 0 8px 0"
2447
2461
  }
2448
- }, tokenError ? "Not authorised" : "Sign in required"), /*#__PURE__*/_react.default.createElement("p", {
2462
+ }, "Access Denied"), /*#__PURE__*/_react.default.createElement("p", {
2449
2463
  style: {
2450
2464
  fontSize: "14px",
2451
2465
  color: "#666",
2452
2466
  margin: 0,
2453
2467
  lineHeight: 1.5
2454
2468
  }
2455
- }, authErrorMessage), /*#__PURE__*/_react.default.createElement("p", {
2456
- style: {
2457
- fontSize: "13px",
2458
- color: "#999",
2459
- marginTop: "16px",
2460
- marginBottom: 0
2461
- }
2462
- }, "Redirecting to login..."))));
2469
+ }, "You do not have permission to access Afiya Pro. Please contact administrator for assistance."))));
2463
2470
  }
2464
2471
  return /*#__PURE__*/_react.default.createElement(AppointmentErrorBoundary, null, content);
2465
2472
  };
@@ -29,5 +29,5 @@ const DEFAULT_PARAMS = exports.DEFAULT_PARAMS = {
29
29
  const REQUEST_TIMEOUT = exports.REQUEST_TIMEOUT = 10000;
30
30
 
31
31
  // Join call URL (will be dynamic from auth API later)
32
- const JOIN_CALL_URL = exports.JOIN_CALL_URL = "https://wbafedevittisalwe01-had2b3e0a7h6fyey.westeurope-01.azurewebsites.net/call/";
33
- const WEB_URL = exports.WEB_URL = "https://wbaemrdevittisalwe01-fnapdpfme7bvduhh.westeurope-01.azurewebsites.net/";
32
+ const JOIN_CALL_URL = exports.JOIN_CALL_URL = "https://ittisalqa.powermindinc.com/call/";
33
+ const WEB_URL = exports.WEB_URL = "https://afiyaproqa.powermindinc.com/";