pih-appointment-widget 0.0.20 → 0.0.22

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.
@@ -28,6 +28,7 @@ const STORAGE_KEY_EMAIL = "pih_appointment_email";
28
28
  const STORAGE_KEY_APP_TOKEN = "pih_appointment_appToken";
29
29
  const STORAGE_KEY_DOCTOR_ID = "pih_appointment_doctorId";
30
30
  const STORAGE_KEY_USER_NAME = "pih_appointment_userName";
31
+ const STORAGE_KEY_API_BASE_URL = "pih_appointment_apiBaseUrl";
31
32
  const DEFAULT_PIP_WIDTH = 720;
32
33
  const DEFAULT_PIP_HEIGHT = 560;
33
34
 
@@ -117,7 +118,14 @@ const AppointmentPage = _ref => {
117
118
  let {
118
119
  config = {}
119
120
  } = _ref;
120
- const apiBaseUrl = config.apiBaseUrl || _apiConfig.API_BASE_URL;
121
+ const [storedApiBaseUrl, setStoredApiBaseUrl] = (0, _react.useState)(() => {
122
+ try {
123
+ return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_API_BASE_URL) : null;
124
+ } catch {
125
+ return null;
126
+ }
127
+ });
128
+ const apiBaseUrl = config.apiBaseUrl || storedApiBaseUrl || _apiConfig.API_BASE_URL;
121
129
  const hospitalId = config.hospitalId || _apiConfig.DEFAULT_PARAMS.hospitalId;
122
130
 
123
131
  // idToken/email: config first, then localStorage. When Flutter (or parent) passes a new token, we use it and re-login.
@@ -161,8 +169,12 @@ const AppointmentPage = _ref => {
161
169
  localStorage.setItem(STORAGE_KEY_EMAIL, config.email);
162
170
  setStoredEmail(config.email);
163
171
  }
172
+ if (config.apiBaseUrl && String(config.apiBaseUrl).trim()) {
173
+ localStorage.setItem(STORAGE_KEY_API_BASE_URL, config.apiBaseUrl.trim());
174
+ setStoredApiBaseUrl(config.apiBaseUrl.trim());
175
+ }
164
176
  } catch (e) {}
165
- }, [config.idToken, config.token, config.email]);
177
+ }, [config.idToken, config.token, config.email, config.apiBaseUrl]);
166
178
  const [appToken, setAppToken] = (0, _react.useState)(() => {
167
179
  try {
168
180
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_APP_TOKEN) : null;
@@ -319,6 +331,8 @@ const AppointmentPage = _ref => {
319
331
  const [selectedDate, setSelectedDate] = (0, _react.useState)("today"); // today, tomorrow, week, month, year, custom
320
332
  const [dateOption, setDateOption] = (0, _react.useState)("today"); // Currently selected option in dropdown
321
333
  const [showDatePicker, setShowDatePicker] = (0, _react.useState)(false);
334
+ const [showAppointmentTypePicker, setShowAppointmentTypePicker] = (0, _react.useState)(false);
335
+ const [appointmentTypeFilter, setAppointmentTypeFilter] = (0, _react.useState)("all"); // 'all' | 'ONLINE' | 'PHYSICAL'
322
336
  const [sortOrder, setSortOrder] = (0, _react.useState)("asc"); // asc or desc for date sorting
323
337
  const [searchQuery, setSearchQuery] = (0, _react.useState)(""); // Search query for filtering
324
338
 
@@ -429,10 +443,11 @@ const AppointmentPage = _ref => {
429
443
  setSelectedAppointment(sortedAppointments[0]);
430
444
  }
431
445
  };
432
- const fetchAppointments = (0, _react.useCallback)(async () => {
446
+ const fetchAppointments = (0, _react.useCallback)(async overrideType => {
433
447
  if (!appToken) return;
434
448
  console.log(doctorIdFromLogin, 'fetchAppointments -> doctorIdFromLogin');
435
449
  const doctorId = doctorIdFromLogin;
450
+ const typeToUse = overrideType !== undefined ? overrideType : appointmentTypeFilter;
436
451
  setLoading(true);
437
452
  setError(null);
438
453
  try {
@@ -442,7 +457,7 @@ const AppointmentPage = _ref => {
442
457
  doctorId,
443
458
  token: appToken
444
459
  };
445
- const response = await (0, _appointmentService.getAppointmentsByStatus)(activeTab, fromDate, toDate, serviceConfig);
460
+ const response = await (0, _appointmentService.getAppointmentsByStatus)(activeTab, fromDate, toDate, typeToUse, serviceConfig);
446
461
  if (response.status === 401 || response.status === 403) {
447
462
  // Token expired — clear stored token and trigger re-login (SSO effect will fire)
448
463
  try {
@@ -476,7 +491,7 @@ const AppointmentPage = _ref => {
476
491
  } finally {
477
492
  setLoading(false);
478
493
  }
479
- }, [activeTab, fromDate, toDate, apiBaseUrl, hospitalId, doctorIdFromLogin, appToken]);
494
+ }, [activeTab, fromDate, toDate, appointmentTypeFilter, apiBaseUrl, hospitalId, doctorIdFromLogin, appToken]);
480
495
 
481
496
  // Handle appointment selection - no API call, just show data from list
482
497
  const handleAppointmentSelect = appointment => {
@@ -492,6 +507,7 @@ const AppointmentPage = _ref => {
492
507
  localStorage.removeItem(STORAGE_KEY_APP_TOKEN);
493
508
  localStorage.removeItem(STORAGE_KEY_DOCTOR_ID);
494
509
  localStorage.removeItem(STORAGE_KEY_USER_NAME);
510
+ localStorage.removeItem(STORAGE_KEY_API_BASE_URL);
495
511
  }
496
512
  } catch (e) {}
497
513
  setShowProfileDropdown(false);
@@ -781,7 +797,7 @@ const AppointmentPage = _ref => {
781
797
  // Reset page to 1 when filters change
782
798
  (0, _react.useEffect)(() => {
783
799
  setCurrentPage(1);
784
- }, [activeTab, selectedDate, fromDate, toDate, searchQuery]);
800
+ }, [activeTab, selectedDate, fromDate, toDate, searchQuery, appointmentTypeFilter]);
785
801
 
786
802
  // Fetch appointments when we have appToken (tab/date change triggers refetch via fetchAppointments deps)
787
803
  (0, _react.useEffect)(() => {
@@ -838,18 +854,21 @@ const AppointmentPage = _ref => {
838
854
  };
839
855
  }, []);
840
856
 
841
- // Close date picker when clicking outside
857
+ // Close date picker and appointment type picker when clicking outside
842
858
  (0, _react.useEffect)(() => {
843
859
  const handleClickOutside = event => {
844
860
  if (showDatePicker && !event.target.closest('button') && !event.target.closest('input[type="date"]')) {
845
861
  setShowDatePicker(false);
846
862
  }
863
+ if (showAppointmentTypePicker && !event.target.closest('[data-appointment-type-picker]')) {
864
+ setShowAppointmentTypePicker(false);
865
+ }
847
866
  };
848
867
  document.addEventListener("click", handleClickOutside);
849
868
  return () => {
850
869
  document.removeEventListener("click", handleClickOutside);
851
870
  };
852
- }, [showDatePicker]);
871
+ }, [showDatePicker, showAppointmentTypePicker]);
853
872
  let fontFamily = '"Nunito", serif';
854
873
 
855
874
  // Error as popup overlay (main page stays in background); auto-redirect to home
@@ -1202,9 +1221,133 @@ const AppointmentPage = _ref => {
1202
1221
  alignItems: "center",
1203
1222
  width: isMobile ? "auto" : "auto",
1204
1223
  position: "relative",
1205
- justifyContent: isMobile ? "flex-start" : "flex-end"
1224
+ justifyContent: isMobile ? "flex-start" : "flex-end",
1225
+ flexWrap: "wrap"
1206
1226
  }
1227
+ }, /*#__PURE__*/_react.default.createElement("div", {
1228
+ style: {
1229
+ position: "relative"
1230
+ },
1231
+ "data-appointment-type-picker": true
1207
1232
  }, /*#__PURE__*/_react.default.createElement("button", {
1233
+ onClick: () => setShowAppointmentTypePicker(!showAppointmentTypePicker),
1234
+ style: {
1235
+ padding: isMobile ? "8px 12px" : "8px 12px",
1236
+ fontFamily,
1237
+ fontWeight: 600,
1238
+ border: "1px solid #E5E5E5",
1239
+ borderRadius: "6px",
1240
+ fontSize: isMobile ? "11px" : "13px",
1241
+ color: "#1a1a1a",
1242
+ background: "#FFFFFF",
1243
+ display: "flex",
1244
+ alignItems: "center",
1245
+ gap: isMobile ? "4px" : "6px",
1246
+ cursor: "pointer",
1247
+ flex: "none",
1248
+ minWidth: isMobile ? "100px" : "auto",
1249
+ justifyContent: "center"
1250
+ }
1251
+ }, /*#__PURE__*/_react.default.createElement("svg", {
1252
+ width: isMobile ? "14" : "16",
1253
+ height: isMobile ? "14" : "16",
1254
+ viewBox: "0 0 24 24",
1255
+ fill: "none",
1256
+ stroke: "currentColor",
1257
+ strokeWidth: "2",
1258
+ strokeLinecap: "round",
1259
+ strokeLinejoin: "round"
1260
+ }, /*#__PURE__*/_react.default.createElement("path", {
1261
+ d: "M4.8 2A2.8 2.8 0 0 0 2 4.8v14.4A2.8 2.8 0 0 0 4.8 22h14.4a2.8 2.8 0 0 0 2.8-2.8V4.8A2.8 2.8 0 0 0 19.2 2H4.8z"
1262
+ }), /*#__PURE__*/_react.default.createElement("path", {
1263
+ d: "M8 12h8M8 16h5"
1264
+ })), /*#__PURE__*/_react.default.createElement("span", {
1265
+ style: {
1266
+ overflow: "hidden",
1267
+ textOverflow: "ellipsis",
1268
+ whiteSpace: "nowrap",
1269
+ color: "#4C4DDC"
1270
+ }
1271
+ }, appointmentTypeFilter === "all" ? "All Appointment" : appointmentTypeFilter === "ONLINE" ? "Online" : "Physical"), /*#__PURE__*/_react.default.createElement("svg", {
1272
+ width: isMobile ? "8" : "10",
1273
+ height: isMobile ? "8" : "10",
1274
+ viewBox: "0 0 24 24",
1275
+ fill: "none",
1276
+ stroke: "currentColor",
1277
+ strokeWidth: "2",
1278
+ strokeLinecap: "round",
1279
+ strokeLinejoin: "round"
1280
+ }, /*#__PURE__*/_react.default.createElement("polyline", {
1281
+ points: "6 9 12 15 18 9"
1282
+ }))), showAppointmentTypePicker && /*#__PURE__*/_react.default.createElement("div", {
1283
+ style: {
1284
+ position: "absolute",
1285
+ top: "100%",
1286
+ right: isMobile ? "auto" : 0,
1287
+ left: isMobile ? 0 : "auto",
1288
+ marginTop: "4px",
1289
+ background: "#FFFFFF",
1290
+ border: "1px solid #E5E5E5",
1291
+ borderRadius: "8px",
1292
+ boxShadow: "0 4px 16px rgba(0,0,0,0.15)",
1293
+ padding: "8px",
1294
+ zIndex: 1000,
1295
+ minWidth: isMobile ? "240px" : "200px",
1296
+ width: isMobile ? "calc(100vw - 24px)" : "auto",
1297
+ maxWidth: isMobile ? "calc(100vw - 24px)" : "240px"
1298
+ }
1299
+ }, [{
1300
+ value: "all",
1301
+ label: "All Appointment"
1302
+ }, {
1303
+ value: "ONLINE",
1304
+ label: "Online"
1305
+ }, {
1306
+ value: "PHYSICAL",
1307
+ label: "Physical"
1308
+ }].map(_ref2 => {
1309
+ let {
1310
+ value,
1311
+ label
1312
+ } = _ref2;
1313
+ return /*#__PURE__*/_react.default.createElement("button", {
1314
+ key: value,
1315
+ onClick: () => {
1316
+ setAppointmentTypeFilter(value);
1317
+ setShowAppointmentTypePicker(false);
1318
+ fetchAppointments(value);
1319
+ },
1320
+ style: {
1321
+ width: "100%",
1322
+ padding: "10px 12px",
1323
+ background: appointmentTypeFilter === value ? "#E8EEF4" : "#FFFFFF",
1324
+ border: "none",
1325
+ borderRadius: "4px",
1326
+ fontSize: "13px",
1327
+ fontFamily,
1328
+ cursor: "pointer",
1329
+ textAlign: "left",
1330
+ fontWeight: appointmentTypeFilter === value ? 600 : 400,
1331
+ color: appointmentTypeFilter === value ? "#4C4DDC" : "#1a1a1a",
1332
+ marginBottom: "4px",
1333
+ display: "flex",
1334
+ justifyContent: "space-between",
1335
+ alignItems: "center",
1336
+ transition: "all 0.2s ease"
1337
+ },
1338
+ onMouseEnter: e => {
1339
+ if (appointmentTypeFilter !== value) e.target.style.background = "#F5F5F5";
1340
+ },
1341
+ onMouseLeave: e => {
1342
+ if (appointmentTypeFilter !== value) e.target.style.background = "#FFFFFF";
1343
+ }
1344
+ }, /*#__PURE__*/_react.default.createElement("span", null, label), appointmentTypeFilter === value && /*#__PURE__*/_react.default.createElement("span", {
1345
+ style: {
1346
+ color: "#4C4DDC",
1347
+ fontSize: "16px"
1348
+ }
1349
+ }, "\u2713"));
1350
+ }))), /*#__PURE__*/_react.default.createElement("button", {
1208
1351
  onClick: () => {
1209
1352
  // Initialize temp dates and option with current values when opening picker
1210
1353
  if (!showDatePicker) {
@@ -22,8 +22,7 @@ const API_PATHS = exports.API_PATHS = {
22
22
 
23
23
  // Default request parameters (will be fetched from auth API later)
24
24
  const DEFAULT_PARAMS = exports.DEFAULT_PARAMS = {
25
- hospitalId: "dMtEGhak",
26
- doctorId: 6694
25
+ hospitalId: "dMtEGhak"
27
26
  };
28
27
 
29
28
  // Request timeout (milliseconds)
@@ -149,8 +149,7 @@
149
149
 
150
150
  // Default request parameters (will be fetched from auth API later)
151
151
  const DEFAULT_PARAMS = {
152
- hospitalId: "dMtEGhak",
153
- doctorId: 6694
152
+ hospitalId: "dMtEGhak"
154
153
  };
155
154
 
156
155
  // Join call URL (will be dynamic from auth API later)
@@ -165,16 +164,16 @@
165
164
  * @param {object} config - Optional configuration { apiBaseUrl, hospitalId, doctorId }
166
165
  * @returns {Promise} Appointments data
167
166
  */
168
- const getAppointmentsByStatus = async function (status, fromDate, toDate) {
169
- let config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
167
+ const getAppointmentsByStatus = async function (status, fromDate, toDate, type) {
168
+ let config = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
170
169
  // Map status to API format
171
170
  let apiStatus = (status || "").toUpperCase();
172
171
  if (apiStatus === "INPROGRESS") {
173
172
  apiStatus = "IN_PROGRESS";
174
173
  }
175
- const baseURL = config.apiBaseUrl || API_BASE_URL;
174
+ const baseURL = config.apiBaseUrl;
176
175
  const hospitalId = config.hospitalId || DEFAULT_PARAMS.hospitalId;
177
- const doctorId = config.doctorId || DEFAULT_PARAMS.doctorId;
176
+ const doctorId = config.doctorId;
178
177
  const token = config.token || '';
179
178
  const params = {
180
179
  hospitalId,
@@ -183,6 +182,9 @@
183
182
  toDate,
184
183
  statuses: apiStatus
185
184
  };
185
+ if (type && String(type).toUpperCase() !== "ALL") {
186
+ params.appointmentType = String(type).toUpperCase();
187
+ }
186
188
  const url = `${baseURL}${API_PATHS.APPOINTMENTS}`;
187
189
 
188
190
  // Return raw response (including status) so caller can detect 401 and re-login
@@ -198,14 +200,15 @@
198
200
  */
199
201
  const initiateConsultation = async function (appointment) {
200
202
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
201
- const baseURL = (config.apiBaseUrl || API_BASE_URL).replace(/\/$/, "");
203
+ console.log("initiateConsultation -> config", config);
204
+ const baseURL = config.apiBaseUrl.replace(/\/$/, "");
202
205
  const url = `${baseURL}${API_PATHS.INITIATE_CALL}`;
203
206
  const appToken = config.appToken || "";
204
207
  const body = {
205
208
  patientId: String(appointment.patientId || ""),
206
209
  primaryPatientId: String(appointment.primaryPatientId || appointment.patientId || ""),
207
210
  hospitalId: config.hospitalId || DEFAULT_PARAMS.hospitalId,
208
- doctorId: String(config.doctor_id || DEFAULT_PARAMS.doctorId),
211
+ doctorId: String(config.doctorId),
209
212
  patientName: appointment.patientName || appointment.name || "",
210
213
  doctorName: appointment.doctorName || config.doctorName,
211
214
  appointmentId: String(appointment.id || appointment.appointmentId || appointment._id || "")
@@ -231,6 +234,7 @@
231
234
  const STORAGE_KEY_APP_TOKEN = "pih_appointment_appToken";
232
235
  const STORAGE_KEY_DOCTOR_ID = "pih_appointment_doctorId";
233
236
  const STORAGE_KEY_USER_NAME = "pih_appointment_userName";
237
+ const STORAGE_KEY_API_BASE_URL = "pih_appointment_apiBaseUrl";
234
238
  const DEFAULT_PIP_WIDTH = 720;
235
239
  const DEFAULT_PIP_HEIGHT = 560;
236
240
 
@@ -320,7 +324,14 @@
320
324
  let {
321
325
  config = {}
322
326
  } = _ref;
323
- const apiBaseUrl = config.apiBaseUrl || API_BASE_URL;
327
+ const [storedApiBaseUrl, setStoredApiBaseUrl] = React.useState(() => {
328
+ try {
329
+ return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_API_BASE_URL) : null;
330
+ } catch {
331
+ return null;
332
+ }
333
+ });
334
+ const apiBaseUrl = config.apiBaseUrl || storedApiBaseUrl || API_BASE_URL;
324
335
  const hospitalId = config.hospitalId || DEFAULT_PARAMS.hospitalId;
325
336
 
326
337
  // idToken/email: config first, then localStorage. When Flutter (or parent) passes a new token, we use it and re-login.
@@ -364,8 +375,12 @@
364
375
  localStorage.setItem(STORAGE_KEY_EMAIL, config.email);
365
376
  setStoredEmail(config.email);
366
377
  }
378
+ if (config.apiBaseUrl && String(config.apiBaseUrl).trim()) {
379
+ localStorage.setItem(STORAGE_KEY_API_BASE_URL, config.apiBaseUrl.trim());
380
+ setStoredApiBaseUrl(config.apiBaseUrl.trim());
381
+ }
367
382
  } catch (e) {}
368
- }, [config.idToken, config.token, config.email]);
383
+ }, [config.idToken, config.token, config.email, config.apiBaseUrl]);
369
384
  const [appToken, setAppToken] = React.useState(() => {
370
385
  try {
371
386
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_APP_TOKEN) : null;
@@ -522,6 +537,8 @@
522
537
  const [selectedDate, setSelectedDate] = React.useState("today"); // today, tomorrow, week, month, year, custom
523
538
  const [dateOption, setDateOption] = React.useState("today"); // Currently selected option in dropdown
524
539
  const [showDatePicker, setShowDatePicker] = React.useState(false);
540
+ const [showAppointmentTypePicker, setShowAppointmentTypePicker] = React.useState(false);
541
+ const [appointmentTypeFilter, setAppointmentTypeFilter] = React.useState("all"); // 'all' | 'ONLINE' | 'PHYSICAL'
525
542
  const [sortOrder, setSortOrder] = React.useState("asc"); // asc or desc for date sorting
526
543
  const [searchQuery, setSearchQuery] = React.useState(""); // Search query for filtering
527
544
 
@@ -632,10 +649,11 @@
632
649
  setSelectedAppointment(sortedAppointments[0]);
633
650
  }
634
651
  };
635
- const fetchAppointments = React.useCallback(async () => {
652
+ const fetchAppointments = React.useCallback(async overrideType => {
636
653
  if (!appToken) return;
637
654
  console.log(doctorIdFromLogin, 'fetchAppointments -> doctorIdFromLogin');
638
655
  const doctorId = doctorIdFromLogin;
656
+ const typeToUse = overrideType !== undefined ? overrideType : appointmentTypeFilter;
639
657
  setLoading(true);
640
658
  setError(null);
641
659
  try {
@@ -645,7 +663,7 @@
645
663
  doctorId,
646
664
  token: appToken
647
665
  };
648
- const response = await getAppointmentsByStatus(activeTab, fromDate, toDate, serviceConfig);
666
+ const response = await getAppointmentsByStatus(activeTab, fromDate, toDate, typeToUse, serviceConfig);
649
667
  if (response.status === 401 || response.status === 403) {
650
668
  // Token expired — clear stored token and trigger re-login (SSO effect will fire)
651
669
  try {
@@ -679,7 +697,7 @@
679
697
  } finally {
680
698
  setLoading(false);
681
699
  }
682
- }, [activeTab, fromDate, toDate, apiBaseUrl, hospitalId, doctorIdFromLogin, appToken]);
700
+ }, [activeTab, fromDate, toDate, appointmentTypeFilter, apiBaseUrl, hospitalId, doctorIdFromLogin, appToken]);
683
701
 
684
702
  // Handle appointment selection - no API call, just show data from list
685
703
  const handleAppointmentSelect = appointment => {
@@ -966,7 +984,7 @@
966
984
  // Reset page to 1 when filters change
967
985
  React.useEffect(() => {
968
986
  setCurrentPage(1);
969
- }, [activeTab, selectedDate, fromDate, toDate, searchQuery]);
987
+ }, [activeTab, selectedDate, fromDate, toDate, searchQuery, appointmentTypeFilter]);
970
988
 
971
989
  // Fetch appointments when we have appToken (tab/date change triggers refetch via fetchAppointments deps)
972
990
  React.useEffect(() => {
@@ -1023,18 +1041,21 @@
1023
1041
  };
1024
1042
  }, []);
1025
1043
 
1026
- // Close date picker when clicking outside
1044
+ // Close date picker and appointment type picker when clicking outside
1027
1045
  React.useEffect(() => {
1028
1046
  const handleClickOutside = event => {
1029
1047
  if (showDatePicker && !event.target.closest('button') && !event.target.closest('input[type="date"]')) {
1030
1048
  setShowDatePicker(false);
1031
1049
  }
1050
+ if (showAppointmentTypePicker && !event.target.closest('[data-appointment-type-picker]')) {
1051
+ setShowAppointmentTypePicker(false);
1052
+ }
1032
1053
  };
1033
1054
  document.addEventListener("click", handleClickOutside);
1034
1055
  return () => {
1035
1056
  document.removeEventListener("click", handleClickOutside);
1036
1057
  };
1037
- }, [showDatePicker]);
1058
+ }, [showDatePicker, showAppointmentTypePicker]);
1038
1059
  let fontFamily = '"Nunito", serif';
1039
1060
 
1040
1061
  // Error as popup overlay (main page stays in background); auto-redirect to home
@@ -1241,9 +1262,133 @@
1241
1262
  alignItems: "center",
1242
1263
  width: isMobile ? "auto" : "auto",
1243
1264
  position: "relative",
1244
- justifyContent: isMobile ? "flex-start" : "flex-end"
1265
+ justifyContent: isMobile ? "flex-start" : "flex-end",
1266
+ flexWrap: "wrap"
1245
1267
  }
1268
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
1269
+ style: {
1270
+ position: "relative"
1271
+ },
1272
+ "data-appointment-type-picker": true
1246
1273
  }, /*#__PURE__*/React__default["default"].createElement("button", {
1274
+ onClick: () => setShowAppointmentTypePicker(!showAppointmentTypePicker),
1275
+ style: {
1276
+ padding: isMobile ? "8px 12px" : "8px 12px",
1277
+ fontFamily,
1278
+ fontWeight: 600,
1279
+ border: "1px solid #E5E5E5",
1280
+ borderRadius: "6px",
1281
+ fontSize: isMobile ? "11px" : "13px",
1282
+ color: "#1a1a1a",
1283
+ background: "#FFFFFF",
1284
+ display: "flex",
1285
+ alignItems: "center",
1286
+ gap: isMobile ? "4px" : "6px",
1287
+ cursor: "pointer",
1288
+ flex: "none",
1289
+ minWidth: isMobile ? "100px" : "auto",
1290
+ justifyContent: "center"
1291
+ }
1292
+ }, /*#__PURE__*/React__default["default"].createElement("svg", {
1293
+ width: isMobile ? "14" : "16",
1294
+ height: isMobile ? "14" : "16",
1295
+ viewBox: "0 0 24 24",
1296
+ fill: "none",
1297
+ stroke: "currentColor",
1298
+ strokeWidth: "2",
1299
+ strokeLinecap: "round",
1300
+ strokeLinejoin: "round"
1301
+ }, /*#__PURE__*/React__default["default"].createElement("path", {
1302
+ d: "M4.8 2A2.8 2.8 0 0 0 2 4.8v14.4A2.8 2.8 0 0 0 4.8 22h14.4a2.8 2.8 0 0 0 2.8-2.8V4.8A2.8 2.8 0 0 0 19.2 2H4.8z"
1303
+ }), /*#__PURE__*/React__default["default"].createElement("path", {
1304
+ d: "M8 12h8M8 16h5"
1305
+ })), /*#__PURE__*/React__default["default"].createElement("span", {
1306
+ style: {
1307
+ overflow: "hidden",
1308
+ textOverflow: "ellipsis",
1309
+ whiteSpace: "nowrap",
1310
+ color: "#4C4DDC"
1311
+ }
1312
+ }, appointmentTypeFilter === "all" ? "All Appointment" : appointmentTypeFilter === "ONLINE" ? "Online" : "Physical"), /*#__PURE__*/React__default["default"].createElement("svg", {
1313
+ width: isMobile ? "8" : "10",
1314
+ height: isMobile ? "8" : "10",
1315
+ viewBox: "0 0 24 24",
1316
+ fill: "none",
1317
+ stroke: "currentColor",
1318
+ strokeWidth: "2",
1319
+ strokeLinecap: "round",
1320
+ strokeLinejoin: "round"
1321
+ }, /*#__PURE__*/React__default["default"].createElement("polyline", {
1322
+ points: "6 9 12 15 18 9"
1323
+ }))), showAppointmentTypePicker && /*#__PURE__*/React__default["default"].createElement("div", {
1324
+ style: {
1325
+ position: "absolute",
1326
+ top: "100%",
1327
+ right: isMobile ? "auto" : 0,
1328
+ left: isMobile ? 0 : "auto",
1329
+ marginTop: "4px",
1330
+ background: "#FFFFFF",
1331
+ border: "1px solid #E5E5E5",
1332
+ borderRadius: "8px",
1333
+ boxShadow: "0 4px 16px rgba(0,0,0,0.15)",
1334
+ padding: "8px",
1335
+ zIndex: 1000,
1336
+ minWidth: isMobile ? "240px" : "200px",
1337
+ width: isMobile ? "calc(100vw - 24px)" : "auto",
1338
+ maxWidth: isMobile ? "calc(100vw - 24px)" : "240px"
1339
+ }
1340
+ }, [{
1341
+ value: "all",
1342
+ label: "All Appointment"
1343
+ }, {
1344
+ value: "ONLINE",
1345
+ label: "Online"
1346
+ }, {
1347
+ value: "PHYSICAL",
1348
+ label: "Physical"
1349
+ }].map(_ref2 => {
1350
+ let {
1351
+ value,
1352
+ label
1353
+ } = _ref2;
1354
+ return /*#__PURE__*/React__default["default"].createElement("button", {
1355
+ key: value,
1356
+ onClick: () => {
1357
+ setAppointmentTypeFilter(value);
1358
+ setShowAppointmentTypePicker(false);
1359
+ fetchAppointments(value);
1360
+ },
1361
+ style: {
1362
+ width: "100%",
1363
+ padding: "10px 12px",
1364
+ background: appointmentTypeFilter === value ? "#E8EEF4" : "#FFFFFF",
1365
+ border: "none",
1366
+ borderRadius: "4px",
1367
+ fontSize: "13px",
1368
+ fontFamily,
1369
+ cursor: "pointer",
1370
+ textAlign: "left",
1371
+ fontWeight: appointmentTypeFilter === value ? 600 : 400,
1372
+ color: appointmentTypeFilter === value ? "#4C4DDC" : "#1a1a1a",
1373
+ marginBottom: "4px",
1374
+ display: "flex",
1375
+ justifyContent: "space-between",
1376
+ alignItems: "center",
1377
+ transition: "all 0.2s ease"
1378
+ },
1379
+ onMouseEnter: e => {
1380
+ if (appointmentTypeFilter !== value) e.target.style.background = "#F5F5F5";
1381
+ },
1382
+ onMouseLeave: e => {
1383
+ if (appointmentTypeFilter !== value) e.target.style.background = "#FFFFFF";
1384
+ }
1385
+ }, /*#__PURE__*/React__default["default"].createElement("span", null, label), appointmentTypeFilter === value && /*#__PURE__*/React__default["default"].createElement("span", {
1386
+ style: {
1387
+ color: "#4C4DDC",
1388
+ fontSize: "16px"
1389
+ }
1390
+ }, "\u2713"));
1391
+ }))), /*#__PURE__*/React__default["default"].createElement("button", {
1247
1392
  onClick: () => {
1248
1393
  // Initialize temp dates and option with current values when opening picker
1249
1394
  if (!showDatePicker) {
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react-dom")):"function"==typeof define&&define.amd?define(["exports","react","react-dom"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).MyPackage={},e.React,e.ReactDOM)}(this,(function(e,t,n){"use strict";function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=o(t),i=o(n);const r="https://afiyaapiqa.powermindinc.com",l="/appointment/V1/consultant/all-appointments",d="/notification/V1/consultation/online/initiate",s="dMtEGhak",p=6694,c="https://wbafedevittisalwe01-had2b3e0a7h6fyey.westeurope-01.azurewebsites.net/call/",u=async function(e,t,n){let o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},a=(e||"").toUpperCase();"INPROGRESS"===a&&(a="IN_PROGRESS");const i=o.apiBaseUrl||r,d=o.hospitalId||s,c=o.doctorId||p,u=o.token||"",f={hospitalId:d,doctorId:c,fromDate:t,toDate:n,statuses:a},m=`${i}${l}`,x=await async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"";const o=new URL(e);return o.search=new URLSearchParams(t).toString(),fetch(o,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`${n}`}}).then((async e=>{const t=await e.json().catch((()=>({})));return e.ok?t:{err:t?.resultInfo?.message||"Something went wrong!",status:e.status}})).catch((e=>(console.error("Fetch error:",e),{err:e?.message||String(e)||"Network error"})))}(m,f,"PIH-Appointment-Widget",u);return x},f=async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=`${(t.apiBaseUrl||r).replace(/\/$/,"")}${d}`,o=t.appToken||"";return async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=arguments.length>4?arguments[4]:void 0;const a=new URL(e);Object.keys(n).forEach((e=>{a.searchParams.append(e,n[e])}));const i={"Content-Type":"application/json"};o&&(i.Authorization=o);const r={method:"POST",headers:i,body:JSON.stringify(t)};return fetch(a.toString(),r).then((async e=>{const t=await e.json().catch((()=>({})));return e.ok?t:{err:t?.resultInfo?.message||"Something went wrong!",status:e.status}})).catch((e=>(console.error("Fetch error:",e),{err:e.message||"Network error"})))}(n,{patientId:String(e.patientId||""),primaryPatientId:String(e.primaryPatientId||e.patientId||""),hospitalId:t.hospitalId||s,doctorId:String(t.doctor_id||p),patientName:e.patientName||e.name||"",doctorName:e.doctorName||t.doctorName,appointmentId:String(e.id||e.appointmentId||e._id||"")},"PIH-Appointment-Widget",{},o)};const m="pih_appointment_idToken",x="pih_appointment_email",g="pih_appointment_appToken",h="pih_appointment_doctorId",y="pih_appointment_userName",E=720,F="pih-appointment-widget",b="data-pih-widget";class w extends t.Component{state={hasError:!1};static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e,t){"undefined"!=typeof console&&console.error&&console.error("Appointment widget error:",e,t)}render(){return this.state.hasError?a.default.createElement("div",{className:F,[b]:"teleconsult-appointments",style:{fontFamily:'"Nunito", serif',background:"#F5F5F7",boxSizing:"border-box",minHeight:"100vh",display:"flex",alignItems:"center",justifyContent:"center",padding:"24px",textAlign:"center"}},a.default.createElement("div",{style:{maxWidth:"400px"}},a.default.createElement("div",{style:{fontSize:"48px",marginBottom:"16px"}},"⚠️"),a.default.createElement("h2",{style:{fontSize:"20px",fontWeight:700,color:"#1a1a1a",margin:"0 0 8px 0"}},"Something went wrong"),a.default.createElement("p",{style:{fontSize:"14px",color:"#666",margin:0,lineHeight:1.5}},"Please refresh the page or try again later."))):this.props.children}}const S=e=>{let{config:n={}}=e;const o=n.apiBaseUrl||r,i=n.hospitalId||s,[l,d]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(m):null}catch{return null}})),[p,S]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(x):null}catch{return null}})),v=n.idToken||n.token||l,k=n.email||p;t.useEffect((()=>{try{if("undefined"==typeof localStorage)return;const e=n.idToken||n.token;if(e&&String(e).trim()){localStorage.getItem(m)!==e&&(I(null),z(null),T(null),localStorage.removeItem(g),localStorage.removeItem(h),localStorage.removeItem(y)),localStorage.setItem(m,e),d(e)}n.email&&String(n.email).trim()&&(localStorage.setItem(x,n.email),S(n.email))}catch(e){}}),[n.idToken,n.token,n.email]);const[C,I]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(g):null}catch{return null}})),[D,z]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(h):null}catch{return null}})),[W,T]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(y):null}catch{return null}})),[M,A]=t.useState((()=>{try{if("undefined"==typeof localStorage)return!1;const e=localStorage.getItem(g),t=localStorage.getItem(m),n=localStorage.getItem(x);return!e&&!(!t||!n)}catch{return!1}})),[R,N]=t.useState(null),[P,j]=t.useState(!1),[B,H]=t.useState(0);t.useEffect((()=>{C&&M&&A(!1)}),[C,M]),t.useEffect((()=>{C||(v&&k?(j(!1),N((e=>"Sign in required. Redirecting to home..."===e?null:e))):(N("Sign in required. Redirecting to home..."),j(!0)))}),[C,v,k]),t.useEffect((()=>{if(!P)return;const e=n.homeUrl||"https://wbaemrdevittisalwe01-fnapdpfme7bvduhh.westeurope-01.azurewebsites.net/";if(!e||"undefined"==typeof window)return;const t=setTimeout((()=>{window.location.href=e}),2500);return()=>clearTimeout(t)}),[P,n.homeUrl]),t.useEffect((()=>{if(!M)return;const e=setTimeout((()=>{N("Request timed out. Please try again."),A(!1)}),3e4);return()=>clearTimeout(e)}),[M]);const L=n.joinCallUrl||c;C&&String(L||"").replace(/\/?$/,"/");const $=function(e){if(!e||"string"!=typeof e)return{};try{const t=e.split(".");if(3!==t.length)return{};const n=t[1].replace(/-/g,"+").replace(/_/g,"/"),o=n.padEnd(n.length+(4-n.length%4)%4,"=");return JSON.parse(atob(o))}catch{return{}}}(v),_=W||$.name||$.sub||"User",O=()=>(new Date).toISOString().split("T")[0],[U,Y]=t.useState("upcoming"),[V,q]=t.useState([]),[X,G]=t.useState(null),[J,K]=t.useState(!1),[Q,Z]=t.useState(null),[ee,te]=t.useState(window.innerWidth<768),[ne,oe]=t.useState("today"),[ae,ie]=t.useState("today"),[re,le]=t.useState(!1),[de,se]=t.useState("asc"),[pe,ce]=t.useState(""),[ue,fe]=t.useState(!1),[me,xe]=t.useState(!1),[ge,he]=t.useState(!1),[ye,Ee]=t.useState(null),[Fe,be]=t.useState(null),[we,Se]=t.useState(!1),[ve,ke]=t.useState(null),[Ce,Ie]=t.useState((()=>({x:Math.max(20,"undefined"!=typeof window?window.innerWidth-E-20:300),y:80}))),[De,ze]=t.useState({width:E,height:560}),[We,Te]=t.useState(!1),[Me,Ae]=t.useState({x:0,y:0}),[Re,Ne]=t.useState(!1),[Pe,je]=t.useState(null),[Be,He]=t.useState({x:0,y:0,width:0,height:0});t.useState(!1);const[Le,$e]=t.useState(1),_e=V.filter((e=>{if(!pe.trim())return!0;const t=pe.toLowerCase(),n=(e.patientName||"").toLowerCase(),o=String(e.patientId||"").toLowerCase();return n.includes(t)||o.includes(t)})),Oe=20*(Le-1),Ue=Oe+20,Ye=_e.slice(Oe,Ue),Ve=Math.ceil(_e.length/20),qe=_e.length,[Xe,Ge]=t.useState(O()),[Je,Ke]=t.useState(O()),[Qe,Ze]=t.useState(),[et,tt]=t.useState(),nt=e=>e?.id||e?._id||e?.appointmentId||e?.patientId||JSON.stringify(e),ot=e=>e?.image?e.image:null,at=e=>e?e.charAt(0).toUpperCase():"?",it=e=>{if(!e)return"#4C4DDC";const t=["#4C4DDC","#1CC3CE","#FF6B6B","#4ECDC4","#45B7D1","#FFA07A","#98D8C8","#F7DC6F"];return t[e.charCodeAt(0)%t.length]},rt=()=>{const e="asc"===de?"desc":"asc";se(e);const t=[...V].sort(((t,n)=>{const o=new Date(t.appointmentDate||t.date||0),a=new Date(n.appointmentDate||n.date||0);return"asc"===e?o-a:a-o}));q(t),$e(1),t.length>0&&G(t[0])},lt=t.useCallback((async()=>{if(!C)return;console.log(D,"fetchAppointments -> doctorIdFromLogin");const e=D;K(!0),Z(null);try{const t={apiBaseUrl:o,hospitalId:i,doctorId:e,token:C},n=await u(U,Xe,Je,t);if(401===n.status||403===n.status){try{"undefined"!=typeof localStorage&&(localStorage.removeItem(g),localStorage.removeItem(h),localStorage.removeItem(y))}catch(e){}return I(null),z(null),T(null),H((e=>e+1)),void Z("Session expired. Re-authenticating...")}if(n.err)return void Z(String(n.err||"Failed to fetch appointments"));const a=n.data||n.appointments||n||[];q(Array.isArray(a)?a:[]),Array.isArray(a)&&a.length>0?G(a[0]):G(null)}catch(e){console.error("Error fetching appointments:",e),Z(e.message||"Failed to fetch appointments")}finally{K(!1)}}),[U,Xe,Je,o,i,D,C]),dt=e=>{G(e)},st=async()=>{if(X&&C){Se(!0),ke(null);try{const e={apiBaseUrl:o,hospitalId:i,doctorId:D,doctorName:W||_,appToken:C};console.log(X,"selectedAppointment"),console.log(e,"callConfig");const t=await f(X,e);if(401===t.status||403===t.status)return ke("Session expired. Please try again."),void Se(!1);if(t.err||!t.data?.token)return ke(String(t.err||"Failed to initiate call")),void Se(!1);const a=n.joinCallUrl||c,r=t.data.token?String(a||"").replace(/\/?$/,"/")+t.data.token:"";console.log("joinCallUrl",r),Ee(t.data.token),be(r||""),fe(!0),xe(!1),he(!1),ze({width:E,height:560}),Ie({x:Math.max(20,window.innerWidth-E-20),y:80})}catch(e){ke(e.message||"Failed to initiate call")}finally{ke(null),Se(!1)}}},pt=()=>{fe(!1),xe(!1),he(!1),Ee(null),be(null),ke(null),lt()},ct=()=>{ge&&he(!1),xe(!me)},ut=()=>{me&&xe(!1),he(!ge)},ft=e=>{if(0!==e.button)return;if(e.target.closest("button"))return;e.currentTarget.setPointerCapture&&e.currentTarget.setPointerCapture(e.pointerId),Te(!0);const t=e.currentTarget.getBoundingClientRect();Ae({x:e.clientX-t.left,y:e.clientY-t.top})},mt=t.useCallback((e=>{if(!ge)if(We){const t=e.clientX-Me.x,n=e.clientY-Me.y,o=window.innerWidth-De.width,a=window.innerHeight-De.height;Ie({x:Math.max(0,Math.min(t,o)),y:Math.max(0,Math.min(n,a))})}else if(Re){const t=e.clientX-Be.x,n=e.clientY-Be.y;let o=Be.width,a=Be.height,i=Be.posX,r=Be.posY;const l=300,d=250,s=window.innerWidth-40,p=window.innerHeight-100;if("bottom-right"===Pe)o=Math.min(Math.max(Be.width+t,l),s),a=Math.min(Math.max(Be.height+n,d),p),i+o>window.innerWidth&&(o=window.innerWidth-i),r+a>window.innerHeight&&(a=window.innerHeight-r);else if("bottom-left"===Pe){o=Math.min(Math.max(Be.width-t,l),s),i=Math.max(0,Be.posX+t),0===i&&(o=Be.posX+Be.width),a=Math.min(Math.max(Be.height+n,d),p),r+a>window.innerHeight&&(a=window.innerHeight-r)}else if("top-right"===Pe){o=Math.min(Math.max(Be.width+t,l),s),i+o>window.innerWidth&&(o=window.innerWidth-i);a=Math.min(Math.max(Be.height-n,d),p),r=Math.max(0,Be.posY+n),0===r&&(a=Be.posY+Be.height)}else if("top-left"===Pe){o=Math.min(Math.max(Be.width-t,l),s),i=Math.max(0,Be.posX+t),0===i&&(o=Be.posX+Be.width);a=Math.min(Math.max(Be.height-n,d),p),r=Math.max(0,Be.posY+n),0===r&&(a=Be.posY+Be.height)}ze({width:o,height:a}),Ie({x:i,y:r})}}),[We,Re,Me,Pe,Be,Ce,De,ge]),xt=()=>{Te(!1),Ne(!1),je(null)},gt=(e,t)=>{t.preventDefault(),t.stopPropagation(),t.currentTarget.setPointerCapture&&t.currentTarget.setPointerCapture(t.pointerId),Ne(!0),je(e),He({x:t.clientX,y:t.clientY,width:De.width,height:De.height,posX:Ce.x,posY:Ce.y})};t.useEffect((()=>{if(!ue||ge)return;const e=()=>{if(!(window.innerWidth<768)){const e=me?350:De.width,t=me?60:De.height,n=window.innerWidth-40,o=window.innerHeight-100,a=Math.min(e,n),i=Math.min(t,o);a===De.width&&i===De.height||ze({width:a,height:i});const r=window.innerWidth-a-20,l=window.innerHeight-i-20;Ie((e=>({x:Math.min(e.x,r),y:Math.min(e.y,l)})))}};return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)}),[ue,me,ge,De]),t.useEffect((()=>{if(!(v&&k&&(!C||B>0)))return;let e=!1;return A(!0),N(null),(async(e,t,n,o)=>{const a=`${e.replace(/\/$/,"")}/um/user/V1/sso/login?hospitalId=${encodeURIComponent(t)}`,i={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({idToken:n,email:o})};return console.log("[getTokenFromSso] request",{url:a,body:{idToken:n?n.slice(0,50)+"...":null,email:o}}),fetch(a,i).then((e=>(console.log("[getTokenFromSso] response status",e.status,e.statusText),e.ok?e.json().then((e=>(console.log("[getTokenFromSso] success",{hasData:!!e,dataKeys:e?Object.keys(e):[],hasAccessToken:!!e?.data?.access_token}),e))):e.json().then((t=>{const n=t?.resultInfo?.message||"SSO login failed";return console.log("[getTokenFromSso] error body",t),{err:n,status:e.status}})).catch((()=>({err:"Something went wrong!",status:e.status})))))).catch((e=>(console.error("[getTokenFromSso] catch",e),{err:e.message||"Network error"})))})(o,i,v,k).then((t=>{if(e)return;const n=function(e){return!e||e.err?null:e.data?.access_token??e.data?.token??e.token??e.accessToken??null}(t);if(400===t.status)return N(t.err||"Invalid request. Redirecting to home..."),A(!1),void j(!0);if(t.err||!n){N(String(t.err||"Failed to get token")),I(null),z(null),T(null);try{"undefined"!=typeof localStorage&&(localStorage.removeItem(g),localStorage.removeItem(h),localStorage.removeItem(y))}catch(e){}}else{const e=function(e){if(!e?.data)return null;const t=e.data.doctor_id??e.data.doctorId??null;return console.log(t,"extractDoctorIdFromLoginResponse -> id"),null!=t?String(t):null}(t);console.log(e,"extractDoctorIdFromLoginResponse -> doctorId");const o=function(e){if(!e?.data)return null;const t=e.data.name??e.data.doctor_name??e.data.userName??null;return null!=t?String(t):null}(t);I(n),z(e),T(o),N(null),j(!1);try{"undefined"!=typeof localStorage&&(localStorage.setItem(g,n),e&&localStorage.setItem(h,e),o&&localStorage.setItem(y,o))}catch(e){}}})).catch((()=>{})).finally((()=>{e||A(!1)})),()=>{e=!0}}),[o,i,v,k,B]),t.useEffect((()=>{$e(1)}),[U,ne,Xe,Je,pe]),t.useEffect((()=>{!M&&C&&lt()}),[lt,C,M]),t.useEffect((()=>{const e=document.createElement("link");e.href="https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap",e.rel="stylesheet",document.head.appendChild(e);const t=document.createElement("style");t.innerHTML="\n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n @media (max-width: 768px) {\n .appointments-grid {\n grid-template-columns: 1.5fr 1fr 0.8fr !important;\n }\n .appointments-header-grid {\n grid-template-columns: 1.5fr 1fr 0.8fr !important;\n }\n .hide-on-mobile {\n display: none !important;\n }\n }\n @media (max-width: 480px) {\n .appointments-header-grid {\n font-size: 10px !important;\n }\n .appointments-grid {\n font-size: 11px !important;\n }\n }\n ",document.head.appendChild(t);const n=()=>{te(window.innerWidth<768)};return window.addEventListener("resize",n),()=>{document.head.removeChild(e),document.head.removeChild(t),window.removeEventListener("resize",n)}}),[]),t.useEffect((()=>{const e=e=>{!re||e.target.closest("button")||e.target.closest('input[type="date"]')||le(!1)};return document.addEventListener("click",e),()=>{document.removeEventListener("click",e)}}),[re]);let ht='"Nunito", serif';const yt=R||!C&&(!v||!k),Et=R||"Sign in required. Redirecting to home...";let Ft;return Ft=M&&v&&k?a.default.createElement("div",{className:F,[b]:"teleconsult-appointments",style:{fontFamily:ht,background:"#F5F5F7",boxSizing:"border-box",height:"100%",minHeight:"100vh",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"24px"}},a.default.createElement("style",null,"@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }"),a.default.createElement("div",{style:{width:"40px",height:"40px",border:"3px solid #f3f3f3",borderTop:"3px solid #4C4DDC",borderRadius:"50%",animation:"spin 1s linear infinite",marginBottom:"16px"}}),a.default.createElement("p",{style:{fontSize:"14px",color:"#666",margin:0}},"Checking authorisation...")):a.default.createElement(a.default.Fragment,null,a.default.createElement("div",{className:F,[b]:"teleconsult-appointments",style:{fontFamily:ht,background:"#F5F5F7",boxSizing:"border-box",height:"100%",minHeight:"100vh",width:"100%",display:"flex",flexDirection:"column",overflow:"hidden"}},a.default.createElement("div",{style:{background:"#FFFFFF",padding:ee?"10px 12px":"12px 24px",display:"flex",justifyContent:"space-between",alignItems:"center",borderBottom:"1px solid #E5E5E5",flexWrap:"nowrap",gap:ee?"8px":"0"}},a.default.createElement("div",{style:{position:"relative",width:ee?"calc(100% - 90px)":"480px",maxWidth:ee?"none":"480px"}},a.default.createElement("input",{type:"text",placeholder:"Search by patient name or ID",value:pe,onChange:e=>ce(e.target.value),style:{width:"100%",padding:ee?"8px 32px 8px 10px":"8px 36px 8px 14px",border:"1px solid #E5E5E5",borderRadius:"6px",fontSize:ee?"12px":"13px",fontFamily:ht,background:"#FFFFFF",outline:"none",boxSizing:"border-box"}}),pe&&a.default.createElement("button",{onClick:()=>ce(""),style:{position:"absolute",right:"8px",top:"50%",transform:"translateY(-50%)",background:"none",border:"none",cursor:"pointer",padding:"4px",display:"flex",alignItems:"center",justifyContent:"center",color:"#999",fontSize:"16px"},title:"Clear search"},"✕")),!1),a.default.createElement("div",{style:{padding:ee?"12px":"16px 24px",flex:1,minHeight:0,overflow:"hidden",display:"flex",flexDirection:"column"}},a.default.createElement("div",{style:{marginBottom:ee?"10px":"14px"}},a.default.createElement("h1",{style:{fontSize:ee?"18px":"22px",fontWeight:700,color:"#1a1a1a",margin:"0 0 2px 0"}},"Tele Consultation"),a.default.createElement("p",{style:{fontSize:ee?"11px":"12px",color:"#999",margin:0}},"Displaying All Tele Consultation Appointments")),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:ee?"flex-start":"center",marginBottom:ee?"10px":"14px",flexDirection:ee?"column":"row",gap:ee?"12px":"0"}},a.default.createElement("div",{style:{display:"flex",gap:"6px",flexWrap:"wrap",width:ee?"100%":"auto"}},a.default.createElement("button",{onClick:()=>Y("upcoming"),style:{background:"upcoming"===U?"#4C4DDC":"#FFFFFF",padding:ee?"8px 10px":"9px 16px",border:"upcoming"===U?"none":"1px solid #E5E5E5",borderRadius:"6px",fontSize:ee?"10px":"13px",color:"upcoming"===U?"white":"#555555",fontWeight:600,fontFamily:ht,cursor:"pointer",flex:ee?"1 1 auto":"none",minWidth:ee?"0":"auto",transition:"all 0.3s ease",whiteSpace:"nowrap"}},"Upcoming Appointments"),a.default.createElement("button",{onClick:()=>Y("completed"),style:{background:"completed"===U?"#4C4DDC":"#FFFFFF",padding:ee?"8px 10px":"9px 16px",border:"completed"===U?"none":"1px solid #E5E5E5",borderRadius:"6px",fontSize:ee?"10px":"13px",color:"completed"===U?"white":"#555555",fontWeight:600,fontFamily:ht,cursor:"pointer",flex:ee?"1 1 auto":"none",minWidth:ee?"0":"auto",transition:"all 0.3s ease",whiteSpace:"nowrap"}},"Completed Appointments"),a.default.createElement("button",{onClick:()=>Y("cancelled"),style:{background:"cancelled"===U?"#4C4DDC":"#FFFFFF",padding:ee?"8px 10px":"9px 16px",border:"cancelled"===U?"none":"1px solid #E5E5E5",borderRadius:"6px",fontSize:ee?"10px":"13px",color:"cancelled"===U?"white":"#555555",fontWeight:600,fontFamily:ht,cursor:"pointer",flex:ee?"1 1 auto":"none",minWidth:ee?"0":"auto",transition:"all 0.3s ease",whiteSpace:"nowrap"}},"Cancelled Appointments")),a.default.createElement("div",{style:{display:"flex",gap:"8px",alignItems:"center",width:"auto",position:"relative",justifyContent:ee?"flex-start":"flex-end"}},a.default.createElement("button",{onClick:()=>{re||(Ze(Xe),tt(Je),ie(ne)),le(!re)},style:{padding:"8px 12px",fontFamily:ht,fontWeight:600,border:"1px solid #E5E5E5",borderRadius:"6px",fontSize:ee?"11px":"13px",color:"#1a1a1a",background:"#FFFFFF",display:"flex",alignItems:"center",gap:ee?"4px":"6px",cursor:"pointer",flex:"none",minWidth:ee?"100px":"auto",justifyContent:"center"}},a.default.createElement("svg",{width:ee?"12":"14",height:ee?"12":"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},a.default.createElement("rect",{x:"3",y:"4",width:"18",height:"18",rx:"2",ry:"2"}),a.default.createElement("line",{x1:"16",y1:"2",x2:"16",y2:"6"}),a.default.createElement("line",{x1:"8",y1:"2",x2:"8",y2:"6"}),a.default.createElement("line",{x1:"3",y1:"10",x2:"21",y2:"10"})),a.default.createElement("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}},(()=>{switch(ne){case"today":default:return"Today";case"tomorrow":return"Tomorrow";case"currentWeek":return"Current Week";case"thisMonth":return"This Month";case"currentYear":return"Current Year";case"custom":return ee?"Custom":`${Xe} to ${Je}`}})()),a.default.createElement("svg",{width:ee?"8":"10",height:ee?"8":"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},a.default.createElement("polyline",{points:"6 9 12 15 18 9"}))),re&&a.default.createElement("div",{style:{position:"absolute",top:"100%",right:ee?"auto":0,left:ee?0:"auto",marginTop:"4px",background:"#FFFFFF",border:"1px solid #E5E5E5",borderRadius:"8px",boxShadow:"0 4px 16px rgba(0,0,0,0.15)",padding:"8px",zIndex:1e3,minWidth:ee?"280px":"240px",width:ee?"calc(100vw - 24px)":"auto",maxWidth:ee?"calc(100vw - 24px)":"280px"}},a.default.createElement("div",{style:{marginBottom:"custom"===ae?"12px":"0"}},["thisMonth","today","tomorrow","currentWeek","currentYear","custom"].map((e=>a.default.createElement("button",{key:e,onClick:()=>{if(ie(e),"custom"!==e){const t=(e=>{const t=new Date;let n,o;switch(e){case"today":default:n=o=O();break;case"tomorrow":const e=new Date(t);e.setDate(e.getDate()+1),n=o=e.toISOString().split("T")[0];break;case"currentWeek":const a=new Date(t),i=new Date(t),r=t.getDay(),l=0===r?-6:1-r;a.setDate(t.getDate()+l),i.setDate(a.getDate()+6),n=a.toISOString().split("T")[0],o=i.toISOString().split("T")[0];break;case"thisMonth":const d=new Date(t.getFullYear(),t.getMonth(),1),s=new Date(t.getFullYear(),t.getMonth()+1,0);n=d.toISOString().split("T")[0],o=s.toISOString().split("T")[0];break;case"currentYear":n=`${t.getFullYear()}-01-01`,o=`${t.getFullYear()}-12-31`}return{from:n,to:o}})(e);oe(e),Ge(t.from),Ke(t.to),Ze(t.from),tt(t.to),le(!1)}else Ze(""),tt("")},style:{width:"100%",padding:"10px 12px",background:ae===e?"#E8EEF4":"#FFFFFF",border:"none",borderRadius:"4px",fontSize:"13px",fontFamily:ht,cursor:"pointer",textAlign:"left",fontWeight:ae===e?600:400,color:ae===e?"#4C4DDC":"#1a1a1a",marginBottom:"4px",display:"flex",justifyContent:"space-between",alignItems:"center",transition:"all 0.2s ease"},onMouseEnter:t=>{ae!==e&&(t.target.style.background="#F5F5F5")},onMouseLeave:t=>{ae!==e&&(t.target.style.background="#FFFFFF")}},a.default.createElement("span",null,{thisMonth:"This Month",today:"Today",tomorrow:"Tomorrow",currentWeek:"Current Week",currentYear:"Current Year",custom:"Custom"}[e]),ae===e&&a.default.createElement("span",{style:{color:"#4C4DDC",fontSize:"16px"}},"✓"))))),"custom"===ae&&a.default.createElement("div",{style:{paddingTop:"8px",borderTop:"1px solid #E5E5E5"}},a.default.createElement("div",{style:{marginBottom:"8px"}},a.default.createElement("input",{type:"date",value:Qe,onChange:e=>Ze(e.target.value),placeholder:"Start Date",style:{width:"100%",padding:"10px 8px",border:"1px solid #E5E5E5",borderRadius:"4px",fontSize:"13px",fontFamily:ht,boxSizing:"border-box",cursor:"pointer"}})),a.default.createElement("div",{style:{marginBottom:"12px"}},a.default.createElement("input",{type:"date",value:et,onChange:e=>tt(e.target.value),placeholder:"End Date",style:{width:"100%",padding:"10px 8px",border:"1px solid #E5E5E5",borderRadius:"4px",fontSize:"13px",fontFamily:ht,boxSizing:"border-box",cursor:"pointer"}})),a.default.createElement("div",{style:{display:"flex",gap:"8px"}},a.default.createElement("button",{onClick:()=>{ie(ne),Ze(Xe),tt(Je),le(!1)},style:{flex:1,padding:"10px 12px",background:"#FFFFFF",color:"#4C4DDC",border:"1px solid #4C4DDC",borderRadius:"4px",fontSize:"13px",fontFamily:ht,fontWeight:600,cursor:"pointer"}},"Cancel"),a.default.createElement("button",{onClick:()=>{Qe&&et&&(oe("custom"),Ge(Qe),Ke(et),le(!1))},style:{flex:1,padding:"10px 12px",background:"#4C4DDC",color:"#FFFFFF",border:"none",borderRadius:"4px",fontSize:"13px",fontFamily:ht,fontWeight:600,cursor:"pointer"}},"Submit")))))),a.default.createElement("div",{style:{display:"flex",flexDirection:ee?"column":"row",gap:ee?"12px":"14px",flex:1,minHeight:0,overflow:ee?"auto":"hidden"}},a.default.createElement("div",{style:{flex:ee?"none":"1 1 65%",width:ee?"100%":"auto",display:"flex",flexDirection:"column",minHeight:ee?"400px":0}},a.default.createElement("div",{style:{background:"#FFFFFF",borderRadius:"8px",boxShadow:"0 1px 4px rgba(0,0,0,0.08)",overflow:"hidden",display:"flex",flexDirection:"column",flex:ee?"none":1,minHeight:ee?"auto":0}},a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:ee?"12px 14px":"14px 18px",borderBottom:"1px solid #F1F1F1"}},a.default.createElement("div",{style:{display:"flex",alignItems:"center",gap:ee?"6px":"8px"}},a.default.createElement("span",{style:{fontSize:ee?"14px":"15px",fontWeight:700,color:"#1a1a1a"}},"Appointments"),a.default.createElement("span",{style:{background:"#4C4DDC",color:"#fff",fontSize:ee?"10px":"11px",fontWeight:600,padding:ee?"2px 7px":"3px 8px",borderRadius:"12px"}},qe))),a.default.createElement("div",{className:"appointments-header-grid",style:{display:"grid",gridTemplateColumns:ee?"1.5fr 1fr 0.8fr":"2.5fr 1fr 1.5fr 0.8fr 1.2fr",gap:ee?"8px":"12px",padding:ee?"8px 12px":"10px 18px",background:"#F5F5F5",fontSize:ee?"10px":"12px",fontWeight:600,color:"#666"}},a.default.createElement("div",null,"Patients name"),!ee&&a.default.createElement("div",null,"Patient ID"),a.default.createElement("div",{onClick:rt,style:{display:"flex",alignItems:"center",gap:"3px",cursor:"pointer",userSelect:"none"}},"Date",a.default.createElement("span",{style:{opacity:.7,fontSize:"10px"}},"asc"===de?"▲":"▼")),!ee&&a.default.createElement("div",null,"Slot"),!ee&&a.default.createElement("div",null,"Doctor")),a.default.createElement("div",{style:{overflow:"auto",flex:1}},M?a.default.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",padding:"40px",color:"#888"}},a.default.createElement("div",{style:{textAlign:"center"}},a.default.createElement("div",{style:{width:"40px",height:"40px",border:"3px solid #f3f3f3",borderTop:"3px solid #4C4DDC",borderRadius:"50%",animation:"spin 1s linear infinite",margin:"0 auto 10px"}}),"Getting token...")):J?a.default.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",padding:"40px",color:"#888"}},a.default.createElement("div",{style:{textAlign:"center"}},a.default.createElement("div",{style:{width:"40px",height:"40px",border:"3px solid #f3f3f3",borderTop:"3px solid #4C4DDC",borderRadius:"50%",animation:"spin 1s linear infinite",margin:"0 auto 10px"}}),"Loading appointments...")):Q?a.default.createElement("div",{style:{padding:"40px",textAlign:"center",color:"#FF0000"}},a.default.createElement("div",{style:{fontSize:"16px",marginBottom:"8px"}},"⚠️ Error"),a.default.createElement("div",{style:{fontSize:"13px"}},Q),a.default.createElement("button",{onClick:lt,style:{marginTop:"16px",padding:"8px 16px",background:"#4C4DDC",color:"white",border:"none",borderRadius:"6px",cursor:"pointer",fontFamily:ht}},"Retry")):0===Ye.length?a.default.createElement("div",{style:{padding:"40px",textAlign:"center",color:"#888"}},a.default.createElement("div",{style:{fontSize:"16px",marginBottom:"8px"}},"📋"),a.default.createElement("div",{style:{fontSize:"13px"}},pe?`No appointments found for "${pe}"`:"No appointments found"),pe&&a.default.createElement("button",{onClick:()=>ce(""),style:{marginTop:"12px",padding:"6px 12px",background:"#4C4DDC",color:"white",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"12px",fontFamily:ht}},"Clear Search")):Ye.map((e=>a.default.createElement("div",{key:nt(e),role:"button",tabIndex:0,onClick:()=>dt(e),onKeyDown:t=>"Enter"===t.key&&dt(e),className:"appointments-grid",style:{display:"grid",gridTemplateColumns:ee?"1.5fr 1fr 0.8fr":"2.5fr 1fr 1.5fr 0.8fr 1.2fr",gap:ee?"8px":"12px",padding:ee?"10px 12px":"12px 18px",background:nt(X)===nt(e)?"#E8EEF4":"#FFFFFF",borderTop:"1px solid #F1F1F1",alignItems:"center",cursor:"pointer",fontSize:ee?"11px":"13px"}},a.default.createElement("div",{style:{display:"flex",alignItems:"center",gap:ee?"8px":"10px"}},ot(e)?a.default.createElement("img",{src:e.image,alt:"",style:{width:ee?"32px":"36px",height:ee?"32px":"36px",borderRadius:"50%",objectFit:"cover"}}):a.default.createElement("div",{style:{width:ee?"32px":"36px",height:ee?"32px":"36px",borderRadius:"50%",background:it(e.patientName),display:"flex",alignItems:"center",justifyContent:"center",color:"#FFFFFF",fontWeight:600,fontSize:ee?"14px":"16px"}},at(e.patientName)),a.default.createElement("div",null,a.default.createElement("div",{style:{fontWeight:600,color:"#1a1a1a",fontSize:ee?"11px":"13px"}},e.patientName),a.default.createElement("div",{style:{fontSize:ee?"9px":"11px",color:"#888"}},e.email))),!ee&&a.default.createElement("div",{style:{color:"#555",fontSize:"12px"}},e.patientId),a.default.createElement("div",{style:{color:"#555",fontSize:ee?"10px":"12px"}},(()=>{const t=e.appointmentDate||"",n=t.match(/\s(\d{1,2}:\d{2}(?:\s*(?:AM|PM))?)$/i);return n?a.default.createElement(a.default.Fragment,null,a.default.createElement("div",null,t.slice(0,n.index).trim()),a.default.createElement("div",{style:{fontSize:ee?"9px":"11px",color:"#888"}},n[1].trim())):a.default.createElement("div",null,t)})()),!ee&&a.default.createElement("div",{style:{color:"#555",fontSize:"12px"}},e.appointmentTime||"-"),!ee&&a.default.createElement("div",{style:{color:"#555",fontSize:"12px"}},e.doctorName||e.doctor||"-"))))),!J&&!Q&&Ye.length>0&&a.default.createElement("div",{style:{padding:ee?"12px 14px":"14px 18px",borderTop:"1px solid #F1F1F1",display:"flex",justifyContent:"space-between",alignItems:"center",background:"#FFFFFF",flexWrap:ee?"wrap":"nowrap",gap:ee?"10px":"0"}},a.default.createElement("div",{style:{fontSize:ee?"11px":"12px",color:"#666"}},"Showing page ",Le," of ",Ve," (",qe," total)"),a.default.createElement("div",{style:{display:"flex",gap:"6px",alignItems:"center"}},a.default.createElement("button",{onClick:()=>$e((e=>Math.max(1,e-1))),disabled:1===Le,style:{padding:ee?"6px 10px":"6px 12px",border:"1px solid #E5E5E5",borderRadius:"4px",background:1===Le?"#F5F5F5":"#FFFFFF",color:1===Le?"#999":"#1a1a1a",fontSize:ee?"11px":"12px",fontFamily:ht,fontWeight:600,cursor:1===Le?"not-allowed":"pointer",opacity:1===Le?.5:1}},"Previous"),a.default.createElement("div",{style:{display:"flex",gap:"4px"}},[...Array(Math.min(5,Ve))].map(((e,t)=>{let n;return n=Ve<=5||Le<=3?t+1:Le>=Ve-2?Ve-4+t:Le-2+t,a.default.createElement("button",{key:n,onClick:()=>$e(n),style:{padding:ee?"6px 10px":"6px 12px",border:Le===n?"none":"1px solid #E5E5E5",borderRadius:"4px",background:Le===n?"#4C4DDC":"#FFFFFF",color:Le===n?"#FFFFFF":"#1a1a1a",fontSize:ee?"11px":"12px",fontFamily:ht,fontWeight:600,cursor:"pointer",minWidth:ee?"32px":"36px"}},n)}))),a.default.createElement("button",{onClick:()=>$e((e=>Math.min(Ve,e+1))),disabled:Le===Ve,style:{padding:ee?"6px 10px":"6px 12px",border:"1px solid #E5E5E5",borderRadius:"4px",background:Le===Ve?"#F5F5F5":"#FFFFFF",color:Le===Ve?"#999":"#1a1a1a",fontSize:ee?"11px":"12px",fontFamily:ht,fontWeight:600,cursor:Le===Ve?"not-allowed":"pointer",opacity:Le===Ve?.5:1}},"Next"))))),a.default.createElement("div",{style:{flex:ee?"none":"1 1 35%",width:ee?"100%":"auto",display:X||!ee?"flex":"none",flexDirection:"column",minHeight:ee?"auto":0}},a.default.createElement("div",{style:{border:"1px solid #E5E5E5",borderRadius:"8px",overflow:"hidden",background:"#FFFFFF",boxShadow:"0 1px 4px rgba(0,0,0,0.08)",display:"flex",flexDirection:"column",flex:ee?"none":1,minHeight:ee?"auto":0}},X?a.default.createElement(a.default.Fragment,null,a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:ee?"12px 14px":"16px 18px",background:"#E8EEF4",borderBottom:"1px solid #E5E5E5"}},a.default.createElement("div",null,a.default.createElement("div",{style:{color:"#002668",fontSize:ee?"14px":"16px",fontWeight:"700"}},X.patientName||"N/A"),a.default.createElement("div",{style:{color:"#002668",fontSize:ee?"11px":"13px"}},X.patientId||X.mrn||"N/A")),a.default.createElement("div",null,ot(X)?a.default.createElement("img",{style:{width:ee?"36px":"44px",height:ee?"36px":"44px",borderRadius:"50%",objectFit:"cover"},src:X.image,alt:X.patientName}):a.default.createElement("div",{style:{width:ee?"36px":"44px",height:ee?"36px":"44px",borderRadius:"50%",background:it(X.patientName),display:"flex",alignItems:"center",justifyContent:"center",color:"#FFFFFF",fontWeight:700,fontSize:ee?"16px":"20px"}},at(X.patientName)))),a.default.createElement("div",{style:{padding:ee?"12px 14px":"14px 18px",gap:ee?"10px":"12px",display:"flex",flexDirection:"column",background:"white",overflow:"auto",flex:1,position:"relative"}},a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ee?"10px":"11px",color:"#888",marginBottom:"3px"}},"Speciality"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ee?"12px":"13px"}},X?.specialisation||X?.speciality||"N/A")),a.default.createElement("div",{style:{textAlign:"right"}},a.default.createElement("div",{style:{fontSize:ee?"10px":"11px",color:"#888",marginBottom:"3px"}},"Appointment Type"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ee?"12px":"13px"}},X?.type||X?.appointmentType||"Online"))),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ee?"10px":"11px",color:"#888",marginBottom:"3px"}},"Appointment Date"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ee?"12px":"13px"}},X?.date||X?.appointmentDate||"N/A")),a.default.createElement("div",{style:{textAlign:"right"}},a.default.createElement("div",{style:{fontSize:ee?"10px":"11px",color:"#888",marginBottom:"3px"}},"Appointment Time"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ee?"12px":"13px"}},X?.time||X?.appointmentTime||"N/A"))),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ee?"10px":"11px",color:"#888",marginBottom:"3px"}},"Doctor"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ee?"12px":"13px"}},X?.doctor||X?.doctorName||"N/A"))),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ee?"10px":"11px",color:"#888",marginBottom:"3px"}},"Hospital"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ee?"12px":"13px"}},X?.hospital||X?.hospitalName||"N/A"))),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ee?"10px":"11px",color:"#888",marginBottom:"3px"}},"Reason for Appointment"),a.default.createElement("div",{style:{fontWeight:"600",fontSize:ee?"11px":"12px",lineHeight:"1.4"}},X?.reason||X?.reasonForAppointment||"No reason provided"))),"upcoming"===U&&a.default.createElement("div",{style:{display:"flex",flexDirection:ee?"column":"row",gap:"6px",marginTop:"10px"}},a.default.createElement("button",{type:"button",onClick:st,disabled:we,style:{flex:1,background:we?"#99e4e8":"#1CC3CE",color:"#FFFFFF",border:"1px solid #1CC3CE",borderRadius:"6px",padding:ee?"10px 8px":"8px 6px",fontFamily:ht,fontWeight:600,fontSize:ee?"11px":"12px",cursor:we?"not-allowed":"pointer"}},we?"Connecting...":"Join Call >")),"upcoming"===U&&ve&&a.default.createElement("div",{style:{fontSize:"11px",color:"#e53935",marginTop:"6px",textAlign:"center",width:"100%"}},"⚠️ ",ve))):a.default.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100%",padding:"40px",color:"#888",textAlign:"center"}},a.default.createElement("div",null,a.default.createElement("div",{style:{fontSize:"16px",marginBottom:"8px"}},"📋"),a.default.createElement("div",{style:{fontSize:"13px"}},"Select an appointment to view details"))))))),ue&&a.default.createElement("div",{style:{position:"fixed",left:ge?"0":ee?"10px":`${Ce.x}px`,top:ge?"0":ee?"70px":`${Ce.y}px`,right:ge?"0":ee?"10px":"auto",bottom:ge?"0":"auto",width:ge?"100vw":ee?"calc(100vw - 20px)":me?"350px":`${De.width}px`,height:ge?"100vh":me?"auto":ee?"300px":`${De.height}px`,background:"#FFFFFF",borderRadius:ge?"0":"8px",boxShadow:"0 8px 24px rgba(0, 0, 0, 0.3)",zIndex:1e4,overflow:"hidden",display:"flex",flexDirection:"column",transition:We||Re?"none":"all 0.3s ease"}},a.default.createElement("div",{onPointerDown:ee||ge?void 0:ft,onPointerMove:ee||ge?void 0:mt,onPointerUp:ee||ge?void 0:xt,onPointerCancel:ee||ge?void 0:xt,style:{background:"linear-gradient(135deg, #4C4DDC 0%, #3A3BBD 100%)",color:"#FFFFFF",padding:ee?"8px 10px":"10px 12px",display:"flex",justifyContent:"space-between",alignItems:"center",cursor:ee||ge?"default":"move",userSelect:"none"}},a.default.createElement("div",{style:{display:"flex",alignItems:"center",gap:ee?"6px":"8px",flex:1,minWidth:0}},a.default.createElement("div",{style:{width:ee?"6px":"8px",height:ee?"6px":"8px",borderRadius:"50%",background:"#FF4444",animation:"pulse 2s infinite",flexShrink:0}}),a.default.createElement("span",{style:{fontSize:ee?"11px":"13px",fontWeight:600,fontFamily:ht,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}},"Video Call - ",X?.patientName||"Patient")),a.default.createElement("div",{style:{display:"flex",gap:ee?"4px":"6px",alignItems:"center",flexShrink:0}},!ge&&a.default.createElement("button",{onClick:ct,style:{background:"rgba(255, 255, 255, 0.2)",border:"1px solid rgba(255, 255, 255, 0.3)",borderRadius:"6px",color:"#FFFFFF",cursor:"pointer",padding:ee?"5px 8px":"6px 10px",lineHeight:1,display:"flex",alignItems:"center",justifyContent:"center",minWidth:ee?"28px":"32px",height:ee?"28px":"32px",transition:"background 0.2s ease"},onMouseEnter:e=>e.target.style.background="rgba(255, 255, 255, 0.3)",onMouseLeave:e=>e.target.style.background="rgba(255, 255, 255, 0.2)",title:me?"Restore":"Minimize"},me?a.default.createElement("svg",{width:ee?"14":"16",height:ee?"14":"16",viewBox:"0 0 16 16",fill:"none"},a.default.createElement("rect",{x:"3",y:"3",width:"10",height:"10",stroke:"white",strokeWidth:"1.8",fill:"none"})):a.default.createElement("svg",{width:ee?"14":"16",height:ee?"14":"16",viewBox:"0 0 16 16",fill:"none"},a.default.createElement("line",{x1:"3",y1:"8",x2:"13",y2:"8",stroke:"white",strokeWidth:"1.8",strokeLinecap:"round"}))),a.default.createElement("button",{onClick:ut,style:{background:"rgba(255, 255, 255, 0.2)",border:"1px solid rgba(255, 255, 255, 0.3)",borderRadius:"6px",color:"#FFFFFF",cursor:"pointer",padding:ee?"5px 8px":"6px 10px",lineHeight:1,display:"flex",alignItems:"center",justifyContent:"center",minWidth:ee?"28px":"32px",height:ee?"28px":"32px",transition:"background 0.2s ease"},onMouseEnter:e=>e.target.style.background="rgba(255, 255, 255, 0.3)",onMouseLeave:e=>e.target.style.background="rgba(255, 255, 255, 0.2)",title:ge?"Exit Fullscreen":"Fullscreen"},ge?a.default.createElement("svg",{width:ee?"14":"16",height:ee?"14":"16",viewBox:"0 0 16 16",fill:"none"},a.default.createElement("path",{d:"M10 3H13V6M6 13H3V10M13 10V13H10M3 6V3H6",stroke:"white",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round"})):a.default.createElement("svg",{width:ee?"14":"16",height:ee?"14":"16",viewBox:"0 0 16 16",fill:"none"},a.default.createElement("path",{d:"M3 6V3H6M13 10V13H10M10 3H13V6M6 13H3V10",stroke:"white",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round"}))),a.default.createElement("button",{onClick:pt,style:{background:"rgba(255, 255, 255, 0.2)",border:"1px solid rgba(255, 255, 255, 0.3)",borderRadius:"6px",color:"#FFFFFF",cursor:"pointer",padding:ee?"5px 8px":"6px 10px",lineHeight:1,display:"flex",alignItems:"center",justifyContent:"center",minWidth:ee?"28px":"32px",height:ee?"28px":"32px",fontWeight:"bold",fontSize:ee?"18px":"22px",transition:"background 0.2s ease"},onMouseEnter:e=>e.target.style.background="rgba(255, 255, 255, 0.3)",onMouseLeave:e=>e.target.style.background="rgba(255, 255, 255, 0.2)",title:"Close"},"×"))),!me&&a.default.createElement("div",{style:{flex:1,background:"#000000",position:"relative"}},a.default.createElement("iframe",{src:(()=>{if(!ye)return"";const e=String(L||"").replace(/\/?$/,"/");return console.log("${base}token=${callToken}",`${e}token=${ye}`),`${e}token=${ye}`})(),style:{width:"100%",height:"100%",border:"none"},allow:"camera; microphone; display-capture; autoplay",allowFullScreen:!0,title:"Video Call"})),!ee&&!ge&&!me&&a.default.createElement(a.default.Fragment,null,a.default.createElement("div",{onPointerDown:e=>gt("top-left",e),onPointerMove:mt,onPointerUp:xt,onPointerCancel:xt,style:{position:"absolute",left:0,top:0,width:"16px",height:"16px",cursor:"nwse-resize",background:"transparent",zIndex:10001}}),a.default.createElement("div",{onPointerDown:e=>gt("top-right",e),onPointerMove:mt,onPointerUp:xt,onPointerCancel:xt,style:{position:"absolute",right:0,top:0,width:"16px",height:"16px",cursor:"nesw-resize",background:"transparent",zIndex:10001}}),a.default.createElement("div",{onPointerDown:e=>gt("bottom-left",e),onPointerMove:mt,onPointerUp:xt,onPointerCancel:xt,style:{position:"absolute",left:0,bottom:0,width:"16px",height:"16px",cursor:"nesw-resize",background:"transparent",zIndex:10001}}),a.default.createElement("div",{onPointerDown:e=>gt("bottom-right",e),onPointerMove:mt,onPointerUp:xt,onPointerCancel:xt,style:{position:"absolute",right:0,bottom:0,width:"16px",height:"16px",cursor:"nwse-resize",background:"transparent",zIndex:10001}})),a.default.createElement("style",null,"\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n "))),yt&&a.default.createElement("div",{style:{position:"fixed",inset:0,zIndex:1e5,display:"flex",alignItems:"center",justifyContent:"center",padding:"24px",background:"rgba(0,0,0,0.4)",boxSizing:"border-box"}},a.default.createElement("div",{style:{fontFamily:ht,maxWidth:"400px",width:"100%",padding:"32px 24px",background:"#FFFFFF",borderRadius:"12px",boxShadow:"0 8px 32px rgba(0,0,0,0.2)",textAlign:"center"}},a.default.createElement("div",{style:{fontSize:"48px",marginBottom:"16px"}},"🔒"),a.default.createElement("h2",{style:{fontSize:"20px",fontWeight:700,color:"#1a1a1a",margin:"0 0 8px 0"}},R?"Not authorised":"Sign in required"),a.default.createElement("p",{style:{fontSize:"14px",color:"#666",margin:0,lineHeight:1.5}},Et),a.default.createElement("p",{style:{fontSize:"13px",color:"#999",marginTop:"16px",marginBottom:0}},"Redirecting to login...")))),a.default.createElement(w,null,Ft)};let v=null;const k={showWidget:(e,t)=>{v||(v=document.createElement("div"),document.body.appendChild(v));const n=()=>a.default.createElement(a.default.Fragment,null,a.default.createElement(S,{config:e}));i.default.render(a.default.createElement(n,null),v)},closePopup:()=>{v&&(i.default.unmountComponentAtNode(v),v=null)}};window.BookingSDK=k,e.AppointmentPage=S,e.PIH_APPOINTMENT_WIDGET_CLASS=F,e.default=k,Object.defineProperty(e,"__esModule",{value:!0})}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react-dom")):"function"==typeof define&&define.amd?define(["exports","react","react-dom"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).MyPackage={},e.React,e.ReactDOM)}(this,(function(e,t,n){"use strict";function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=o(t),i=o(n);const l="/appointment/V1/consultant/all-appointments",r="/notification/V1/consultation/online/initiate",d="dMtEGhak",p="https://wbafedevittisalwe01-had2b3e0a7h6fyey.westeurope-01.azurewebsites.net/call/",s=async function(e,t,n,o){let a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{},i=(e||"").toUpperCase();"INPROGRESS"===i&&(i="IN_PROGRESS");const r=a.apiBaseUrl,p=a.hospitalId||d,s=a.doctorId,c=a.token||"",u={hospitalId:p,doctorId:s,fromDate:t,toDate:n,statuses:i};o&&"ALL"!==String(o).toUpperCase()&&(u.appointmentType=String(o).toUpperCase());const f=`${r}${l}`,m=await async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"";const o=new URL(e);return o.search=new URLSearchParams(t).toString(),fetch(o,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`${n}`}}).then((async e=>{const t=await e.json().catch((()=>({})));return e.ok?t:{err:t?.resultInfo?.message||"Something went wrong!",status:e.status}})).catch((e=>(console.error("Fetch error:",e),{err:e?.message||String(e)||"Network error"})))}(f,u,"PIH-Appointment-Widget",c);return m},c=async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};console.log("initiateConsultation -> config",t);const n=`${t.apiBaseUrl.replace(/\/$/,"")}${r}`,o=t.appToken||"";return async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=arguments.length>4?arguments[4]:void 0;const a=new URL(e);Object.keys(n).forEach((e=>{a.searchParams.append(e,n[e])}));const i={"Content-Type":"application/json"};o&&(i.Authorization=o);const l={method:"POST",headers:i,body:JSON.stringify(t)};return fetch(a.toString(),l).then((async e=>{const t=await e.json().catch((()=>({})));return e.ok?t:{err:t?.resultInfo?.message||"Something went wrong!",status:e.status}})).catch((e=>(console.error("Fetch error:",e),{err:e.message||"Network error"})))}(n,{patientId:String(e.patientId||""),primaryPatientId:String(e.primaryPatientId||e.patientId||""),hospitalId:t.hospitalId||d,doctorId:String(t.doctorId),patientName:e.patientName||e.name||"",doctorName:e.doctorName||t.doctorName,appointmentId:String(e.id||e.appointmentId||e._id||"")},"PIH-Appointment-Widget",{},o)};const u="pih_appointment_idToken",f="pih_appointment_email",m="pih_appointment_appToken",x="pih_appointment_doctorId",g="pih_appointment_userName",h="pih_appointment_apiBaseUrl",y=720,E="pih-appointment-widget",F="data-pih-widget";class b extends t.Component{state={hasError:!1};static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e,t){"undefined"!=typeof console&&console.error&&console.error("Appointment widget error:",e,t)}render(){return this.state.hasError?a.default.createElement("div",{className:E,[F]:"teleconsult-appointments",style:{fontFamily:'"Nunito", serif',background:"#F5F5F7",boxSizing:"border-box",minHeight:"100vh",display:"flex",alignItems:"center",justifyContent:"center",padding:"24px",textAlign:"center"}},a.default.createElement("div",{style:{maxWidth:"400px"}},a.default.createElement("div",{style:{fontSize:"48px",marginBottom:"16px"}},"⚠️"),a.default.createElement("h2",{style:{fontSize:"20px",fontWeight:700,color:"#1a1a1a",margin:"0 0 8px 0"}},"Something went wrong"),a.default.createElement("p",{style:{fontSize:"14px",color:"#666",margin:0,lineHeight:1.5}},"Please refresh the page or try again later."))):this.props.children}}const w=e=>{let{config:n={}}=e;const[o,i]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(h):null}catch{return null}})),l=n.apiBaseUrl||o||"https://afiyaapiqa.powermindinc.com",r=n.hospitalId||d,[w,S]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(u):null}catch{return null}})),[v,k]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(f):null}catch{return null}})),C=n.idToken||n.token||w,I=n.email||v;t.useEffect((()=>{try{if("undefined"==typeof localStorage)return;const e=n.idToken||n.token;if(e&&String(e).trim()){localStorage.getItem(u)!==e&&(z(null),M(null),A(null),localStorage.removeItem(m),localStorage.removeItem(x),localStorage.removeItem(g)),localStorage.setItem(u,e),S(e)}n.email&&String(n.email).trim()&&(localStorage.setItem(f,n.email),k(n.email)),n.apiBaseUrl&&String(n.apiBaseUrl).trim()&&(localStorage.setItem(h,n.apiBaseUrl.trim()),i(n.apiBaseUrl.trim()))}catch(e){}}),[n.idToken,n.token,n.email,n.apiBaseUrl]);const[D,z]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(m):null}catch{return null}})),[W,M]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(x):null}catch{return null}})),[T,A]=t.useState((()=>{try{return"undefined"!=typeof localStorage?localStorage.getItem(g):null}catch{return null}})),[R,N]=t.useState((()=>{try{if("undefined"==typeof localStorage)return!1;const e=localStorage.getItem(m),t=localStorage.getItem(u),n=localStorage.getItem(f);return!e&&!(!t||!n)}catch{return!1}})),[P,j]=t.useState(null),[B,L]=t.useState(!1),[H,U]=t.useState(0);t.useEffect((()=>{D&&R&&N(!1)}),[D,R]),t.useEffect((()=>{D||(C&&I?(L(!1),j((e=>"Sign in required. Redirecting to home..."===e?null:e))):(j("Sign in required. Redirecting to home..."),L(!0)))}),[D,C,I]),t.useEffect((()=>{if(!B)return;const e=n.homeUrl||"https://wbaemrdevittisalwe01-fnapdpfme7bvduhh.westeurope-01.azurewebsites.net/";if(!e||"undefined"==typeof window)return;const t=setTimeout((()=>{window.location.href=e}),2500);return()=>clearTimeout(t)}),[B,n.homeUrl]),t.useEffect((()=>{if(!R)return;const e=setTimeout((()=>{j("Request timed out. Please try again."),N(!1)}),3e4);return()=>clearTimeout(e)}),[R]);const O=n.joinCallUrl||p;D&&String(O||"").replace(/\/?$/,"/");const $=function(e){if(!e||"string"!=typeof e)return{};try{const t=e.split(".");if(3!==t.length)return{};const n=t[1].replace(/-/g,"+").replace(/_/g,"/"),o=n.padEnd(n.length+(4-n.length%4)%4,"=");return JSON.parse(atob(o))}catch{return{}}}(C),_=T||$.name||$.sub||"User",Y=()=>(new Date).toISOString().split("T")[0],[V,q]=t.useState("upcoming"),[X,G]=t.useState([]),[J,K]=t.useState(null),[Q,Z]=t.useState(!1),[ee,te]=t.useState(null),[ne,oe]=t.useState(window.innerWidth<768),[ae,ie]=t.useState("today"),[le,re]=t.useState("today"),[de,pe]=t.useState(!1),[se,ce]=t.useState(!1),[ue,fe]=t.useState("all"),[me,xe]=t.useState("asc"),[ge,he]=t.useState(""),[ye,Ee]=t.useState(!1),[Fe,be]=t.useState(!1),[we,Se]=t.useState(!1),[ve,ke]=t.useState(null),[Ce,Ie]=t.useState(null),[De,ze]=t.useState(!1),[We,Me]=t.useState(null),[Te,Ae]=t.useState((()=>({x:Math.max(20,"undefined"!=typeof window?window.innerWidth-y-20:300),y:80}))),[Re,Ne]=t.useState({width:y,height:560}),[Pe,je]=t.useState(!1),[Be,Le]=t.useState({x:0,y:0}),[He,Ue]=t.useState(!1),[Oe,$e]=t.useState(null),[_e,Ye]=t.useState({x:0,y:0,width:0,height:0});t.useState(!1);const[Ve,qe]=t.useState(1),Xe=X.filter((e=>{if(!ge.trim())return!0;const t=ge.toLowerCase(),n=(e.patientName||"").toLowerCase(),o=String(e.patientId||"").toLowerCase();return n.includes(t)||o.includes(t)})),Ge=20*(Ve-1),Je=Ge+20,Ke=Xe.slice(Ge,Je),Qe=Math.ceil(Xe.length/20),Ze=Xe.length,[et,tt]=t.useState(Y()),[nt,ot]=t.useState(Y()),[at,it]=t.useState(),[lt,rt]=t.useState(),dt=e=>e?.id||e?._id||e?.appointmentId||e?.patientId||JSON.stringify(e),pt=e=>e?.image?e.image:null,st=e=>e?e.charAt(0).toUpperCase():"?",ct=e=>{if(!e)return"#4C4DDC";const t=["#4C4DDC","#1CC3CE","#FF6B6B","#4ECDC4","#45B7D1","#FFA07A","#98D8C8","#F7DC6F"];return t[e.charCodeAt(0)%t.length]},ut=()=>{const e="asc"===me?"desc":"asc";xe(e);const t=[...X].sort(((t,n)=>{const o=new Date(t.appointmentDate||t.date||0),a=new Date(n.appointmentDate||n.date||0);return"asc"===e?o-a:a-o}));G(t),qe(1),t.length>0&&K(t[0])},ft=t.useCallback((async e=>{if(!D)return;console.log(W,"fetchAppointments -> doctorIdFromLogin");const t=W,n=void 0!==e?e:ue;Z(!0),te(null);try{const e={apiBaseUrl:l,hospitalId:r,doctorId:t,token:D},o=await s(V,et,nt,n,e);if(401===o.status||403===o.status){try{"undefined"!=typeof localStorage&&(localStorage.removeItem(m),localStorage.removeItem(x),localStorage.removeItem(g))}catch(e){}return z(null),M(null),A(null),U((e=>e+1)),void te("Session expired. Re-authenticating...")}if(o.err)return void te(String(o.err||"Failed to fetch appointments"));const a=o.data||o.appointments||o||[];G(Array.isArray(a)?a:[]),Array.isArray(a)&&a.length>0?K(a[0]):K(null)}catch(e){console.error("Error fetching appointments:",e),te(e.message||"Failed to fetch appointments")}finally{Z(!1)}}),[V,et,nt,ue,l,r,W,D]),mt=e=>{K(e)},xt=async()=>{if(J&&D){ze(!0),Me(null);try{const e={apiBaseUrl:l,hospitalId:r,doctorId:W,doctorName:T||_,appToken:D};console.log(J,"selectedAppointment"),console.log(e,"callConfig");const t=await c(J,e);if(401===t.status||403===t.status)return Me("Session expired. Please try again."),void ze(!1);if(t.err||!t.data?.token)return Me(String(t.err||"Failed to initiate call")),void ze(!1);const o=n.joinCallUrl||p,a=t.data.token?String(o||"").replace(/\/?$/,"/")+t.data.token:"";console.log("joinCallUrl",a),ke(t.data.token),Ie(a||""),Ee(!0),be(!1),Se(!1),Ne({width:y,height:560}),Ae({x:Math.max(20,window.innerWidth-y-20),y:80})}catch(e){Me(e.message||"Failed to initiate call")}finally{Me(null),ze(!1)}}},gt=()=>{Ee(!1),be(!1),Se(!1),ke(null),Ie(null),Me(null),ft()},ht=()=>{we&&Se(!1),be(!Fe)},yt=()=>{Fe&&be(!1),Se(!we)},Et=e=>{if(0!==e.button)return;if(e.target.closest("button"))return;e.currentTarget.setPointerCapture&&e.currentTarget.setPointerCapture(e.pointerId),je(!0);const t=e.currentTarget.getBoundingClientRect();Le({x:e.clientX-t.left,y:e.clientY-t.top})},Ft=t.useCallback((e=>{if(!we)if(Pe){const t=e.clientX-Be.x,n=e.clientY-Be.y,o=window.innerWidth-Re.width,a=window.innerHeight-Re.height;Ae({x:Math.max(0,Math.min(t,o)),y:Math.max(0,Math.min(n,a))})}else if(He){const t=e.clientX-_e.x,n=e.clientY-_e.y;let o=_e.width,a=_e.height,i=_e.posX,l=_e.posY;const r=300,d=250,p=window.innerWidth-40,s=window.innerHeight-100;if("bottom-right"===Oe)o=Math.min(Math.max(_e.width+t,r),p),a=Math.min(Math.max(_e.height+n,d),s),i+o>window.innerWidth&&(o=window.innerWidth-i),l+a>window.innerHeight&&(a=window.innerHeight-l);else if("bottom-left"===Oe){o=Math.min(Math.max(_e.width-t,r),p),i=Math.max(0,_e.posX+t),0===i&&(o=_e.posX+_e.width),a=Math.min(Math.max(_e.height+n,d),s),l+a>window.innerHeight&&(a=window.innerHeight-l)}else if("top-right"===Oe){o=Math.min(Math.max(_e.width+t,r),p),i+o>window.innerWidth&&(o=window.innerWidth-i);a=Math.min(Math.max(_e.height-n,d),s),l=Math.max(0,_e.posY+n),0===l&&(a=_e.posY+_e.height)}else if("top-left"===Oe){o=Math.min(Math.max(_e.width-t,r),p),i=Math.max(0,_e.posX+t),0===i&&(o=_e.posX+_e.width);a=Math.min(Math.max(_e.height-n,d),s),l=Math.max(0,_e.posY+n),0===l&&(a=_e.posY+_e.height)}Ne({width:o,height:a}),Ae({x:i,y:l})}}),[Pe,He,Be,Oe,_e,Te,Re,we]),bt=()=>{je(!1),Ue(!1),$e(null)},wt=(e,t)=>{t.preventDefault(),t.stopPropagation(),t.currentTarget.setPointerCapture&&t.currentTarget.setPointerCapture(t.pointerId),Ue(!0),$e(e),Ye({x:t.clientX,y:t.clientY,width:Re.width,height:Re.height,posX:Te.x,posY:Te.y})};t.useEffect((()=>{if(!ye||we)return;const e=()=>{if(!(window.innerWidth<768)){const e=Fe?350:Re.width,t=Fe?60:Re.height,n=window.innerWidth-40,o=window.innerHeight-100,a=Math.min(e,n),i=Math.min(t,o);a===Re.width&&i===Re.height||Ne({width:a,height:i});const l=window.innerWidth-a-20,r=window.innerHeight-i-20;Ae((e=>({x:Math.min(e.x,l),y:Math.min(e.y,r)})))}};return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)}),[ye,Fe,we,Re]),t.useEffect((()=>{if(!(C&&I&&(!D||H>0)))return;let e=!1;return N(!0),j(null),(async(e,t,n,o)=>{const a=`${e.replace(/\/$/,"")}/um/user/V1/sso/login?hospitalId=${encodeURIComponent(t)}`,i={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({idToken:n,email:o})};return console.log("[getTokenFromSso] request",{url:a,body:{idToken:n?n.slice(0,50)+"...":null,email:o}}),fetch(a,i).then((e=>(console.log("[getTokenFromSso] response status",e.status,e.statusText),e.ok?e.json().then((e=>(console.log("[getTokenFromSso] success",{hasData:!!e,dataKeys:e?Object.keys(e):[],hasAccessToken:!!e?.data?.access_token}),e))):e.json().then((t=>{const n=t?.resultInfo?.message||"SSO login failed";return console.log("[getTokenFromSso] error body",t),{err:n,status:e.status}})).catch((()=>({err:"Something went wrong!",status:e.status})))))).catch((e=>(console.error("[getTokenFromSso] catch",e),{err:e.message||"Network error"})))})(l,r,C,I).then((t=>{if(e)return;const n=function(e){return!e||e.err?null:e.data?.access_token??e.data?.token??e.token??e.accessToken??null}(t);if(400===t.status)return j(t.err||"Invalid request. Redirecting to home..."),N(!1),void L(!0);if(t.err||!n){j(String(t.err||"Failed to get token")),z(null),M(null),A(null);try{"undefined"!=typeof localStorage&&(localStorage.removeItem(m),localStorage.removeItem(x),localStorage.removeItem(g))}catch(e){}}else{const e=function(e){if(!e?.data)return null;const t=e.data.doctor_id??e.data.doctorId??null;return console.log(t,"extractDoctorIdFromLoginResponse -> id"),null!=t?String(t):null}(t);console.log(e,"extractDoctorIdFromLoginResponse -> doctorId");const o=function(e){if(!e?.data)return null;const t=e.data.name??e.data.doctor_name??e.data.userName??null;return null!=t?String(t):null}(t);z(n),M(e),A(o),j(null),L(!1);try{"undefined"!=typeof localStorage&&(localStorage.setItem(m,n),e&&localStorage.setItem(x,e),o&&localStorage.setItem(g,o))}catch(e){}}})).catch((()=>{})).finally((()=>{e||N(!1)})),()=>{e=!0}}),[l,r,C,I,H]),t.useEffect((()=>{qe(1)}),[V,ae,et,nt,ge,ue]),t.useEffect((()=>{!R&&D&&ft()}),[ft,D,R]),t.useEffect((()=>{const e=document.createElement("link");e.href="https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap",e.rel="stylesheet",document.head.appendChild(e);const t=document.createElement("style");t.innerHTML="\n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n @media (max-width: 768px) {\n .appointments-grid {\n grid-template-columns: 1.5fr 1fr 0.8fr !important;\n }\n .appointments-header-grid {\n grid-template-columns: 1.5fr 1fr 0.8fr !important;\n }\n .hide-on-mobile {\n display: none !important;\n }\n }\n @media (max-width: 480px) {\n .appointments-header-grid {\n font-size: 10px !important;\n }\n .appointments-grid {\n font-size: 11px !important;\n }\n }\n ",document.head.appendChild(t);const n=()=>{oe(window.innerWidth<768)};return window.addEventListener("resize",n),()=>{document.head.removeChild(e),document.head.removeChild(t),window.removeEventListener("resize",n)}}),[]),t.useEffect((()=>{const e=e=>{!de||e.target.closest("button")||e.target.closest('input[type="date"]')||pe(!1),se&&!e.target.closest("[data-appointment-type-picker]")&&ce(!1)};return document.addEventListener("click",e),()=>{document.removeEventListener("click",e)}}),[de,se]);let St='"Nunito", serif';const vt=P||!D&&(!C||!I),kt=P||"Sign in required. Redirecting to home...";let Ct;return Ct=R&&C&&I?a.default.createElement("div",{className:E,[F]:"teleconsult-appointments",style:{fontFamily:St,background:"#F5F5F7",boxSizing:"border-box",height:"100%",minHeight:"100vh",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"24px"}},a.default.createElement("style",null,"@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }"),a.default.createElement("div",{style:{width:"40px",height:"40px",border:"3px solid #f3f3f3",borderTop:"3px solid #4C4DDC",borderRadius:"50%",animation:"spin 1s linear infinite",marginBottom:"16px"}}),a.default.createElement("p",{style:{fontSize:"14px",color:"#666",margin:0}},"Checking authorisation...")):a.default.createElement(a.default.Fragment,null,a.default.createElement("div",{className:E,[F]:"teleconsult-appointments",style:{fontFamily:St,background:"#F5F5F7",boxSizing:"border-box",height:"100%",minHeight:"100vh",width:"100%",display:"flex",flexDirection:"column",overflow:"hidden"}},a.default.createElement("div",{style:{background:"#FFFFFF",padding:ne?"10px 12px":"12px 24px",display:"flex",justifyContent:"space-between",alignItems:"center",borderBottom:"1px solid #E5E5E5",flexWrap:"nowrap",gap:ne?"8px":"0"}},a.default.createElement("div",{style:{position:"relative",width:ne?"calc(100% - 90px)":"480px",maxWidth:ne?"none":"480px"}},a.default.createElement("input",{type:"text",placeholder:"Search by patient name or ID",value:ge,onChange:e=>he(e.target.value),style:{width:"100%",padding:ne?"8px 32px 8px 10px":"8px 36px 8px 14px",border:"1px solid #E5E5E5",borderRadius:"6px",fontSize:ne?"12px":"13px",fontFamily:St,background:"#FFFFFF",outline:"none",boxSizing:"border-box"}}),ge&&a.default.createElement("button",{onClick:()=>he(""),style:{position:"absolute",right:"8px",top:"50%",transform:"translateY(-50%)",background:"none",border:"none",cursor:"pointer",padding:"4px",display:"flex",alignItems:"center",justifyContent:"center",color:"#999",fontSize:"16px"},title:"Clear search"},"✕")),!1),a.default.createElement("div",{style:{padding:ne?"12px":"16px 24px",flex:1,minHeight:0,overflow:"hidden",display:"flex",flexDirection:"column"}},a.default.createElement("div",{style:{marginBottom:ne?"10px":"14px"}},a.default.createElement("h1",{style:{fontSize:ne?"18px":"22px",fontWeight:700,color:"#1a1a1a",margin:"0 0 2px 0"}},"Tele Consultation"),a.default.createElement("p",{style:{fontSize:ne?"11px":"12px",color:"#999",margin:0}},"Displaying All Tele Consultation Appointments")),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:ne?"flex-start":"center",marginBottom:ne?"10px":"14px",flexDirection:ne?"column":"row",gap:ne?"12px":"0"}},a.default.createElement("div",{style:{display:"flex",gap:"6px",flexWrap:"wrap",width:ne?"100%":"auto"}},a.default.createElement("button",{onClick:()=>q("upcoming"),style:{background:"upcoming"===V?"#4C4DDC":"#FFFFFF",padding:ne?"8px 10px":"9px 16px",border:"upcoming"===V?"none":"1px solid #E5E5E5",borderRadius:"6px",fontSize:ne?"10px":"13px",color:"upcoming"===V?"white":"#555555",fontWeight:600,fontFamily:St,cursor:"pointer",flex:ne?"1 1 auto":"none",minWidth:ne?"0":"auto",transition:"all 0.3s ease",whiteSpace:"nowrap"}},"Upcoming Appointments"),a.default.createElement("button",{onClick:()=>q("completed"),style:{background:"completed"===V?"#4C4DDC":"#FFFFFF",padding:ne?"8px 10px":"9px 16px",border:"completed"===V?"none":"1px solid #E5E5E5",borderRadius:"6px",fontSize:ne?"10px":"13px",color:"completed"===V?"white":"#555555",fontWeight:600,fontFamily:St,cursor:"pointer",flex:ne?"1 1 auto":"none",minWidth:ne?"0":"auto",transition:"all 0.3s ease",whiteSpace:"nowrap"}},"Completed Appointments"),a.default.createElement("button",{onClick:()=>q("cancelled"),style:{background:"cancelled"===V?"#4C4DDC":"#FFFFFF",padding:ne?"8px 10px":"9px 16px",border:"cancelled"===V?"none":"1px solid #E5E5E5",borderRadius:"6px",fontSize:ne?"10px":"13px",color:"cancelled"===V?"white":"#555555",fontWeight:600,fontFamily:St,cursor:"pointer",flex:ne?"1 1 auto":"none",minWidth:ne?"0":"auto",transition:"all 0.3s ease",whiteSpace:"nowrap"}},"Cancelled Appointments")),a.default.createElement("div",{style:{display:"flex",gap:"8px",alignItems:"center",width:"auto",position:"relative",justifyContent:ne?"flex-start":"flex-end",flexWrap:"wrap"}},a.default.createElement("div",{style:{position:"relative"},"data-appointment-type-picker":!0},a.default.createElement("button",{onClick:()=>ce(!se),style:{padding:"8px 12px",fontFamily:St,fontWeight:600,border:"1px solid #E5E5E5",borderRadius:"6px",fontSize:ne?"11px":"13px",color:"#1a1a1a",background:"#FFFFFF",display:"flex",alignItems:"center",gap:ne?"4px":"6px",cursor:"pointer",flex:"none",minWidth:ne?"100px":"auto",justifyContent:"center"}},a.default.createElement("svg",{width:ne?"14":"16",height:ne?"14":"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},a.default.createElement("path",{d:"M4.8 2A2.8 2.8 0 0 0 2 4.8v14.4A2.8 2.8 0 0 0 4.8 22h14.4a2.8 2.8 0 0 0 2.8-2.8V4.8A2.8 2.8 0 0 0 19.2 2H4.8z"}),a.default.createElement("path",{d:"M8 12h8M8 16h5"})),a.default.createElement("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"#4C4DDC"}},"all"===ue?"All Appointment":"ONLINE"===ue?"Online":"Physical"),a.default.createElement("svg",{width:ne?"8":"10",height:ne?"8":"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},a.default.createElement("polyline",{points:"6 9 12 15 18 9"}))),se&&a.default.createElement("div",{style:{position:"absolute",top:"100%",right:ne?"auto":0,left:ne?0:"auto",marginTop:"4px",background:"#FFFFFF",border:"1px solid #E5E5E5",borderRadius:"8px",boxShadow:"0 4px 16px rgba(0,0,0,0.15)",padding:"8px",zIndex:1e3,minWidth:ne?"240px":"200px",width:ne?"calc(100vw - 24px)":"auto",maxWidth:ne?"calc(100vw - 24px)":"240px"}},[{value:"all",label:"All Appointment"},{value:"ONLINE",label:"Online"},{value:"PHYSICAL",label:"Physical"}].map((e=>{let{value:t,label:n}=e;return a.default.createElement("button",{key:t,onClick:()=>{fe(t),ce(!1),ft(t)},style:{width:"100%",padding:"10px 12px",background:ue===t?"#E8EEF4":"#FFFFFF",border:"none",borderRadius:"4px",fontSize:"13px",fontFamily:St,cursor:"pointer",textAlign:"left",fontWeight:ue===t?600:400,color:ue===t?"#4C4DDC":"#1a1a1a",marginBottom:"4px",display:"flex",justifyContent:"space-between",alignItems:"center",transition:"all 0.2s ease"},onMouseEnter:e=>{ue!==t&&(e.target.style.background="#F5F5F5")},onMouseLeave:e=>{ue!==t&&(e.target.style.background="#FFFFFF")}},a.default.createElement("span",null,n),ue===t&&a.default.createElement("span",{style:{color:"#4C4DDC",fontSize:"16px"}},"✓"))})))),a.default.createElement("button",{onClick:()=>{de||(it(et),rt(nt),re(ae)),pe(!de)},style:{padding:"8px 12px",fontFamily:St,fontWeight:600,border:"1px solid #E5E5E5",borderRadius:"6px",fontSize:ne?"11px":"13px",color:"#1a1a1a",background:"#FFFFFF",display:"flex",alignItems:"center",gap:ne?"4px":"6px",cursor:"pointer",flex:"none",minWidth:ne?"100px":"auto",justifyContent:"center"}},a.default.createElement("svg",{width:ne?"12":"14",height:ne?"12":"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},a.default.createElement("rect",{x:"3",y:"4",width:"18",height:"18",rx:"2",ry:"2"}),a.default.createElement("line",{x1:"16",y1:"2",x2:"16",y2:"6"}),a.default.createElement("line",{x1:"8",y1:"2",x2:"8",y2:"6"}),a.default.createElement("line",{x1:"3",y1:"10",x2:"21",y2:"10"})),a.default.createElement("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}},(()=>{switch(ae){case"today":default:return"Today";case"tomorrow":return"Tomorrow";case"currentWeek":return"Current Week";case"thisMonth":return"This Month";case"currentYear":return"Current Year";case"custom":return ne?"Custom":`${et} to ${nt}`}})()),a.default.createElement("svg",{width:ne?"8":"10",height:ne?"8":"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},a.default.createElement("polyline",{points:"6 9 12 15 18 9"}))),de&&a.default.createElement("div",{style:{position:"absolute",top:"100%",right:ne?"auto":0,left:ne?0:"auto",marginTop:"4px",background:"#FFFFFF",border:"1px solid #E5E5E5",borderRadius:"8px",boxShadow:"0 4px 16px rgba(0,0,0,0.15)",padding:"8px",zIndex:1e3,minWidth:ne?"280px":"240px",width:ne?"calc(100vw - 24px)":"auto",maxWidth:ne?"calc(100vw - 24px)":"280px"}},a.default.createElement("div",{style:{marginBottom:"custom"===le?"12px":"0"}},["thisMonth","today","tomorrow","currentWeek","currentYear","custom"].map((e=>a.default.createElement("button",{key:e,onClick:()=>{if(re(e),"custom"!==e){const t=(e=>{const t=new Date;let n,o;switch(e){case"today":default:n=o=Y();break;case"tomorrow":const e=new Date(t);e.setDate(e.getDate()+1),n=o=e.toISOString().split("T")[0];break;case"currentWeek":const a=new Date(t),i=new Date(t),l=t.getDay(),r=0===l?-6:1-l;a.setDate(t.getDate()+r),i.setDate(a.getDate()+6),n=a.toISOString().split("T")[0],o=i.toISOString().split("T")[0];break;case"thisMonth":const d=new Date(t.getFullYear(),t.getMonth(),1),p=new Date(t.getFullYear(),t.getMonth()+1,0);n=d.toISOString().split("T")[0],o=p.toISOString().split("T")[0];break;case"currentYear":n=`${t.getFullYear()}-01-01`,o=`${t.getFullYear()}-12-31`}return{from:n,to:o}})(e);ie(e),tt(t.from),ot(t.to),it(t.from),rt(t.to),pe(!1)}else it(""),rt("")},style:{width:"100%",padding:"10px 12px",background:le===e?"#E8EEF4":"#FFFFFF",border:"none",borderRadius:"4px",fontSize:"13px",fontFamily:St,cursor:"pointer",textAlign:"left",fontWeight:le===e?600:400,color:le===e?"#4C4DDC":"#1a1a1a",marginBottom:"4px",display:"flex",justifyContent:"space-between",alignItems:"center",transition:"all 0.2s ease"},onMouseEnter:t=>{le!==e&&(t.target.style.background="#F5F5F5")},onMouseLeave:t=>{le!==e&&(t.target.style.background="#FFFFFF")}},a.default.createElement("span",null,{thisMonth:"This Month",today:"Today",tomorrow:"Tomorrow",currentWeek:"Current Week",currentYear:"Current Year",custom:"Custom"}[e]),le===e&&a.default.createElement("span",{style:{color:"#4C4DDC",fontSize:"16px"}},"✓"))))),"custom"===le&&a.default.createElement("div",{style:{paddingTop:"8px",borderTop:"1px solid #E5E5E5"}},a.default.createElement("div",{style:{marginBottom:"8px"}},a.default.createElement("input",{type:"date",value:at,onChange:e=>it(e.target.value),placeholder:"Start Date",style:{width:"100%",padding:"10px 8px",border:"1px solid #E5E5E5",borderRadius:"4px",fontSize:"13px",fontFamily:St,boxSizing:"border-box",cursor:"pointer"}})),a.default.createElement("div",{style:{marginBottom:"12px"}},a.default.createElement("input",{type:"date",value:lt,onChange:e=>rt(e.target.value),placeholder:"End Date",style:{width:"100%",padding:"10px 8px",border:"1px solid #E5E5E5",borderRadius:"4px",fontSize:"13px",fontFamily:St,boxSizing:"border-box",cursor:"pointer"}})),a.default.createElement("div",{style:{display:"flex",gap:"8px"}},a.default.createElement("button",{onClick:()=>{re(ae),it(et),rt(nt),pe(!1)},style:{flex:1,padding:"10px 12px",background:"#FFFFFF",color:"#4C4DDC",border:"1px solid #4C4DDC",borderRadius:"4px",fontSize:"13px",fontFamily:St,fontWeight:600,cursor:"pointer"}},"Cancel"),a.default.createElement("button",{onClick:()=>{at&&lt&&(ie("custom"),tt(at),ot(lt),pe(!1))},style:{flex:1,padding:"10px 12px",background:"#4C4DDC",color:"#FFFFFF",border:"none",borderRadius:"4px",fontSize:"13px",fontFamily:St,fontWeight:600,cursor:"pointer"}},"Submit")))))),a.default.createElement("div",{style:{display:"flex",flexDirection:ne?"column":"row",gap:ne?"12px":"14px",flex:1,minHeight:0,overflow:ne?"auto":"hidden"}},a.default.createElement("div",{style:{flex:ne?"none":"1 1 65%",width:ne?"100%":"auto",display:"flex",flexDirection:"column",minHeight:ne?"400px":0}},a.default.createElement("div",{style:{background:"#FFFFFF",borderRadius:"8px",boxShadow:"0 1px 4px rgba(0,0,0,0.08)",overflow:"hidden",display:"flex",flexDirection:"column",flex:ne?"none":1,minHeight:ne?"auto":0}},a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:ne?"12px 14px":"14px 18px",borderBottom:"1px solid #F1F1F1"}},a.default.createElement("div",{style:{display:"flex",alignItems:"center",gap:ne?"6px":"8px"}},a.default.createElement("span",{style:{fontSize:ne?"14px":"15px",fontWeight:700,color:"#1a1a1a"}},"Appointments"),a.default.createElement("span",{style:{background:"#4C4DDC",color:"#fff",fontSize:ne?"10px":"11px",fontWeight:600,padding:ne?"2px 7px":"3px 8px",borderRadius:"12px"}},Ze))),a.default.createElement("div",{className:"appointments-header-grid",style:{display:"grid",gridTemplateColumns:ne?"1.5fr 1fr 0.8fr":"2.5fr 1fr 1.5fr 0.8fr 1.2fr",gap:ne?"8px":"12px",padding:ne?"8px 12px":"10px 18px",background:"#F5F5F5",fontSize:ne?"10px":"12px",fontWeight:600,color:"#666"}},a.default.createElement("div",null,"Patients name"),!ne&&a.default.createElement("div",null,"Patient ID"),a.default.createElement("div",{onClick:ut,style:{display:"flex",alignItems:"center",gap:"3px",cursor:"pointer",userSelect:"none"}},"Date",a.default.createElement("span",{style:{opacity:.7,fontSize:"10px"}},"asc"===me?"▲":"▼")),!ne&&a.default.createElement("div",null,"Slot"),!ne&&a.default.createElement("div",null,"Doctor")),a.default.createElement("div",{style:{overflow:"auto",flex:1}},R?a.default.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",padding:"40px",color:"#888"}},a.default.createElement("div",{style:{textAlign:"center"}},a.default.createElement("div",{style:{width:"40px",height:"40px",border:"3px solid #f3f3f3",borderTop:"3px solid #4C4DDC",borderRadius:"50%",animation:"spin 1s linear infinite",margin:"0 auto 10px"}}),"Getting token...")):Q?a.default.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",padding:"40px",color:"#888"}},a.default.createElement("div",{style:{textAlign:"center"}},a.default.createElement("div",{style:{width:"40px",height:"40px",border:"3px solid #f3f3f3",borderTop:"3px solid #4C4DDC",borderRadius:"50%",animation:"spin 1s linear infinite",margin:"0 auto 10px"}}),"Loading appointments...")):ee?a.default.createElement("div",{style:{padding:"40px",textAlign:"center",color:"#FF0000"}},a.default.createElement("div",{style:{fontSize:"16px",marginBottom:"8px"}},"⚠️ Error"),a.default.createElement("div",{style:{fontSize:"13px"}},ee),a.default.createElement("button",{onClick:ft,style:{marginTop:"16px",padding:"8px 16px",background:"#4C4DDC",color:"white",border:"none",borderRadius:"6px",cursor:"pointer",fontFamily:St}},"Retry")):0===Ke.length?a.default.createElement("div",{style:{padding:"40px",textAlign:"center",color:"#888"}},a.default.createElement("div",{style:{fontSize:"16px",marginBottom:"8px"}},"📋"),a.default.createElement("div",{style:{fontSize:"13px"}},ge?`No appointments found for "${ge}"`:"No appointments found"),ge&&a.default.createElement("button",{onClick:()=>he(""),style:{marginTop:"12px",padding:"6px 12px",background:"#4C4DDC",color:"white",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"12px",fontFamily:St}},"Clear Search")):Ke.map((e=>a.default.createElement("div",{key:dt(e),role:"button",tabIndex:0,onClick:()=>mt(e),onKeyDown:t=>"Enter"===t.key&&mt(e),className:"appointments-grid",style:{display:"grid",gridTemplateColumns:ne?"1.5fr 1fr 0.8fr":"2.5fr 1fr 1.5fr 0.8fr 1.2fr",gap:ne?"8px":"12px",padding:ne?"10px 12px":"12px 18px",background:dt(J)===dt(e)?"#E8EEF4":"#FFFFFF",borderTop:"1px solid #F1F1F1",alignItems:"center",cursor:"pointer",fontSize:ne?"11px":"13px"}},a.default.createElement("div",{style:{display:"flex",alignItems:"center",gap:ne?"8px":"10px"}},pt(e)?a.default.createElement("img",{src:e.image,alt:"",style:{width:ne?"32px":"36px",height:ne?"32px":"36px",borderRadius:"50%",objectFit:"cover"}}):a.default.createElement("div",{style:{width:ne?"32px":"36px",height:ne?"32px":"36px",borderRadius:"50%",background:ct(e.patientName),display:"flex",alignItems:"center",justifyContent:"center",color:"#FFFFFF",fontWeight:600,fontSize:ne?"14px":"16px"}},st(e.patientName)),a.default.createElement("div",null,a.default.createElement("div",{style:{fontWeight:600,color:"#1a1a1a",fontSize:ne?"11px":"13px"}},e.patientName),a.default.createElement("div",{style:{fontSize:ne?"9px":"11px",color:"#888"}},e.email))),!ne&&a.default.createElement("div",{style:{color:"#555",fontSize:"12px"}},e.patientId),a.default.createElement("div",{style:{color:"#555",fontSize:ne?"10px":"12px"}},(()=>{const t=e.appointmentDate||"",n=t.match(/\s(\d{1,2}:\d{2}(?:\s*(?:AM|PM))?)$/i);return n?a.default.createElement(a.default.Fragment,null,a.default.createElement("div",null,t.slice(0,n.index).trim()),a.default.createElement("div",{style:{fontSize:ne?"9px":"11px",color:"#888"}},n[1].trim())):a.default.createElement("div",null,t)})()),!ne&&a.default.createElement("div",{style:{color:"#555",fontSize:"12px"}},e.appointmentTime||"-"),!ne&&a.default.createElement("div",{style:{color:"#555",fontSize:"12px"}},e.doctorName||e.doctor||"-"))))),!Q&&!ee&&Ke.length>0&&a.default.createElement("div",{style:{padding:ne?"12px 14px":"14px 18px",borderTop:"1px solid #F1F1F1",display:"flex",justifyContent:"space-between",alignItems:"center",background:"#FFFFFF",flexWrap:ne?"wrap":"nowrap",gap:ne?"10px":"0"}},a.default.createElement("div",{style:{fontSize:ne?"11px":"12px",color:"#666"}},"Showing page ",Ve," of ",Qe," (",Ze," total)"),a.default.createElement("div",{style:{display:"flex",gap:"6px",alignItems:"center"}},a.default.createElement("button",{onClick:()=>qe((e=>Math.max(1,e-1))),disabled:1===Ve,style:{padding:ne?"6px 10px":"6px 12px",border:"1px solid #E5E5E5",borderRadius:"4px",background:1===Ve?"#F5F5F5":"#FFFFFF",color:1===Ve?"#999":"#1a1a1a",fontSize:ne?"11px":"12px",fontFamily:St,fontWeight:600,cursor:1===Ve?"not-allowed":"pointer",opacity:1===Ve?.5:1}},"Previous"),a.default.createElement("div",{style:{display:"flex",gap:"4px"}},[...Array(Math.min(5,Qe))].map(((e,t)=>{let n;return n=Qe<=5||Ve<=3?t+1:Ve>=Qe-2?Qe-4+t:Ve-2+t,a.default.createElement("button",{key:n,onClick:()=>qe(n),style:{padding:ne?"6px 10px":"6px 12px",border:Ve===n?"none":"1px solid #E5E5E5",borderRadius:"4px",background:Ve===n?"#4C4DDC":"#FFFFFF",color:Ve===n?"#FFFFFF":"#1a1a1a",fontSize:ne?"11px":"12px",fontFamily:St,fontWeight:600,cursor:"pointer",minWidth:ne?"32px":"36px"}},n)}))),a.default.createElement("button",{onClick:()=>qe((e=>Math.min(Qe,e+1))),disabled:Ve===Qe,style:{padding:ne?"6px 10px":"6px 12px",border:"1px solid #E5E5E5",borderRadius:"4px",background:Ve===Qe?"#F5F5F5":"#FFFFFF",color:Ve===Qe?"#999":"#1a1a1a",fontSize:ne?"11px":"12px",fontFamily:St,fontWeight:600,cursor:Ve===Qe?"not-allowed":"pointer",opacity:Ve===Qe?.5:1}},"Next"))))),a.default.createElement("div",{style:{flex:ne?"none":"1 1 35%",width:ne?"100%":"auto",display:J||!ne?"flex":"none",flexDirection:"column",minHeight:ne?"auto":0}},a.default.createElement("div",{style:{border:"1px solid #E5E5E5",borderRadius:"8px",overflow:"hidden",background:"#FFFFFF",boxShadow:"0 1px 4px rgba(0,0,0,0.08)",display:"flex",flexDirection:"column",flex:ne?"none":1,minHeight:ne?"auto":0}},J?a.default.createElement(a.default.Fragment,null,a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:ne?"12px 14px":"16px 18px",background:"#E8EEF4",borderBottom:"1px solid #E5E5E5"}},a.default.createElement("div",null,a.default.createElement("div",{style:{color:"#002668",fontSize:ne?"14px":"16px",fontWeight:"700"}},J.patientName||"N/A"),a.default.createElement("div",{style:{color:"#002668",fontSize:ne?"11px":"13px"}},J.patientId||J.mrn||"N/A")),a.default.createElement("div",null,pt(J)?a.default.createElement("img",{style:{width:ne?"36px":"44px",height:ne?"36px":"44px",borderRadius:"50%",objectFit:"cover"},src:J.image,alt:J.patientName}):a.default.createElement("div",{style:{width:ne?"36px":"44px",height:ne?"36px":"44px",borderRadius:"50%",background:ct(J.patientName),display:"flex",alignItems:"center",justifyContent:"center",color:"#FFFFFF",fontWeight:700,fontSize:ne?"16px":"20px"}},st(J.patientName)))),a.default.createElement("div",{style:{padding:ne?"12px 14px":"14px 18px",gap:ne?"10px":"12px",display:"flex",flexDirection:"column",background:"white",overflow:"auto",flex:1,position:"relative"}},a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ne?"10px":"11px",color:"#888",marginBottom:"3px"}},"Speciality"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ne?"12px":"13px"}},J?.specialisation||J?.speciality||"N/A")),a.default.createElement("div",{style:{textAlign:"right"}},a.default.createElement("div",{style:{fontSize:ne?"10px":"11px",color:"#888",marginBottom:"3px"}},"Appointment Type"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ne?"12px":"13px"}},J?.type||J?.appointmentType||"Online"))),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ne?"10px":"11px",color:"#888",marginBottom:"3px"}},"Appointment Date"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ne?"12px":"13px"}},J?.date||J?.appointmentDate||"N/A")),a.default.createElement("div",{style:{textAlign:"right"}},a.default.createElement("div",{style:{fontSize:ne?"10px":"11px",color:"#888",marginBottom:"3px"}},"Appointment Time"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ne?"12px":"13px"}},J?.time||J?.appointmentTime||"N/A"))),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ne?"10px":"11px",color:"#888",marginBottom:"3px"}},"Doctor"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ne?"12px":"13px"}},J?.doctor||J?.doctorName||"N/A"))),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ne?"10px":"11px",color:"#888",marginBottom:"3px"}},"Hospital"),a.default.createElement("div",{style:{fontWeight:"700",fontSize:ne?"12px":"13px"}},J?.hospital||J?.hospitalName||"N/A"))),a.default.createElement("div",{style:{display:"flex",justifyContent:"space-between"}},a.default.createElement("div",{style:{textAlign:"left"}},a.default.createElement("div",{style:{fontSize:ne?"10px":"11px",color:"#888",marginBottom:"3px"}},"Reason for Appointment"),a.default.createElement("div",{style:{fontWeight:"600",fontSize:ne?"11px":"12px",lineHeight:"1.4"}},J?.reason||J?.reasonForAppointment||"No reason provided"))),"upcoming"===V&&a.default.createElement("div",{style:{display:"flex",flexDirection:ne?"column":"row",gap:"6px",marginTop:"10px"}},a.default.createElement("button",{type:"button",onClick:xt,disabled:De,style:{flex:1,background:De?"#99e4e8":"#1CC3CE",color:"#FFFFFF",border:"1px solid #1CC3CE",borderRadius:"6px",padding:ne?"10px 8px":"8px 6px",fontFamily:St,fontWeight:600,fontSize:ne?"11px":"12px",cursor:De?"not-allowed":"pointer"}},De?"Connecting...":"Join Call >")),"upcoming"===V&&We&&a.default.createElement("div",{style:{fontSize:"11px",color:"#e53935",marginTop:"6px",textAlign:"center",width:"100%"}},"⚠️ ",We))):a.default.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100%",padding:"40px",color:"#888",textAlign:"center"}},a.default.createElement("div",null,a.default.createElement("div",{style:{fontSize:"16px",marginBottom:"8px"}},"📋"),a.default.createElement("div",{style:{fontSize:"13px"}},"Select an appointment to view details"))))))),ye&&a.default.createElement("div",{style:{position:"fixed",left:we?"0":ne?"10px":`${Te.x}px`,top:we?"0":ne?"70px":`${Te.y}px`,right:we?"0":ne?"10px":"auto",bottom:we?"0":"auto",width:we?"100vw":ne?"calc(100vw - 20px)":Fe?"350px":`${Re.width}px`,height:we?"100vh":Fe?"auto":ne?"300px":`${Re.height}px`,background:"#FFFFFF",borderRadius:we?"0":"8px",boxShadow:"0 8px 24px rgba(0, 0, 0, 0.3)",zIndex:1e4,overflow:"hidden",display:"flex",flexDirection:"column",transition:Pe||He?"none":"all 0.3s ease"}},a.default.createElement("div",{onPointerDown:ne||we?void 0:Et,onPointerMove:ne||we?void 0:Ft,onPointerUp:ne||we?void 0:bt,onPointerCancel:ne||we?void 0:bt,style:{background:"linear-gradient(135deg, #4C4DDC 0%, #3A3BBD 100%)",color:"#FFFFFF",padding:ne?"8px 10px":"10px 12px",display:"flex",justifyContent:"space-between",alignItems:"center",cursor:ne||we?"default":"move",userSelect:"none"}},a.default.createElement("div",{style:{display:"flex",alignItems:"center",gap:ne?"6px":"8px",flex:1,minWidth:0}},a.default.createElement("div",{style:{width:ne?"6px":"8px",height:ne?"6px":"8px",borderRadius:"50%",background:"#FF4444",animation:"pulse 2s infinite",flexShrink:0}}),a.default.createElement("span",{style:{fontSize:ne?"11px":"13px",fontWeight:600,fontFamily:St,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}},"Video Call - ",J?.patientName||"Patient")),a.default.createElement("div",{style:{display:"flex",gap:ne?"4px":"6px",alignItems:"center",flexShrink:0}},!we&&a.default.createElement("button",{onClick:ht,style:{background:"rgba(255, 255, 255, 0.2)",border:"1px solid rgba(255, 255, 255, 0.3)",borderRadius:"6px",color:"#FFFFFF",cursor:"pointer",padding:ne?"5px 8px":"6px 10px",lineHeight:1,display:"flex",alignItems:"center",justifyContent:"center",minWidth:ne?"28px":"32px",height:ne?"28px":"32px",transition:"background 0.2s ease"},onMouseEnter:e=>e.target.style.background="rgba(255, 255, 255, 0.3)",onMouseLeave:e=>e.target.style.background="rgba(255, 255, 255, 0.2)",title:Fe?"Restore":"Minimize"},Fe?a.default.createElement("svg",{width:ne?"14":"16",height:ne?"14":"16",viewBox:"0 0 16 16",fill:"none"},a.default.createElement("rect",{x:"3",y:"3",width:"10",height:"10",stroke:"white",strokeWidth:"1.8",fill:"none"})):a.default.createElement("svg",{width:ne?"14":"16",height:ne?"14":"16",viewBox:"0 0 16 16",fill:"none"},a.default.createElement("line",{x1:"3",y1:"8",x2:"13",y2:"8",stroke:"white",strokeWidth:"1.8",strokeLinecap:"round"}))),a.default.createElement("button",{onClick:yt,style:{background:"rgba(255, 255, 255, 0.2)",border:"1px solid rgba(255, 255, 255, 0.3)",borderRadius:"6px",color:"#FFFFFF",cursor:"pointer",padding:ne?"5px 8px":"6px 10px",lineHeight:1,display:"flex",alignItems:"center",justifyContent:"center",minWidth:ne?"28px":"32px",height:ne?"28px":"32px",transition:"background 0.2s ease"},onMouseEnter:e=>e.target.style.background="rgba(255, 255, 255, 0.3)",onMouseLeave:e=>e.target.style.background="rgba(255, 255, 255, 0.2)",title:we?"Exit Fullscreen":"Fullscreen"},we?a.default.createElement("svg",{width:ne?"14":"16",height:ne?"14":"16",viewBox:"0 0 16 16",fill:"none"},a.default.createElement("path",{d:"M10 3H13V6M6 13H3V10M13 10V13H10M3 6V3H6",stroke:"white",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round"})):a.default.createElement("svg",{width:ne?"14":"16",height:ne?"14":"16",viewBox:"0 0 16 16",fill:"none"},a.default.createElement("path",{d:"M3 6V3H6M13 10V13H10M10 3H13V6M6 13H3V10",stroke:"white",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round"}))),a.default.createElement("button",{onClick:gt,style:{background:"rgba(255, 255, 255, 0.2)",border:"1px solid rgba(255, 255, 255, 0.3)",borderRadius:"6px",color:"#FFFFFF",cursor:"pointer",padding:ne?"5px 8px":"6px 10px",lineHeight:1,display:"flex",alignItems:"center",justifyContent:"center",minWidth:ne?"28px":"32px",height:ne?"28px":"32px",fontWeight:"bold",fontSize:ne?"18px":"22px",transition:"background 0.2s ease"},onMouseEnter:e=>e.target.style.background="rgba(255, 255, 255, 0.3)",onMouseLeave:e=>e.target.style.background="rgba(255, 255, 255, 0.2)",title:"Close"},"×"))),!Fe&&a.default.createElement("div",{style:{flex:1,background:"#000000",position:"relative"}},a.default.createElement("iframe",{src:(()=>{if(!ve)return"";const e=String(O||"").replace(/\/?$/,"/");return console.log("${base}token=${callToken}",`${e}token=${ve}`),`${e}token=${ve}`})(),style:{width:"100%",height:"100%",border:"none"},allow:"camera; microphone; display-capture; autoplay",allowFullScreen:!0,title:"Video Call"})),!ne&&!we&&!Fe&&a.default.createElement(a.default.Fragment,null,a.default.createElement("div",{onPointerDown:e=>wt("top-left",e),onPointerMove:Ft,onPointerUp:bt,onPointerCancel:bt,style:{position:"absolute",left:0,top:0,width:"16px",height:"16px",cursor:"nwse-resize",background:"transparent",zIndex:10001}}),a.default.createElement("div",{onPointerDown:e=>wt("top-right",e),onPointerMove:Ft,onPointerUp:bt,onPointerCancel:bt,style:{position:"absolute",right:0,top:0,width:"16px",height:"16px",cursor:"nesw-resize",background:"transparent",zIndex:10001}}),a.default.createElement("div",{onPointerDown:e=>wt("bottom-left",e),onPointerMove:Ft,onPointerUp:bt,onPointerCancel:bt,style:{position:"absolute",left:0,bottom:0,width:"16px",height:"16px",cursor:"nesw-resize",background:"transparent",zIndex:10001}}),a.default.createElement("div",{onPointerDown:e=>wt("bottom-right",e),onPointerMove:Ft,onPointerUp:bt,onPointerCancel:bt,style:{position:"absolute",right:0,bottom:0,width:"16px",height:"16px",cursor:"nwse-resize",background:"transparent",zIndex:10001}})),a.default.createElement("style",null,"\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n "))),vt&&a.default.createElement("div",{style:{position:"fixed",inset:0,zIndex:1e5,display:"flex",alignItems:"center",justifyContent:"center",padding:"24px",background:"rgba(0,0,0,0.4)",boxSizing:"border-box"}},a.default.createElement("div",{style:{fontFamily:St,maxWidth:"400px",width:"100%",padding:"32px 24px",background:"#FFFFFF",borderRadius:"12px",boxShadow:"0 8px 32px rgba(0,0,0,0.2)",textAlign:"center"}},a.default.createElement("div",{style:{fontSize:"48px",marginBottom:"16px"}},"🔒"),a.default.createElement("h2",{style:{fontSize:"20px",fontWeight:700,color:"#1a1a1a",margin:"0 0 8px 0"}},P?"Not authorised":"Sign in required"),a.default.createElement("p",{style:{fontSize:"14px",color:"#666",margin:0,lineHeight:1.5}},kt),a.default.createElement("p",{style:{fontSize:"13px",color:"#999",marginTop:"16px",marginBottom:0}},"Redirecting to login...")))),a.default.createElement(b,null,Ct)};let S=null;const v={showWidget:(e,t)=>{S||(S=document.createElement("div"),document.body.appendChild(S));const n=()=>a.default.createElement(a.default.Fragment,null,a.default.createElement(w,{config:e}));i.default.render(a.default.createElement(n,null),S)},closePopup:()=>{S&&(i.default.unmountComponentAtNode(S),S=null)}};window.BookingSDK=v,e.AppointmentPage=w,e.PIH_APPOINTMENT_WIDGET_CLASS=E,e.default=v,Object.defineProperty(e,"__esModule",{value:!0})}));
@@ -14,16 +14,16 @@ var _apiConfig = require("../constants/apiConfig");
14
14
  * @param {object} config - Optional configuration { apiBaseUrl, hospitalId, doctorId }
15
15
  * @returns {Promise} Appointments data
16
16
  */
17
- const getAppointmentsByStatus = async function (status, fromDate, toDate) {
18
- let config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
17
+ const getAppointmentsByStatus = async function (status, fromDate, toDate, type) {
18
+ let config = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
19
19
  // Map status to API format
20
20
  let apiStatus = (status || "").toUpperCase();
21
21
  if (apiStatus === "INPROGRESS") {
22
22
  apiStatus = "IN_PROGRESS";
23
23
  }
24
- const baseURL = config.apiBaseUrl || _apiConfig.API_BASE_URL;
24
+ const baseURL = config.apiBaseUrl;
25
25
  const hospitalId = config.hospitalId || _apiConfig.DEFAULT_PARAMS.hospitalId;
26
- const doctorId = config.doctorId || _apiConfig.DEFAULT_PARAMS.doctorId;
26
+ const doctorId = config.doctorId;
27
27
  const token = config.token || '';
28
28
  const params = {
29
29
  hospitalId,
@@ -32,6 +32,9 @@ const getAppointmentsByStatus = async function (status, fromDate, toDate) {
32
32
  toDate,
33
33
  statuses: apiStatus
34
34
  };
35
+ if (type && String(type).toUpperCase() !== "ALL") {
36
+ params.appointmentType = String(type).toUpperCase();
37
+ }
35
38
  const url = `${baseURL}${_apiConfig.API_PATHS.APPOINTMENTS}`;
36
39
 
37
40
  // Return raw response (including status) so caller can detect 401 and re-login
@@ -49,7 +52,7 @@ exports.getAppointmentsByStatus = getAppointmentsByStatus;
49
52
  const getAppointmentDetails = async function (appointmentId) {
50
53
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
51
54
  try {
52
- const baseURL = config.apiBaseUrl || _apiConfig.API_BASE_URL;
55
+ const baseURL = config.apiBaseUrl;
53
56
  const url = `${baseURL}${_apiConfig.API_PATHS.APPOINTMENT_DETAILS}/${appointmentId}`;
54
57
  const response = await (0, _httpService.getApi)(url, {}, "PIH-Appointment-Widget");
55
58
  if (response.err) {
@@ -71,14 +74,15 @@ const getAppointmentDetails = async function (appointmentId) {
71
74
  exports.getAppointmentDetails = getAppointmentDetails;
72
75
  const initiateConsultation = async function (appointment) {
73
76
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
74
- const baseURL = (config.apiBaseUrl || _apiConfig.API_BASE_URL).replace(/\/$/, "");
77
+ console.log("initiateConsultation -> config", config);
78
+ const baseURL = config.apiBaseUrl.replace(/\/$/, "");
75
79
  const url = `${baseURL}${_apiConfig.API_PATHS.INITIATE_CALL}`;
76
80
  const appToken = config.appToken || "";
77
81
  const body = {
78
82
  patientId: String(appointment.patientId || ""),
79
83
  primaryPatientId: String(appointment.primaryPatientId || appointment.patientId || ""),
80
84
  hospitalId: config.hospitalId || _apiConfig.DEFAULT_PARAMS.hospitalId,
81
- doctorId: String(config.doctor_id || _apiConfig.DEFAULT_PARAMS.doctorId),
85
+ doctorId: String(config.doctorId),
82
86
  patientName: appointment.patientName || appointment.name || "",
83
87
  doctorName: appointment.doctorName || config.doctorName,
84
88
  appointmentId: String(appointment.id || appointment.appointmentId || appointment._id || "")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pih-appointment-widget",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "main": "dist/App.js",
5
5
  "module": "dist/App.js",
6
6
  "exports": {
@@ -25,6 +25,7 @@ const STORAGE_KEY_EMAIL = "pih_appointment_email";
25
25
  const STORAGE_KEY_APP_TOKEN = "pih_appointment_appToken";
26
26
  const STORAGE_KEY_DOCTOR_ID = "pih_appointment_doctorId";
27
27
  const STORAGE_KEY_USER_NAME = "pih_appointment_userName";
28
+ const STORAGE_KEY_API_BASE_URL = "pih_appointment_apiBaseUrl";
28
29
 
29
30
  const DEFAULT_PIP_WIDTH = 720;
30
31
  const DEFAULT_PIP_HEIGHT = 560;
@@ -96,8 +97,15 @@ class AppointmentErrorBoundary extends Component {
96
97
  }
97
98
 
98
99
  // SDK Component - accepts configuration from parent app
99
- const AppointmentPage = ({ config = {}}) => {
100
- const apiBaseUrl = config.apiBaseUrl || API_BASE_URL;
100
+ const AppointmentPage = ({ config = {} }) => {
101
+ const [storedApiBaseUrl, setStoredApiBaseUrl] = useState(() => {
102
+ try {
103
+ return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_API_BASE_URL) : null;
104
+ } catch {
105
+ return null;
106
+ }
107
+ });
108
+ const apiBaseUrl = config.apiBaseUrl || storedApiBaseUrl || API_BASE_URL;
101
109
  const hospitalId = config.hospitalId || DEFAULT_PARAMS.hospitalId;
102
110
 
103
111
  // idToken/email: config first, then localStorage. When Flutter (or parent) passes a new token, we use it and re-login.
@@ -141,8 +149,12 @@ const AppointmentPage = ({ config = {}}) => {
141
149
  localStorage.setItem(STORAGE_KEY_EMAIL, config.email);
142
150
  setStoredEmail(config.email);
143
151
  }
152
+ if (config.apiBaseUrl && String(config.apiBaseUrl).trim()) {
153
+ localStorage.setItem(STORAGE_KEY_API_BASE_URL, config.apiBaseUrl.trim());
154
+ setStoredApiBaseUrl(config.apiBaseUrl.trim());
155
+ }
144
156
  } catch (e) {}
145
- }, [config.idToken, config.token, config.email]);
157
+ }, [config.idToken, config.token, config.email, config.apiBaseUrl]);
146
158
 
147
159
  const [appToken, setAppToken] = useState(() => {
148
160
  try {
@@ -293,6 +305,8 @@ const AppointmentPage = ({ config = {}}) => {
293
305
  const [selectedDate, setSelectedDate] = useState("today"); // today, tomorrow, week, month, year, custom
294
306
  const [dateOption, setDateOption] = useState("today"); // Currently selected option in dropdown
295
307
  const [showDatePicker, setShowDatePicker] = useState(false);
308
+ const [showAppointmentTypePicker, setShowAppointmentTypePicker] = useState(false);
309
+ const [appointmentTypeFilter, setAppointmentTypeFilter] = useState("all"); // 'all' | 'ONLINE' | 'PHYSICAL'
296
310
  const [sortOrder, setSortOrder] = useState("asc"); // asc or desc for date sorting
297
311
  const [searchQuery, setSearchQuery] = useState(""); // Search query for filtering
298
312
 
@@ -399,10 +413,11 @@ const AppointmentPage = ({ config = {}}) => {
399
413
  }
400
414
  };
401
415
 
402
- const fetchAppointments = useCallback(async () => {
416
+ const fetchAppointments = useCallback(async (overrideType) => {
403
417
  if (!appToken) return;
404
418
  console.log(doctorIdFromLogin, 'fetchAppointments -> doctorIdFromLogin')
405
419
  const doctorId = doctorIdFromLogin;
420
+ const typeToUse = overrideType !== undefined ? overrideType : appointmentTypeFilter;
406
421
  setLoading(true);
407
422
  setError(null);
408
423
  try {
@@ -412,7 +427,7 @@ const AppointmentPage = ({ config = {}}) => {
412
427
  doctorId,
413
428
  token: appToken,
414
429
  };
415
- const response = await getAppointmentsByStatus(activeTab, fromDate, toDate, serviceConfig);
430
+ const response = await getAppointmentsByStatus(activeTab, fromDate, toDate, typeToUse, serviceConfig);
416
431
  if (response.status === 401 || response.status === 403) {
417
432
  // Token expired — clear stored token and trigger re-login (SSO effect will fire)
418
433
  try {
@@ -446,7 +461,7 @@ const AppointmentPage = ({ config = {}}) => {
446
461
  } finally {
447
462
  setLoading(false);
448
463
  }
449
- }, [activeTab, fromDate, toDate, apiBaseUrl, hospitalId, doctorIdFromLogin, appToken]);
464
+ }, [activeTab, fromDate, toDate, appointmentTypeFilter, apiBaseUrl, hospitalId, doctorIdFromLogin, appToken]);
450
465
 
451
466
  // Handle appointment selection - no API call, just show data from list
452
467
  const handleAppointmentSelect = (appointment) => {
@@ -462,6 +477,7 @@ const AppointmentPage = ({ config = {}}) => {
462
477
  localStorage.removeItem(STORAGE_KEY_APP_TOKEN);
463
478
  localStorage.removeItem(STORAGE_KEY_DOCTOR_ID);
464
479
  localStorage.removeItem(STORAGE_KEY_USER_NAME);
480
+ localStorage.removeItem(STORAGE_KEY_API_BASE_URL);
465
481
  }
466
482
  } catch (e) {}
467
483
  setShowProfileDropdown(false);
@@ -748,7 +764,7 @@ const AppointmentPage = ({ config = {}}) => {
748
764
  // Reset page to 1 when filters change
749
765
  useEffect(() => {
750
766
  setCurrentPage(1);
751
- }, [activeTab, selectedDate, fromDate, toDate, searchQuery]);
767
+ }, [activeTab, selectedDate, fromDate, toDate, searchQuery, appointmentTypeFilter]);
752
768
 
753
769
  // Fetch appointments when we have appToken (tab/date change triggers refetch via fetchAppointments deps)
754
770
  useEffect(() => {
@@ -808,19 +824,22 @@ const AppointmentPage = ({ config = {}}) => {
808
824
  };
809
825
  }, []);
810
826
 
811
- // Close date picker when clicking outside
827
+ // Close date picker and appointment type picker when clicking outside
812
828
  useEffect(() => {
813
829
  const handleClickOutside = (event) => {
814
830
  if (showDatePicker && !event.target.closest('button') && !event.target.closest('input[type="date"]')) {
815
831
  setShowDatePicker(false);
816
832
  }
833
+ if (showAppointmentTypePicker && !event.target.closest('[data-appointment-type-picker]')) {
834
+ setShowAppointmentTypePicker(false);
835
+ }
817
836
  };
818
837
 
819
838
  document.addEventListener("click", handleClickOutside);
820
839
  return () => {
821
840
  document.removeEventListener("click", handleClickOutside);
822
841
  };
823
- }, [showDatePicker]);
842
+ }, [showDatePicker, showAppointmentTypePicker]);
824
843
 
825
844
  let fontFamily = '"Nunito", serif';
826
845
 
@@ -1163,8 +1182,104 @@ const AppointmentPage = ({ config = {}}) => {
1163
1182
  </button>
1164
1183
  </div>
1165
1184
 
1166
- {/* Date Filter */}
1167
- <div style={{ display: "flex", gap: "8px", alignItems: "center", width: isMobile ? "auto" : "auto", position: "relative", justifyContent: isMobile ? "flex-start" : "flex-end" }}>
1185
+ {/* Date Filter + Type of Appointment Filter */}
1186
+ <div style={{ display: "flex", gap: "8px", alignItems: "center", width: isMobile ? "auto" : "auto", position: "relative", justifyContent: isMobile ? "flex-start" : "flex-end", flexWrap: "wrap" }}>
1187
+ {/* Type of Appointment Filter */}
1188
+ <div style={{ position: "relative" }} data-appointment-type-picker>
1189
+ <button
1190
+ onClick={() => setShowAppointmentTypePicker(!showAppointmentTypePicker)}
1191
+ style={{
1192
+ padding: isMobile ? "8px 12px" : "8px 12px",
1193
+ fontFamily,
1194
+ fontWeight: 600,
1195
+ border: "1px solid #E5E5E5",
1196
+ borderRadius: "6px",
1197
+ fontSize: isMobile ? "11px" : "13px",
1198
+ color: "#1a1a1a",
1199
+ background: "#FFFFFF",
1200
+ display: "flex",
1201
+ alignItems: "center",
1202
+ gap: isMobile ? "4px" : "6px",
1203
+ cursor: "pointer",
1204
+ flex: "none",
1205
+ minWidth: isMobile ? "100px" : "auto",
1206
+ justifyContent: "center",
1207
+ }}
1208
+ >
1209
+ <svg width={isMobile ? "14" : "16"} height={isMobile ? "14" : "16"} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
1210
+ <path d="M4.8 2A2.8 2.8 0 0 0 2 4.8v14.4A2.8 2.8 0 0 0 4.8 22h14.4a2.8 2.8 0 0 0 2.8-2.8V4.8A2.8 2.8 0 0 0 19.2 2H4.8z" />
1211
+ <path d="M8 12h8M8 16h5" />
1212
+ </svg>
1213
+ <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: "#4C4DDC" }}>
1214
+ {appointmentTypeFilter === "all" ? "All Appointment" : appointmentTypeFilter === "ONLINE" ? "Online" : "Physical"}
1215
+ </span>
1216
+ <svg width={isMobile ? "8" : "10"} height={isMobile ? "8" : "10"} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
1217
+ <polyline points="6 9 12 15 18 9" />
1218
+ </svg>
1219
+ </button>
1220
+ {showAppointmentTypePicker && (
1221
+ <div
1222
+ style={{
1223
+ position: "absolute",
1224
+ top: "100%",
1225
+ right: isMobile ? "auto" : 0,
1226
+ left: isMobile ? 0 : "auto",
1227
+ marginTop: "4px",
1228
+ background: "#FFFFFF",
1229
+ border: "1px solid #E5E5E5",
1230
+ borderRadius: "8px",
1231
+ boxShadow: "0 4px 16px rgba(0,0,0,0.15)",
1232
+ padding: "8px",
1233
+ zIndex: 1000,
1234
+ minWidth: isMobile ? "240px" : "200px",
1235
+ width: isMobile ? "calc(100vw - 24px)" : "auto",
1236
+ maxWidth: isMobile ? "calc(100vw - 24px)" : "240px",
1237
+ }}
1238
+ >
1239
+ {[
1240
+ { value: "all", label: "All Appointment" },
1241
+ { value: "ONLINE", label: "Online" },
1242
+ { value: "PHYSICAL", label: "Physical" },
1243
+ ].map(({ value, label }) => (
1244
+ <button
1245
+ key={value}
1246
+ onClick={() => {
1247
+ setAppointmentTypeFilter(value);
1248
+ setShowAppointmentTypePicker(false);
1249
+ fetchAppointments(value);
1250
+ }}
1251
+ style={{
1252
+ width: "100%",
1253
+ padding: "10px 12px",
1254
+ background: appointmentTypeFilter === value ? "#E8EEF4" : "#FFFFFF",
1255
+ border: "none",
1256
+ borderRadius: "4px",
1257
+ fontSize: "13px",
1258
+ fontFamily,
1259
+ cursor: "pointer",
1260
+ textAlign: "left",
1261
+ fontWeight: appointmentTypeFilter === value ? 600 : 400,
1262
+ color: appointmentTypeFilter === value ? "#4C4DDC" : "#1a1a1a",
1263
+ marginBottom: "4px",
1264
+ display: "flex",
1265
+ justifyContent: "space-between",
1266
+ alignItems: "center",
1267
+ transition: "all 0.2s ease",
1268
+ }}
1269
+ onMouseEnter={(e) => {
1270
+ if (appointmentTypeFilter !== value) e.target.style.background = "#F5F5F5";
1271
+ }}
1272
+ onMouseLeave={(e) => {
1273
+ if (appointmentTypeFilter !== value) e.target.style.background = "#FFFFFF";
1274
+ }}
1275
+ >
1276
+ <span>{label}</span>
1277
+ {appointmentTypeFilter === value && <span style={{ color: "#4C4DDC", fontSize: "16px" }}>✓</span>}
1278
+ </button>
1279
+ ))}
1280
+ </div>
1281
+ )}
1282
+ </div>
1168
1283
  {/* Date Filter */}
1169
1284
  <button
1170
1285
  onClick={() => {
@@ -16,8 +16,7 @@ export const API_PATHS = {
16
16
 
17
17
  // Default request parameters (will be fetched from auth API later)
18
18
  export const DEFAULT_PARAMS = {
19
- hospitalId: "dMtEGhak",
20
- doctorId: 6694
19
+ hospitalId: "dMtEGhak"
21
20
  };
22
21
 
23
22
  // Request timeout (milliseconds)
@@ -13,19 +13,23 @@ import {
13
13
  * @param {object} config - Optional configuration { apiBaseUrl, hospitalId, doctorId }
14
14
  * @returns {Promise} Appointments data
15
15
  */
16
- export const getAppointmentsByStatus = async (status, fromDate, toDate, config = {}) => {
16
+ export const getAppointmentsByStatus = async (status, fromDate, toDate, type, config = {}) => {
17
17
  // Map status to API format
18
18
  let apiStatus = (status || "").toUpperCase();
19
+
19
20
  if (apiStatus === "INPROGRESS") {
20
21
  apiStatus = "IN_PROGRESS";
21
22
  }
22
23
 
23
- const baseURL = config.apiBaseUrl || API_BASE_URL;
24
+ const baseURL = config.apiBaseUrl;
24
25
  const hospitalId = config.hospitalId || DEFAULT_PARAMS.hospitalId;
25
- const doctorId = config.doctorId || DEFAULT_PARAMS.doctorId;
26
+ const doctorId = config.doctorId;
26
27
  const token = config.token || '';
27
28
 
28
29
  const params = { hospitalId, doctorId, fromDate, toDate, statuses: apiStatus };
30
+ if (type && String(type).toUpperCase() !== "ALL") {
31
+ params.appointmentType = String(type).toUpperCase();
32
+ }
29
33
  const url = `${baseURL}${API_PATHS.APPOINTMENTS}`;
30
34
 
31
35
  // Return raw response (including status) so caller can detect 401 and re-login
@@ -41,7 +45,7 @@ export const getAppointmentsByStatus = async (status, fromDate, toDate, config =
41
45
  */
42
46
  export const getAppointmentDetails = async (appointmentId, config = {}) => {
43
47
  try {
44
- const baseURL = config.apiBaseUrl || API_BASE_URL;
48
+ const baseURL = config.apiBaseUrl;
45
49
  const url = `${baseURL}${API_PATHS.APPOINTMENT_DETAILS}/${appointmentId}`;
46
50
 
47
51
  const response = await getApi(url, {}, "PIH-Appointment-Widget");
@@ -64,7 +68,8 @@ export const getAppointmentDetails = async (appointmentId, config = {}) => {
64
68
  * @returns {Promise<{ data: { token, url, roomName, participantName }, err?, status? }>}
65
69
  */
66
70
  export const initiateConsultation = async (appointment, config = {}) => {
67
- const baseURL = (config.apiBaseUrl || API_BASE_URL).replace(/\/$/, "");
71
+ console.log("initiateConsultation -> config", config)
72
+ const baseURL = (config.apiBaseUrl).replace(/\/$/, "");
68
73
  const url = `${baseURL}${API_PATHS.INITIATE_CALL}`;
69
74
  const appToken = config.appToken || "";
70
75
 
@@ -72,7 +77,7 @@ export const initiateConsultation = async (appointment, config = {}) => {
72
77
  patientId: String(appointment.patientId || ""),
73
78
  primaryPatientId: String(appointment.primaryPatientId || appointment.patientId || ""),
74
79
  hospitalId: config.hospitalId || DEFAULT_PARAMS.hospitalId,
75
- doctorId: String(config.doctor_id || DEFAULT_PARAMS.doctorId),
80
+ doctorId: String(config.doctorId),
76
81
  patientName: appointment.patientName || appointment.name || "",
77
82
  doctorName: appointment.doctorName || config.doctorName,
78
83
  appointmentId: String(appointment.id || appointment.appointmentId || appointment._id || ""),