pih-appointment-widget 0.0.38 → 0.0.39

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.
@@ -9,29 +9,6 @@
9
9
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
10
  var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
11
11
 
12
- function _defineProperty(e, r, t) {
13
- return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
14
- value: t,
15
- enumerable: !0,
16
- configurable: !0,
17
- writable: !0
18
- }) : e[r] = t, e;
19
- }
20
- function _toPrimitive(t, r) {
21
- if ("object" != typeof t || !t) return t;
22
- var e = t[Symbol.toPrimitive];
23
- if (void 0 !== e) {
24
- var i = e.call(t, r || "default");
25
- if ("object" != typeof i) return i;
26
- throw new TypeError("@@toPrimitive must return a primitive value.");
27
- }
28
- return ("string" === r ? String : Number)(t);
29
- }
30
- function _toPropertyKey(t) {
31
- var i = _toPrimitive(t, "string");
32
- return "symbol" == typeof i ? i : i + "";
33
- }
34
-
35
12
  const getApi = async function (url) {
36
13
  let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
37
14
  let token = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
@@ -41,16 +18,15 @@
41
18
  method: "GET",
42
19
  headers: {
43
20
  "Content-Type": "application/json",
44
- "Authorization": "".concat(token)
21
+ "Authorization": `${token}`
45
22
  // "X-CLIENT-APP": header,
46
23
  }
47
24
  };
48
25
  return fetch(urlWithParams, options).then(async response => {
49
26
  const data = await response.json().catch(() => ({}));
50
27
  if (!response.ok) {
51
- var _data$resultInfo;
52
28
  return {
53
- err: (data === null || data === void 0 || (_data$resultInfo = data.resultInfo) === null || _data$resultInfo === void 0 ? void 0 : _data$resultInfo.message) || "Something went wrong!",
29
+ err: data?.resultInfo?.message || "Something went wrong!",
54
30
  status: response.status
55
31
  };
56
32
  }
@@ -58,7 +34,7 @@
58
34
  }).catch(error => {
59
35
  console.error("Fetch error:", error);
60
36
  return {
61
- err: (error === null || error === void 0 ? void 0 : error.message) || String(error) || "Network error"
37
+ err: error?.message || String(error) || "Network error"
62
38
  };
63
39
  });
64
40
  };
@@ -82,9 +58,8 @@
82
58
  return fetch(urlWithParams.toString(), options).then(async response => {
83
59
  const data = await response.json().catch(() => ({}));
84
60
  if (!response.ok) {
85
- var _data$resultInfo2;
86
61
  return {
87
- err: (data === null || data === void 0 || (_data$resultInfo2 = data.resultInfo) === null || _data$resultInfo2 === void 0 ? void 0 : _data$resultInfo2.message) || "Something went wrong!",
62
+ err: data?.resultInfo?.message || "Something went wrong!",
88
63
  status: response.status
89
64
  };
90
65
  }
@@ -97,17 +72,17 @@
97
72
  });
98
73
  };
99
74
 
100
- /**
101
- * SSO login: exchange idToken + email for app token.
102
- * @param {string} apiBaseUrl - e.g. https://afiyaapiqa.powermindinc.com
103
- * @param {string} hospitalId - e.g. dMtEGhak
104
- * @param {string} idToken - JWT id token from auth provider
105
- * @param {string} email - User email
106
- * @returns {Promise<{ token?: string, err?: string, ... }>} - Response with token on success, or { err } on failure
75
+ /**
76
+ * SSO login: exchange idToken + email for app token.
77
+ * @param {string} apiBaseUrl - e.g. https://afiyaapiqa.powermindinc.com
78
+ * @param {string} hospitalId - e.g. dMtEGhak
79
+ * @param {string} idToken - JWT id token from auth provider
80
+ * @param {string} email - User email
81
+ * @returns {Promise<{ token?: string, err?: string, ... }>} - Response with token on success, or { err } on failure
107
82
  */
108
83
  const getTokenFromSso = async (apiBaseUrl, hospitalId, idToken, email) => {
109
84
  const base = apiBaseUrl.replace(/\/$/, "");
110
- const url = "".concat(base, "/um/user/V1/sso/login?hospitalId=").concat(encodeURIComponent(hospitalId));
85
+ const url = `${base}/um/user/V1/sso/login?hospitalId=${encodeURIComponent(hospitalId)}`;
111
86
  const options = {
112
87
  method: "POST",
113
88
  headers: {
@@ -129,8 +104,7 @@
129
104
  console.log("[getTokenFromSso] response status", response.status, response.statusText);
130
105
  if (!response.ok) {
131
106
  return response.json().then(errorData => {
132
- var _errorData$resultInfo;
133
- const errorMessage = (errorData === null || errorData === void 0 || (_errorData$resultInfo = errorData.resultInfo) === null || _errorData$resultInfo === void 0 ? void 0 : _errorData$resultInfo.message) || "SSO login failed";
107
+ const errorMessage = errorData?.resultInfo?.message || "SSO login failed";
134
108
  console.log("[getTokenFromSso] error body", errorData);
135
109
  return {
136
110
  err: errorMessage,
@@ -142,11 +116,10 @@
142
116
  }));
143
117
  }
144
118
  return response.json().then(data => {
145
- var _data$data;
146
119
  console.log("[getTokenFromSso] success", {
147
120
  hasData: !!data,
148
121
  dataKeys: data ? Object.keys(data) : [],
149
- hasAccessToken: !!(data !== null && data !== void 0 && (_data$data = data.data) !== null && _data$data !== void 0 && _data$data.access_token)
122
+ hasAccessToken: !!data?.data?.access_token
150
123
  });
151
124
  return data;
152
125
  });
@@ -179,13 +152,13 @@
179
152
  const JOIN_CALL_URL = "https://ittisalqa.powermindinc.com/call?token=";
180
153
  const WEB_URL = "https://afiyaproqa.powermindinc.com/";
181
154
 
182
- /**
183
- * Fetch appointments by status
184
- * @param {string} status - Appointment status (inprogress, completed, cancelled, upcoming)
185
- * @param {string} fromDate - Start date in YYYY-MM-DD format
186
- * @param {string} toDate - End date in YYYY-MM-DD format
187
- * @param {object} config - Optional configuration { apiBaseUrl, hospitalId, doctorId }
188
- * @returns {Promise} Appointments data
155
+ /**
156
+ * Fetch appointments by status
157
+ * @param {string} status - Appointment status (inprogress, completed, cancelled, upcoming)
158
+ * @param {string} fromDate - Start date in YYYY-MM-DD format
159
+ * @param {string} toDate - End date in YYYY-MM-DD format
160
+ * @param {object} config - Optional configuration { apiBaseUrl, hospitalId, doctorId }
161
+ * @returns {Promise} Appointments data
189
162
  */
190
163
  const getAppointmentsByStatus = async function (status, fromDate, toDate) {
191
164
  let config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
@@ -212,24 +185,24 @@
212
185
  // params.appointmentType = String(type).toUpperCase();
213
186
  // }
214
187
  params.appointmentType = 'ONLINE';
215
- const url = "".concat(baseURL).concat(API_PATHS.APPOINTMENTS);
188
+ const url = `${baseURL}${API_PATHS.APPOINTMENTS}`;
216
189
 
217
190
  // Return raw response (including status) so caller can detect 401 and re-login
218
191
  const response = await getApi(url, params, "PIH-Appointment-Widget", token);
219
192
  return response;
220
193
  };
221
194
 
222
- /**
223
- * Initiate an online consultation — returns LiveKit room token + wss URL.
224
- * @param {object} appointment - Selected appointment object
225
- * @param {object} config - { apiBaseUrl, hospitalId, doctorId, doctorName, appToken }
226
- * @returns {Promise<{ data: { token, url, roomName, participantName }, err?, status? }>}
195
+ /**
196
+ * Initiate an online consultation — returns LiveKit room token + wss URL.
197
+ * @param {object} appointment - Selected appointment object
198
+ * @param {object} config - { apiBaseUrl, hospitalId, doctorId, doctorName, appToken }
199
+ * @returns {Promise<{ data: { token, url, roomName, participantName }, err?, status? }>}
227
200
  */
228
201
  const initiateConsultation = async function (appointment) {
229
202
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
230
203
  console.log("initiateConsultation -> config", config);
231
204
  const baseURL = config.apiBaseUrl.replace(/\/$/, "");
232
- const url = "".concat(baseURL).concat(API_PATHS.INITIATE_CALL);
205
+ const url = `${baseURL}${API_PATHS.INITIATE_CALL}`;
233
206
  const appToken = config.appToken || "";
234
207
  const body = {
235
208
  patientId: String(appointment.patientId || ""),
@@ -252,7 +225,7 @@
252
225
  const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
253
226
  const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=");
254
227
  return JSON.parse(atob(padded));
255
- } catch (_unused) {
228
+ } catch {
256
229
  return {};
257
230
  }
258
231
  }
@@ -272,32 +245,26 @@
272
245
 
273
246
  // Extract from SSO login response (not from appToken JWT — these are only in login response)
274
247
  function extractAppToken(response) {
275
- var _ref, _ref2, _ref3, _response$data$access, _response$data, _response$data2;
276
248
  if (!response || response.err) return null;
277
- return (_ref = (_ref2 = (_ref3 = (_response$data$access = (_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.access_token) !== null && _response$data$access !== void 0 ? _response$data$access : (_response$data2 = response.data) === null || _response$data2 === void 0 ? void 0 : _response$data2.token) !== null && _ref3 !== void 0 ? _ref3 : response.token) !== null && _ref2 !== void 0 ? _ref2 : response.accessToken) !== null && _ref !== void 0 ? _ref : null;
249
+ return response.data?.access_token ?? response.data?.token ?? response.token ?? response.accessToken ?? null;
278
250
  }
279
251
  function extractDoctorIdFromLoginResponse(response) {
280
- var _ref4, _response$data$doctor;
281
- if (!(response !== null && response !== void 0 && response.data)) return null;
282
- const id = (_ref4 = (_response$data$doctor = response.data.doctor_id) !== null && _response$data$doctor !== void 0 ? _response$data$doctor : response.data.doctorId) !== null && _ref4 !== void 0 ? _ref4 : null;
252
+ if (!response?.data) return null;
253
+ const id = response.data.doctor_id ?? response.data.doctorId ?? null;
283
254
  console.log(id, 'extractDoctorIdFromLoginResponse -> id');
284
255
  return id != null ? String(id) : null;
285
256
  }
286
257
  function extractUserNameFromLoginResponse(response) {
287
- var _ref5, _ref6, _response$data$name;
288
- if (!(response !== null && response !== void 0 && response.data)) return null;
289
- const name = (_ref5 = (_ref6 = (_response$data$name = response.data.name) !== null && _response$data$name !== void 0 ? _response$data$name : response.data.doctor_name) !== null && _ref6 !== void 0 ? _ref6 : response.data.userName) !== null && _ref5 !== void 0 ? _ref5 : null;
258
+ if (!response?.data) return null;
259
+ const name = response.data.name ?? response.data.doctor_name ?? response.data.userName ?? null;
290
260
  return name != null ? String(name) : null;
291
261
  }
292
262
 
293
263
  // Error boundary so a render error never shows a blank screen
294
264
  class AppointmentErrorBoundary extends React.Component {
295
- constructor() {
296
- super(...arguments);
297
- _defineProperty(this, "state", {
298
- hasError: false
299
- });
300
- }
265
+ state = {
266
+ hasError: false
267
+ };
301
268
  static getDerivedStateFromError() {
302
269
  return {
303
270
  hasError: true
@@ -354,21 +321,21 @@
354
321
  }
355
322
 
356
323
  // SDK Component - accepts configuration from parent app
357
- const AppointmentPage = _ref7 => {
324
+ const AppointmentPage = _ref => {
358
325
  let {
359
326
  config = {}
360
- } = _ref7;
327
+ } = _ref;
361
328
  const [storedApiBaseUrl, setStoredApiBaseUrl] = React.useState(() => {
362
329
  try {
363
330
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_API_BASE_URL) : null;
364
- } catch (_unused2) {
331
+ } catch {
365
332
  return null;
366
333
  }
367
334
  });
368
335
  const [storedHospitalId, setStoredHospitalId] = React.useState(() => {
369
336
  try {
370
337
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_HOSPITAL_ID) : null;
371
- } catch (_unused3) {
338
+ } catch {
372
339
  return null;
373
340
  }
374
341
  });
@@ -379,14 +346,14 @@
379
346
  const [storedIdToken, setStoredIdToken] = React.useState(() => {
380
347
  try {
381
348
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_ID_TOKEN) : null;
382
- } catch (_unused4) {
349
+ } catch {
383
350
  return null;
384
351
  }
385
352
  });
386
353
  const [storedEmail, setStoredEmail] = React.useState(() => {
387
354
  try {
388
355
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_EMAIL) : null;
389
- } catch (_unused5) {
356
+ } catch {
390
357
  return null;
391
358
  }
392
359
  });
@@ -401,12 +368,14 @@
401
368
  if (token && String(token).trim()) {
402
369
  const prevToken = localStorage.getItem(STORAGE_KEY_ID_TOKEN);
403
370
  if (prevToken !== token) {
404
- // New token from parent (e.g. Flutter re-login) — clear app token and force SSO for the new session.
405
- // refreshLoginTrigger increment guarantees SSO re-runs even if appToken was already null in state.
371
+ // New token from parent (e.g. Flutter re-login) — clear stored credentials.
372
+ // Only increment refreshLoginTrigger when there was an existing appToken to evict;
373
+ // if appToken is already absent, the SSO effect will fire naturally via !appToken.
374
+ const hadAppToken = !!localStorage.getItem(STORAGE_KEY_APP_TOKEN);
406
375
  setAppToken(null);
407
376
  setDoctorIdFromLogin(null);
408
377
  setUserName(null);
409
- setRefreshLoginTrigger(t => t + 1);
378
+ if (hadAppToken) setRefreshLoginTrigger(t => t + 1);
410
379
  localStorage.removeItem(STORAGE_KEY_APP_TOKEN);
411
380
  localStorage.removeItem(STORAGE_KEY_DOCTOR_ID);
412
381
  localStorage.removeItem(STORAGE_KEY_USER_NAME);
@@ -431,21 +400,21 @@
431
400
  const [appToken, setAppToken] = React.useState(() => {
432
401
  try {
433
402
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_APP_TOKEN) : null;
434
- } catch (_unused6) {
403
+ } catch {
435
404
  return null;
436
405
  }
437
406
  });
438
407
  const [doctorIdFromLogin, setDoctorIdFromLogin] = React.useState(() => {
439
408
  try {
440
409
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_DOCTOR_ID) : null;
441
- } catch (_unused7) {
410
+ } catch {
442
411
  return null;
443
412
  }
444
413
  });
445
414
  const [userName, setUserName] = React.useState(() => {
446
415
  try {
447
416
  return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_USER_NAME) : null;
448
- } catch (_unused8) {
417
+ } catch {
449
418
  return null;
450
419
  }
451
420
  });
@@ -456,7 +425,7 @@
456
425
  const hasId = localStorage.getItem(STORAGE_KEY_ID_TOKEN);
457
426
  const hasEmail = localStorage.getItem(STORAGE_KEY_EMAIL);
458
427
  return !hasApp && !!(hasId && hasEmail);
459
- } catch (_unused9) {
428
+ } catch {
460
429
  return false;
461
430
  }
462
431
  });
@@ -518,7 +487,7 @@
518
487
  const y = date.getFullYear();
519
488
  const m = String(date.getMonth() + 1).padStart(2, "0");
520
489
  const d = String(date.getDate()).padStart(2, "0");
521
- return "".concat(y, "-").concat(m, "-").concat(d);
490
+ return `${y}-${m}-${d}`;
522
491
  };
523
492
  const getDateRange = option => {
524
493
  const today = new Date();
@@ -549,8 +518,8 @@
549
518
  to = formatLocalDate(lastOfMonth);
550
519
  break;
551
520
  case "currentYear":
552
- from = "".concat(today.getFullYear(), "-01-01");
553
- to = "".concat(today.getFullYear(), "-12-31");
521
+ from = `${today.getFullYear()}-01-01`;
522
+ to = `${today.getFullYear()}-12-31`;
554
523
  break;
555
524
  default:
556
525
  from = to = getTodayDate();
@@ -575,7 +544,7 @@
575
544
  case "currentYear":
576
545
  return "Current Year";
577
546
  case "custom":
578
- return isMobile ? "Custom" : "".concat(fromDate, " to ").concat(toDate);
547
+ return isMobile ? "Custom" : `${fromDate} to ${toDate}`;
579
548
  default:
580
549
  return "Today";
581
550
  }
@@ -660,12 +629,12 @@
660
629
 
661
630
  // Helper to get unique identifier from appointment
662
631
  const getAppointmentId = appointment => {
663
- return (appointment === null || appointment === void 0 ? void 0 : appointment.id) || (appointment === null || appointment === void 0 ? void 0 : appointment._id) || (appointment === null || appointment === void 0 ? void 0 : appointment.appointmentId) || (appointment === null || appointment === void 0 ? void 0 : appointment.patientId) || JSON.stringify(appointment);
632
+ return appointment?.id || appointment?._id || appointment?.appointmentId || appointment?.patientId || JSON.stringify(appointment);
664
633
  };
665
634
 
666
635
  // Generate avatar with first letter if no image
667
636
  const getPatientAvatar = appointment => {
668
- if (appointment !== null && appointment !== void 0 && appointment.image) {
637
+ if (appointment?.image) {
669
638
  return appointment.image;
670
639
  }
671
640
  // Return null to use the letter avatar component
@@ -766,8 +735,8 @@
766
735
  // Returns true if the current time is within 2 hours after the appointment's scheduled slot time.
767
736
  // Handles date format: "Sun, 15 Mar 2026" and time format: "12:15 PM"
768
737
  const isWithinJoinWindow = appointment => {
769
- const dateStr = (appointment === null || appointment === void 0 ? void 0 : appointment.date) || (appointment === null || appointment === void 0 ? void 0 : appointment.appointmentDate);
770
- const timeStr = (appointment === null || appointment === void 0 ? void 0 : appointment.time) || (appointment === null || appointment === void 0 ? void 0 : appointment.appointmentTime);
738
+ const dateStr = appointment?.date || appointment?.appointmentDate;
739
+ const timeStr = appointment?.time || appointment?.appointmentTime;
771
740
  if (!dateStr || !timeStr) return false;
772
741
  try {
773
742
  // Parse "12:15 PM" or "9:30 AM" into 24-hour h/m values
@@ -787,11 +756,11 @@
787
756
  }
788
757
  if (isNaN(h) || isNaN(m)) return false;
789
758
  // "Sun, 15 Mar 2026 12:15:00" — space-separated; JS parses RFC-like date strings correctly
790
- const appointmentDate = new Date("".concat(dateStr, " ").concat(String(h).padStart(2, "0"), ":").concat(String(m).padStart(2, "0"), ":00"));
759
+ const appointmentDate = new Date(`${dateStr} ${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:00`);
791
760
  if (isNaN(appointmentDate.getTime())) return false;
792
761
  const windowEnd = new Date(appointmentDate.getTime() + 2 * 60 * 60 * 1000);
793
762
  return new Date() <= windowEnd;
794
- } catch (_unused0) {
763
+ } catch {
795
764
  return false;
796
765
  }
797
766
  };
@@ -802,7 +771,6 @@
802
771
  setCallLoading(true);
803
772
  setCallError(null);
804
773
  try {
805
- var _response$data3;
806
774
  const callConfig = {
807
775
  apiBaseUrl,
808
776
  hospitalId,
@@ -830,7 +798,7 @@
830
798
  setCallError("Session expired. Re-authenticating...");
831
799
  return;
832
800
  }
833
- if (response.err || !((_response$data3 = response.data) !== null && _response$data3 !== void 0 && _response$data3.token)) {
801
+ if (response.err || !response.data?.token) {
834
802
  setCallError(String(response.err || "Failed to initiate call"));
835
803
  return;
836
804
  }
@@ -1053,6 +1021,7 @@
1053
1021
  setAppToken(null);
1054
1022
  setDoctorIdFromLogin(null);
1055
1023
  setUserName(null);
1024
+ setRefreshLoginTrigger(0); // reset trigger even on failure to prevent infinite retry loops
1056
1025
  try {
1057
1026
  if (typeof localStorage !== "undefined") {
1058
1027
  localStorage.removeItem(STORAGE_KEY_APP_TOKEN);
@@ -1069,6 +1038,7 @@
1069
1038
  setUserName(name);
1070
1039
  setTokenError(null);
1071
1040
  setRedirectToHome(false);
1041
+ setRefreshLoginTrigger(0); // reset one-shot trigger so SSO doesn't re-fire on next dep change
1072
1042
  try {
1073
1043
  if (typeof localStorage !== "undefined") {
1074
1044
  localStorage.setItem(STORAGE_KEY_APP_TOKEN, token);
@@ -1079,7 +1049,7 @@
1079
1049
  }
1080
1050
  }).catch(err => {
1081
1051
  if (!cancelled) {
1082
- setTokenError((err === null || err === void 0 ? void 0 : err.message) || "Authentication failed. Please try again.");
1052
+ setTokenError(err?.message || "Authentication failed. Please try again.");
1083
1053
  setAppToken(null);
1084
1054
  }
1085
1055
  }).finally(() => {
@@ -1111,7 +1081,32 @@
1111
1081
 
1112
1082
  // Add responsive styles and animations
1113
1083
  const style = document.createElement("style");
1114
- style.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 ";
1084
+ style.innerHTML = `
1085
+ @keyframes spin {
1086
+ 0% { transform: rotate(0deg); }
1087
+ 100% { transform: rotate(360deg); }
1088
+ }
1089
+
1090
+ @media (max-width: 768px) {
1091
+ .appointments-grid {
1092
+ grid-template-columns: 1.5fr 1fr 0.8fr !important;
1093
+ }
1094
+ .appointments-header-grid {
1095
+ grid-template-columns: 1.5fr 1fr 0.8fr !important;
1096
+ }
1097
+ .hide-on-mobile {
1098
+ display: none !important;
1099
+ }
1100
+ }
1101
+ @media (max-width: 480px) {
1102
+ .appointments-header-grid {
1103
+ font-size: 10px !important;
1104
+ }
1105
+ .appointments-grid {
1106
+ font-size: 11px !important;
1107
+ }
1108
+ }
1109
+ `;
1115
1110
  document.head.appendChild(style);
1116
1111
 
1117
1112
  // Handle window resize
@@ -1163,7 +1158,7 @@
1163
1158
  justifyContent: "center",
1164
1159
  padding: "24px"
1165
1160
  }
1166
- }, /*#__PURE__*/React__default["default"].createElement("style", null, "@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }"), /*#__PURE__*/React__default["default"].createElement("div", {
1161
+ }, /*#__PURE__*/React__default["default"].createElement("style", null, `@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }`), /*#__PURE__*/React__default["default"].createElement("div", {
1167
1162
  style: {
1168
1163
  width: "40px",
1169
1164
  height: "40px",
@@ -1776,7 +1771,7 @@
1776
1771
  style: {
1777
1772
  fontSize: "13px"
1778
1773
  }
1779
- }, searchQuery ? "No appointments found for \"".concat(searchQuery, "\"") : "No appointments found"), searchQuery && /*#__PURE__*/React__default["default"].createElement("button", {
1774
+ }, searchQuery ? `No appointments found for "${searchQuery}"` : "No appointments found"), searchQuery && /*#__PURE__*/React__default["default"].createElement("button", {
1780
1775
  onClick: () => setSearchQuery(""),
1781
1776
  style: {
1782
1777
  marginTop: "12px",
@@ -2055,7 +2050,7 @@
2055
2050
  fontWeight: "700",
2056
2051
  fontSize: isMobile ? "12px" : "13px"
2057
2052
  }
2058
- }, (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.specialisation) || (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.speciality) || "N/A")), /*#__PURE__*/React__default["default"].createElement("div", {
2053
+ }, selectedAppointment?.specialisation || selectedAppointment?.speciality || "N/A")), /*#__PURE__*/React__default["default"].createElement("div", {
2059
2054
  style: {
2060
2055
  textAlign: "right"
2061
2056
  }
@@ -2070,7 +2065,7 @@
2070
2065
  fontWeight: "700",
2071
2066
  fontSize: isMobile ? "12px" : "13px"
2072
2067
  }
2073
- }, (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.type) || (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.appointmentType) || "Online"))), /*#__PURE__*/React__default["default"].createElement("div", {
2068
+ }, selectedAppointment?.type || selectedAppointment?.appointmentType || "Online"))), /*#__PURE__*/React__default["default"].createElement("div", {
2074
2069
  style: {
2075
2070
  display: "flex",
2076
2071
  justifyContent: "space-between"
@@ -2090,7 +2085,7 @@
2090
2085
  fontWeight: "700",
2091
2086
  fontSize: isMobile ? "12px" : "13px"
2092
2087
  }
2093
- }, (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.date) || (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.appointmentDate) || "N/A")), /*#__PURE__*/React__default["default"].createElement("div", {
2088
+ }, selectedAppointment?.date || selectedAppointment?.appointmentDate || "N/A")), /*#__PURE__*/React__default["default"].createElement("div", {
2094
2089
  style: {
2095
2090
  textAlign: "right"
2096
2091
  }
@@ -2105,7 +2100,7 @@
2105
2100
  fontWeight: "700",
2106
2101
  fontSize: isMobile ? "12px" : "13px"
2107
2102
  }
2108
- }, (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.time) || (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.appointmentTime) || "N/A"))), /*#__PURE__*/React__default["default"].createElement("div", {
2103
+ }, selectedAppointment?.time || selectedAppointment?.appointmentTime || "N/A"))), /*#__PURE__*/React__default["default"].createElement("div", {
2109
2104
  style: {
2110
2105
  display: "flex",
2111
2106
  justifyContent: "space-between"
@@ -2125,7 +2120,7 @@
2125
2120
  fontWeight: "700",
2126
2121
  fontSize: isMobile ? "12px" : "13px"
2127
2122
  }
2128
- }, (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.doctor) || (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.doctorName) || "N/A"))), /*#__PURE__*/React__default["default"].createElement("div", {
2123
+ }, selectedAppointment?.doctor || selectedAppointment?.doctorName || "N/A"))), /*#__PURE__*/React__default["default"].createElement("div", {
2129
2124
  style: {
2130
2125
  display: "flex",
2131
2126
  justifyContent: "space-between"
@@ -2145,7 +2140,7 @@
2145
2140
  fontWeight: "700",
2146
2141
  fontSize: isMobile ? "12px" : "13px"
2147
2142
  }
2148
- }, (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.hospital) || (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.hospitalName) || "N/A"))), /*#__PURE__*/React__default["default"].createElement("div", {
2143
+ }, selectedAppointment?.hospital || selectedAppointment?.hospitalName || "N/A"))), /*#__PURE__*/React__default["default"].createElement("div", {
2149
2144
  style: {
2150
2145
  display: "flex",
2151
2146
  justifyContent: "space-between"
@@ -2166,7 +2161,7 @@
2166
2161
  fontSize: isMobile ? "11px" : "12px",
2167
2162
  lineHeight: "1.4"
2168
2163
  }
2169
- }, (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.reason) || (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.reasonForAppointment) || "No reason provided"))), (activeTab === "upcoming" || activeTab === "completed" && isWithinJoinWindow(selectedAppointment)) && /*#__PURE__*/React__default["default"].createElement("div", {
2164
+ }, selectedAppointment?.reason || selectedAppointment?.reasonForAppointment || "No reason provided"))), (activeTab === "upcoming" || activeTab === "completed" && isWithinJoinWindow(selectedAppointment)) && /*#__PURE__*/React__default["default"].createElement("div", {
2170
2165
  style: {
2171
2166
  display: "flex",
2172
2167
  flexDirection: isMobile ? "column" : "row",
@@ -2219,12 +2214,12 @@
2219
2214
  }, "Select an appointment to view details"))))))), showPipVideo && /*#__PURE__*/React__default["default"].createElement("div", {
2220
2215
  style: {
2221
2216
  position: "fixed",
2222
- left: isPipFullscreen ? "0" : isMobile ? "10px" : "".concat(pipPosition.x, "px"),
2223
- top: isPipFullscreen ? "0" : isMobile ? "70px" : "".concat(pipPosition.y, "px"),
2217
+ left: isPipFullscreen ? "0" : isMobile ? "10px" : `${pipPosition.x}px`,
2218
+ top: isPipFullscreen ? "0" : isMobile ? "70px" : `${pipPosition.y}px`,
2224
2219
  right: isPipFullscreen ? "0" : isMobile ? "10px" : "auto",
2225
2220
  bottom: isPipFullscreen ? "0" : "auto",
2226
- width: isPipFullscreen ? "100vw" : isMobile ? "calc(100vw - 20px)" : isPipMinimized ? "350px" : "".concat(pipSize.width, "px"),
2227
- height: isPipFullscreen ? "100vh" : isPipMinimized ? "auto" : isMobile ? "300px" : "".concat(pipSize.height, "px"),
2221
+ width: isPipFullscreen ? "100vw" : isMobile ? "calc(100vw - 20px)" : isPipMinimized ? "350px" : `${pipSize.width}px`,
2222
+ height: isPipFullscreen ? "100vh" : isPipMinimized ? "auto" : isMobile ? "300px" : `${pipSize.height}px`,
2228
2223
  background: "#FFFFFF",
2229
2224
  borderRadius: isPipFullscreen ? "0" : "8px",
2230
2225
  boxShadow: "0 8px 24px rgba(0, 0, 0, 0.3)",
@@ -2275,7 +2270,7 @@
2275
2270
  textOverflow: "ellipsis",
2276
2271
  whiteSpace: "nowrap"
2277
2272
  }
2278
- }, "Video Call - ", (selectedAppointment === null || selectedAppointment === void 0 ? void 0 : selectedAppointment.patientName) || "Patient")), /*#__PURE__*/React__default["default"].createElement("div", {
2273
+ }, "Video Call - ", selectedAppointment?.patientName || "Patient")), /*#__PURE__*/React__default["default"].createElement("div", {
2279
2274
  style: {
2280
2275
  display: "flex",
2281
2276
  gap: isMobile ? "4px" : "6px",
@@ -2404,7 +2399,7 @@
2404
2399
  src: (() => {
2405
2400
  if (!callToken) return "";
2406
2401
  const base = String(joinCallUrlBase || "");
2407
- return "".concat(base).concat(callToken);
2402
+ return `${base}${callToken}`;
2408
2403
  })(),
2409
2404
  style: {
2410
2405
  width: "100%",
@@ -2475,7 +2470,12 @@
2475
2470
  background: "transparent",
2476
2471
  zIndex: 10001
2477
2472
  }
2478
- })), /*#__PURE__*/React__default["default"].createElement("style", null, "\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n "))), showAuthError && /*#__PURE__*/React__default["default"].createElement("div", {
2473
+ })), /*#__PURE__*/React__default["default"].createElement("style", null, `
2474
+ @keyframes pulse {
2475
+ 0%, 100% { opacity: 1; }
2476
+ 50% { opacity: 0.5; }
2477
+ }
2478
+ `))), showAuthError && /*#__PURE__*/React__default["default"].createElement("div", {
2479
2479
  style: {
2480
2480
  position: "fixed",
2481
2481
  inset: 0,
@@ -2522,20 +2522,20 @@
2522
2522
  return /*#__PURE__*/React__default["default"].createElement(AppointmentErrorBoundary, null, content);
2523
2523
  };
2524
2524
 
2525
- /**
2526
- * icdService.js
2527
- * Calls the Afiya ICD suggestion API.
2528
- *
2529
- * POST /insurance/api/icd/suggest
2530
- * Body: { query: string, mode: ICD_MODE }
2525
+ /**
2526
+ * icdService.js
2527
+ * Calls the Afiya ICD suggestion API.
2528
+ *
2529
+ * POST /insurance/api/icd/suggest
2530
+ * Body: { query: string, mode: ICD_MODE }
2531
2531
  */
2532
2532
 
2533
- /**
2534
- * Enum for ICD suggest API modes.
2535
- * Use these constants everywhere — never hardcode the string values.
2536
- *
2537
- * @readonly
2538
- * @enum {string}
2533
+ /**
2534
+ * Enum for ICD suggest API modes.
2535
+ * Use these constants everywhere — never hardcode the string values.
2536
+ *
2537
+ * @readonly
2538
+ * @enum {string}
2539
2539
  */
2540
2540
  const ICD_MODE = Object.freeze({
2541
2541
  /** Real-time ICD-10 code lookup (fast, no AI) */
@@ -2545,15 +2545,14 @@
2545
2545
  /** Backend decides best strategy automatically */
2546
2546
  AUTO: "AUTO"
2547
2547
  });
2548
- const SUGGEST_URL = "".concat(API_BASE_URL, "/insurance/api/icd/suggest");
2548
+ const SUGGEST_URL = `${API_BASE_URL}/insurance/api/icd/suggest`;
2549
2549
 
2550
- /**
2551
- * @param {string} query - Plain-language diagnosis / procedure
2552
- * @param {"ICD_ONLY"|"CLAUDE_ONLY"|"AUTO"} mode
2553
- * @returns {Promise<{ matches: Array<{ code, description, reason }>, note: string }>}
2550
+ /**
2551
+ * @param {string} query - Plain-language diagnosis / procedure
2552
+ * @param {"ICD_ONLY"|"CLAUDE_ONLY"|"AUTO"} mode
2553
+ * @returns {Promise<{ matches: Array<{ code, description, reason }>, note: string }>}
2554
2554
  */
2555
2555
  async function getICDSuggestions(query, mode) {
2556
- var _data$data;
2557
2556
  if (!query || !query.trim()) throw new Error("Query cannot be empty");
2558
2557
  const response = await fetch(SUGGEST_URL, {
2559
2558
  method: "POST",
@@ -2566,18 +2565,17 @@
2566
2565
  })
2567
2566
  });
2568
2567
  if (!response.ok) {
2569
- var _errBody$error;
2570
2568
  const errBody = await response.json().catch(() => ({}));
2571
- const msg = (errBody === null || errBody === void 0 ? void 0 : errBody.message) || (errBody === null || errBody === void 0 || (_errBody$error = errBody.error) === null || _errBody$error === void 0 ? void 0 : _errBody$error.message) || "API error: ".concat(response.status, " ").concat(response.statusText);
2569
+ const msg = errBody?.message || errBody?.error?.message || `API error: ${response.status} ${response.statusText}`;
2572
2570
  throw new Error(msg);
2573
2571
  }
2574
2572
  const data = await response.json();
2575
2573
 
2576
2574
  // API wraps response in { data: { matches, note, ... }, resultInfo }
2577
- const payload = (_data$data = data === null || data === void 0 ? void 0 : data.data) !== null && _data$data !== void 0 ? _data$data : data;
2575
+ const payload = data?.data ?? data;
2578
2576
 
2579
2577
  // Normalise response → always return { matches, note }
2580
- if (Array.isArray(payload === null || payload === void 0 ? void 0 : payload.matches)) {
2578
+ if (Array.isArray(payload?.matches)) {
2581
2579
  return {
2582
2580
  matches: payload.matches,
2583
2581
  note: payload.note || ""
@@ -2589,7 +2587,7 @@
2589
2587
  note: ""
2590
2588
  };
2591
2589
  }
2592
- if (Array.isArray(payload === null || payload === void 0 ? void 0 : payload.results)) {
2590
+ if (Array.isArray(payload?.results)) {
2593
2591
  return {
2594
2592
  matches: payload.results.map(r => ({
2595
2593
  code: r.code,
@@ -2602,9 +2600,9 @@
2602
2600
  throw new Error("Unexpected response format from ICD suggest API");
2603
2601
  }
2604
2602
 
2605
- /**
2606
- * useClipboard.js
2607
- * Tiny hook for clipboard copy with transient "Copied!" feedback.
2603
+ /**
2604
+ * useClipboard.js
2605
+ * Tiny hook for clipboard copy with transient "Copied!" feedback.
2608
2606
  */
2609
2607
  function useClipboard() {
2610
2608
  let resetMs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1800;
@@ -2660,10 +2658,10 @@
2660
2658
  copy: "⎘"
2661
2659
  };
2662
2660
 
2663
- /**
2664
- * ICD10Assistant.jsx
2665
- * AI-powered ICD-10 coding assistant panel.
2666
- * Floats as a pill button; expands into a full panel on click.
2661
+ /**
2662
+ * ICD10Assistant.jsx
2663
+ * AI-powered ICD-10 coding assistant panel.
2664
+ * Floats as a pill button; expands into a full panel on click.
2667
2665
  */
2668
2666
 
2669
2667
  // ─── Constants ───────────────────────────────────────────────────────────────
@@ -2712,12 +2710,12 @@
2712
2710
  }, children);
2713
2711
  }
2714
2712
  function Spinner() {
2715
- return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("style", null, "@keyframes icd-spin{to{transform:rotate(360deg)}}"), /*#__PURE__*/React__default["default"].createElement("div", {
2713
+ return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("style", null, `@keyframes icd-spin{to{transform:rotate(360deg)}}`), /*#__PURE__*/React__default["default"].createElement("div", {
2716
2714
  style: {
2717
2715
  width: 20,
2718
2716
  height: 20,
2719
2717
  border: "2.5px solid #d1d5db",
2720
- borderTop: "2.5px solid ".concat(C.primary),
2718
+ borderTop: `2.5px solid ${C.primary}`,
2721
2719
  borderRadius: "50%",
2722
2720
  animation: "icd-spin 0.8s linear infinite",
2723
2721
  flexShrink: 0
@@ -2735,7 +2733,7 @@
2735
2733
  const copied = copiedKey === copyKey;
2736
2734
  return /*#__PURE__*/React__default["default"].createElement("button", {
2737
2735
  onClick: () => copy(text, copyKey),
2738
- title: copied ? "Copied!" : "Copy ".concat(label),
2736
+ title: copied ? "Copied!" : `Copy ${label}`,
2739
2737
  style: {
2740
2738
  display: "inline-flex",
2741
2739
  alignItems: "center",
@@ -2744,7 +2742,7 @@
2744
2742
  fontSize: 11,
2745
2743
  fontWeight: 600,
2746
2744
  fontFamily: FONT,
2747
- border: "1px solid ".concat(copied ? C.success : C.border),
2745
+ border: `1px solid ${copied ? C.success : C.border}`,
2748
2746
  borderRadius: 5,
2749
2747
  background: copied ? C.successLight : C.white,
2750
2748
  color: copied ? C.success : C.muted,
@@ -2752,7 +2750,7 @@
2752
2750
  transition: "all 0.15s ease",
2753
2751
  whiteSpace: "nowrap"
2754
2752
  }
2755
- }, copied ? "✓ Copied" : "\u2398 ".concat(label));
2753
+ }, copied ? "✓ Copied" : `⎘ ${label}`);
2756
2754
  }
2757
2755
 
2758
2756
  // ─── Result Card ──────────────────────────────────────────────────────────────
@@ -2763,11 +2761,11 @@
2763
2761
  copy,
2764
2762
  copiedKey
2765
2763
  } = _ref3;
2766
- const cardCopyKey = "card-".concat(index);
2767
- const fullText = "".concat(match.code, " \u2014 ").concat(match.description).concat(match.reason ? "\nNote: ".concat(match.reason) : "");
2764
+ const cardCopyKey = `card-${index}`;
2765
+ const fullText = `${match.code} ${match.description}${match.reason ? `\nNote: ${match.reason}` : ""}`;
2768
2766
  return /*#__PURE__*/React__default["default"].createElement("div", {
2769
2767
  style: {
2770
- border: "1px solid ".concat(C.border),
2768
+ border: `1px solid ${C.border}`,
2771
2769
  borderRadius: 10,
2772
2770
  padding: "14px 16px",
2773
2771
  background: C.white,
@@ -2825,10 +2823,10 @@
2825
2823
  } = _ref4;
2826
2824
  return /*#__PURE__*/React__default["default"].createElement("button", {
2827
2825
  onClick: () => onClick(item.query),
2828
- title: "Re-run: ".concat(item.query),
2826
+ title: `Re-run: ${item.query}`,
2829
2827
  style: {
2830
2828
  padding: "4px 10px",
2831
- border: "1px solid ".concat(C.border),
2829
+ border: `1px solid ${C.border}`,
2832
2830
  borderRadius: 999,
2833
2831
  fontSize: 11,
2834
2832
  fontFamily: FONT,
@@ -2901,10 +2899,7 @@
2901
2899
  const debounceRef = React.useRef(null);
2902
2900
  const inputRef = React.useRef(null);
2903
2901
  React.useEffect(() => {
2904
- setTimeout(() => {
2905
- var _inputRef$current;
2906
- return (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
2907
- }, 80);
2902
+ setTimeout(() => inputRef.current?.focus(), 80);
2908
2903
  }, []);
2909
2904
  const search = React.useCallback(async term => {
2910
2905
  if (term.length < 2) {
@@ -2917,7 +2912,7 @@
2917
2912
  const data = await getICDSuggestions(term, ICD_MODE.ICD_ONLY);
2918
2913
  const codes = (data.matches || []).map(m => [m.code, m.description]);
2919
2914
  setResults(codes);
2920
- setStatus(codes.length === 0 ? "No matching codes found." : "Showing ".concat(codes.length, " result").concat(codes.length !== 1 ? "s" : ""));
2915
+ setStatus(codes.length === 0 ? "No matching codes found." : `Showing ${codes.length} result${codes.length !== 1 ? "s" : ""}`);
2921
2916
  } catch (err) {
2922
2917
  setStatus(err.message || "Could not fetch results. Check your connection.");
2923
2918
  setResults([]);
@@ -2953,9 +2948,9 @@
2953
2948
  overflow: "hidden",
2954
2949
  animation: "icd-slide-in 0.2s ease"
2955
2950
  }
2956
- }, /*#__PURE__*/React__default["default"].createElement("style", null, "@keyframes icd-slide-in{from{opacity:0;transform:translateY(20px) scale(0.97)}to{opacity:1;transform:translateY(0) scale(1)}}"), /*#__PURE__*/React__default["default"].createElement("div", {
2951
+ }, /*#__PURE__*/React__default["default"].createElement("style", null, `@keyframes icd-slide-in{from{opacity:0;transform:translateY(20px) scale(0.97)}to{opacity:1;transform:translateY(0) scale(1)}}`), /*#__PURE__*/React__default["default"].createElement("div", {
2957
2952
  style: {
2958
- background: "linear-gradient(135deg, ".concat(C.primary, " 0%, ").concat(C.teal, " 100%)"),
2953
+ background: `linear-gradient(135deg, ${C.primary} 0%, ${C.teal} 100%)`,
2959
2954
  padding: "14px 18px",
2960
2955
  flexShrink: 0
2961
2956
  }
@@ -3030,7 +3025,7 @@
3030
3025
  padding: "10px 14px",
3031
3026
  fontSize: 14,
3032
3027
  fontFamily: FONT,
3033
- border: "1.5px solid ".concat(C.border),
3028
+ border: `1.5px solid ${C.border}`,
3034
3029
  borderRadius: 8,
3035
3030
  outline: "none",
3036
3031
  boxSizing: "border-box",
@@ -3044,7 +3039,7 @@
3044
3039
  fontSize: 11,
3045
3040
  color: "#aaa",
3046
3041
  lineHeight: 1.6,
3047
- borderLeft: "3px solid ".concat(C.border),
3042
+ borderLeft: `3px solid ${C.border}`,
3048
3043
  paddingLeft: 8
3049
3044
  }
3050
3045
  }, /*#__PURE__*/React__default["default"].createElement("strong", null, "Note:"), " Use short, specific keywords for better results, or try", " ", /*#__PURE__*/React__default["default"].createElement("button", {
@@ -3069,7 +3064,7 @@
3069
3064
  }, status), status === "No matching codes found." && results.length === 0 && /*#__PURE__*/React__default["default"].createElement("div", {
3070
3065
  style: {
3071
3066
  background: C.warnLight,
3072
- border: "1px solid #fcd34d",
3067
+ border: `1px solid #fcd34d`,
3073
3068
  borderRadius: 10,
3074
3069
  padding: "14px 16px",
3075
3070
  display: "flex",
@@ -3124,7 +3119,7 @@
3124
3119
  alignItems: "center",
3125
3120
  gap: 12,
3126
3121
  padding: "10px 14px",
3127
- border: "1px solid ".concat(C.border),
3122
+ border: `1px solid ${C.border}`,
3128
3123
  borderRadius: 8,
3129
3124
  cursor: "pointer",
3130
3125
  background: C.white,
@@ -3160,7 +3155,7 @@
3160
3155
  style: {
3161
3156
  flexShrink: 0,
3162
3157
  padding: "10px 18px",
3163
- borderTop: "1px solid ".concat(C.border),
3158
+ borderTop: `1px solid ${C.border}`,
3164
3159
  background: C.bg,
3165
3160
  fontSize: 11,
3166
3161
  color: "#aaa",
@@ -3189,7 +3184,7 @@
3189
3184
  padding: "10px 18px",
3190
3185
  borderRadius: 999,
3191
3186
  border: "none",
3192
- background: "linear-gradient(135deg, ".concat(C.primary, " 0%, ").concat(C.teal, " 100%)"),
3187
+ background: `linear-gradient(135deg, ${C.primary} 0%, ${C.teal} 100%)`,
3193
3188
  color: C.white,
3194
3189
  fontFamily: FONT,
3195
3190
  fontWeight: 700,
@@ -3220,7 +3215,6 @@
3220
3215
  // ─── Panel ────────────────────────────────────────────────────────────────────
3221
3216
  // Defined OUTSIDE the main component so its DOM is never torn down on re-render.
3222
3217
  function Panel(_ref9) {
3223
- var _result$matches;
3224
3218
  let {
3225
3219
  panelRef,
3226
3220
  textareaRef,
@@ -3240,7 +3234,7 @@
3240
3234
  mode,
3241
3235
  onModeChange
3242
3236
  } = _ref9;
3243
- const allCodesText = (result === null || result === void 0 || (_result$matches = result.matches) === null || _result$matches === void 0 ? void 0 : _result$matches.map(m => "".concat(m.code, " \u2014 ").concat(m.description)).join("\n")) || "";
3237
+ const allCodesText = result?.matches?.map(m => `${m.code} ${m.description}`).join("\n") || "";
3244
3238
  return /*#__PURE__*/React__default["default"].createElement("div", {
3245
3239
  style: {
3246
3240
  position: "fixed",
@@ -3259,9 +3253,14 @@
3259
3253
  animation: "icd-slide-in 0.2s ease"
3260
3254
  },
3261
3255
  ref: panelRef
3262
- }, /*#__PURE__*/React__default["default"].createElement("style", null, "\n @keyframes icd-slide-in {\n from { opacity: 0; transform: translateY(20px) scale(0.97); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n "), /*#__PURE__*/React__default["default"].createElement("div", {
3256
+ }, /*#__PURE__*/React__default["default"].createElement("style", null, `
3257
+ @keyframes icd-slide-in {
3258
+ from { opacity: 0; transform: translateY(20px) scale(0.97); }
3259
+ to { opacity: 1; transform: translateY(0) scale(1); }
3260
+ }
3261
+ `), /*#__PURE__*/React__default["default"].createElement("div", {
3263
3262
  style: {
3264
- background: "linear-gradient(135deg, ".concat(C.primary, " 0%, ").concat(C.teal, " 100%)"),
3263
+ background: `linear-gradient(135deg, ${C.primary} 0%, ${C.teal} 100%)`,
3265
3264
  padding: "14px 18px",
3266
3265
  flexShrink: 0
3267
3266
  }
@@ -3357,7 +3356,7 @@
3357
3356
  style: {
3358
3357
  width: "100%",
3359
3358
  padding: "10px 12px",
3360
- border: "1.5px solid ".concat(C.border),
3359
+ border: `1.5px solid ${C.border}`,
3361
3360
  borderRadius: 8,
3362
3361
  fontSize: 13,
3363
3362
  fontFamily: FONT,
@@ -3405,7 +3404,7 @@
3405
3404
  justifyContent: "center",
3406
3405
  gap: 8,
3407
3406
  padding: "10px 16px",
3408
- background: !query.trim() || loading ? "#d1d5db" : "linear-gradient(135deg, ".concat(C.primary, " 0%, ").concat(C.primaryDark, " 100%)"),
3407
+ background: !query.trim() || loading ? "#d1d5db" : `linear-gradient(135deg, ${C.primary} 0%, ${C.primaryDark} 100%)`,
3409
3408
  color: C.white,
3410
3409
  border: "none",
3411
3410
  borderRadius: 8,
@@ -3420,7 +3419,7 @@
3420
3419
  style: {
3421
3420
  padding: "10px 14px",
3422
3421
  background: C.bg,
3423
- border: "1px solid ".concat(C.border),
3422
+ border: `1px solid ${C.border}`,
3424
3423
  borderRadius: 8,
3425
3424
  fontSize: 13,
3426
3425
  fontWeight: 600,
@@ -3431,7 +3430,7 @@
3431
3430
  }, "Clear")), error && /*#__PURE__*/React__default["default"].createElement("div", {
3432
3431
  style: {
3433
3432
  background: C.errorLight,
3434
- border: "1px solid #fca5a5",
3433
+ border: `1px solid #fca5a5`,
3435
3434
  borderRadius: 8,
3436
3435
  padding: "10px 14px",
3437
3436
  fontSize: 13,
@@ -3515,7 +3514,7 @@
3515
3514
  style: {
3516
3515
  flexShrink: 0,
3517
3516
  padding: "12px 18px",
3518
- borderTop: "1px solid ".concat(C.border),
3517
+ borderTop: `1px solid ${C.border}`,
3519
3518
  background: C.bg,
3520
3519
  fontSize: 11,
3521
3520
  color: "#aaa",
@@ -3544,10 +3543,7 @@
3544
3543
  // Focus textarea when panel opens
3545
3544
  React.useEffect(() => {
3546
3545
  if (open && textareaRef.current) {
3547
- setTimeout(() => {
3548
- var _textareaRef$current;
3549
- return (_textareaRef$current = textareaRef.current) === null || _textareaRef$current === void 0 ? void 0 : _textareaRef$current.focus();
3550
- }, 80);
3546
+ setTimeout(() => textareaRef.current?.focus(), 80);
3551
3547
  }
3552
3548
  }, [open]);
3553
3549
 
@@ -3590,18 +3586,16 @@
3590
3586
  }
3591
3587
  }, [handleSubmit]);
3592
3588
  const handleClear = React.useCallback(() => {
3593
- var _textareaRef$current2;
3594
3589
  setQuery("");
3595
3590
  setResult(null);
3596
3591
  setError(null);
3597
- (_textareaRef$current2 = textareaRef.current) === null || _textareaRef$current2 === void 0 || _textareaRef$current2.focus();
3592
+ textareaRef.current?.focus();
3598
3593
  }, []);
3599
3594
  const handleHistoryClick = React.useCallback(q => {
3600
- var _textareaRef$current3;
3601
3595
  setQuery(q);
3602
3596
  setResult(null);
3603
3597
  setError(null);
3604
- (_textareaRef$current3 = textareaRef.current) === null || _textareaRef$current3 === void 0 || _textareaRef$current3.focus();
3598
+ textareaRef.current?.focus();
3605
3599
  }, []);
3606
3600
  const handleQueryChange = React.useCallback(e => setQuery(e.target.value), []);
3607
3601
  return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, !open && /*#__PURE__*/React__default["default"].createElement(FloatingButton, {
@@ -3636,14 +3630,14 @@
3636
3630
 
3637
3631
  // SDK for embedding appointment widget
3638
3632
  const BookingSDK = {
3639
- /**
3640
- * Show appointment widget with configuration
3641
- * @param {object} config - Configuration object
3642
- * @param {string} config.apiBaseUrl - Base URL for API
3643
- * @param {string} config.hospitalId - Hospital ID
3644
- * @param {number} config.doctorId - Doctor ID
3645
- * @param {string} config.joinCallUrl - Video call URL
3646
- * @param {function} onAction - Optional callback for actions
3633
+ /**
3634
+ * Show appointment widget with configuration
3635
+ * @param {object} config - Configuration object
3636
+ * @param {string} config.apiBaseUrl - Base URL for API
3637
+ * @param {string} config.hospitalId - Hospital ID
3638
+ * @param {number} config.doctorId - Doctor ID
3639
+ * @param {string} config.joinCallUrl - Video call URL
3640
+ * @param {function} onAction - Optional callback for actions
3647
3641
  */
3648
3642
  showWidget: (config, onAction) => {
3649
3643
  if (!bookingWidgetInstance) {