pih-appointment-widget 0.0.37 → 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;
@@ -2636,10 +2634,34 @@
2636
2634
  };
2637
2635
  }
2638
2636
 
2639
- /**
2640
- * ICD10Assistant.jsx
2641
- * AI-powered ICD-10 coding assistant panel.
2642
- * Floats as a pill button; expands into a full panel on click.
2637
+ var img = "data:image/png;base64,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";
2638
+
2639
+ // ─── Image assets ─────────────────────────────────────────────────────────────
2640
+ const IMG = {
2641
+ /** Main ICD-10 Assistant branding icon (floating button + panel header) */
2642
+ icdIcon: img
2643
+ };
2644
+
2645
+ // ─── Emoji / text icons ───────────────────────────────────────────────────────
2646
+ const ICON = {
2647
+ /** Reason / tip indicator on result cards */
2648
+ reason: "💡",
2649
+ /** Search history chip prefix */
2650
+ history: "🕐",
2651
+ /** Footer medical disclaimer */
2652
+ medical: "⚕️",
2653
+ /** Coding note (currently commented out) */
2654
+ codingNote: "📋",
2655
+ /** Copy success checkmark */
2656
+ copied: "✓",
2657
+ /** Copy action */
2658
+ copy: "⎘"
2659
+ };
2660
+
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.
2643
2665
  */
2644
2666
 
2645
2667
  // ─── Constants ───────────────────────────────────────────────────────────────
@@ -2688,12 +2710,12 @@
2688
2710
  }, children);
2689
2711
  }
2690
2712
  function Spinner() {
2691
- 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", {
2692
2714
  style: {
2693
2715
  width: 20,
2694
2716
  height: 20,
2695
2717
  border: "2.5px solid #d1d5db",
2696
- borderTop: "2.5px solid ".concat(C.primary),
2718
+ borderTop: `2.5px solid ${C.primary}`,
2697
2719
  borderRadius: "50%",
2698
2720
  animation: "icd-spin 0.8s linear infinite",
2699
2721
  flexShrink: 0
@@ -2711,7 +2733,7 @@
2711
2733
  const copied = copiedKey === copyKey;
2712
2734
  return /*#__PURE__*/React__default["default"].createElement("button", {
2713
2735
  onClick: () => copy(text, copyKey),
2714
- title: copied ? "Copied!" : "Copy ".concat(label),
2736
+ title: copied ? "Copied!" : `Copy ${label}`,
2715
2737
  style: {
2716
2738
  display: "inline-flex",
2717
2739
  alignItems: "center",
@@ -2720,7 +2742,7 @@
2720
2742
  fontSize: 11,
2721
2743
  fontWeight: 600,
2722
2744
  fontFamily: FONT,
2723
- border: "1px solid ".concat(copied ? C.success : C.border),
2745
+ border: `1px solid ${copied ? C.success : C.border}`,
2724
2746
  borderRadius: 5,
2725
2747
  background: copied ? C.successLight : C.white,
2726
2748
  color: copied ? C.success : C.muted,
@@ -2728,7 +2750,7 @@
2728
2750
  transition: "all 0.15s ease",
2729
2751
  whiteSpace: "nowrap"
2730
2752
  }
2731
- }, copied ? "✓ Copied" : "\u2398 ".concat(label));
2753
+ }, copied ? "✓ Copied" : `⎘ ${label}`);
2732
2754
  }
2733
2755
 
2734
2756
  // ─── Result Card ──────────────────────────────────────────────────────────────
@@ -2739,11 +2761,11 @@
2739
2761
  copy,
2740
2762
  copiedKey
2741
2763
  } = _ref3;
2742
- const cardCopyKey = "card-".concat(index);
2743
- 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}` : ""}`;
2744
2766
  return /*#__PURE__*/React__default["default"].createElement("div", {
2745
2767
  style: {
2746
- border: "1px solid ".concat(C.border),
2768
+ border: `1px solid ${C.border}`,
2747
2769
  borderRadius: 10,
2748
2770
  padding: "14px 16px",
2749
2771
  background: C.white,
@@ -2790,7 +2812,7 @@
2790
2812
  lineHeight: 1.5,
2791
2813
  paddingLeft: 2
2792
2814
  }
2793
- }, "\uD83D\uDCA1 ", match.reason));
2815
+ }, ICON.reason, " ", match.reason));
2794
2816
  }
2795
2817
 
2796
2818
  // ─── History Chip ─────────────────────────────────────────────────────────────
@@ -2801,10 +2823,10 @@
2801
2823
  } = _ref4;
2802
2824
  return /*#__PURE__*/React__default["default"].createElement("button", {
2803
2825
  onClick: () => onClick(item.query),
2804
- title: "Re-run: ".concat(item.query),
2826
+ title: `Re-run: ${item.query}`,
2805
2827
  style: {
2806
2828
  padding: "4px 10px",
2807
- border: "1px solid ".concat(C.border),
2829
+ border: `1px solid ${C.border}`,
2808
2830
  borderRadius: 999,
2809
2831
  fontSize: 11,
2810
2832
  fontFamily: FONT,
@@ -2819,7 +2841,7 @@
2819
2841
  },
2820
2842
  onMouseEnter: e => e.currentTarget.style.borderColor = C.primary,
2821
2843
  onMouseLeave: e => e.currentTarget.style.borderColor = C.border
2822
- }, "\uD83D\uDD50 ", item.query);
2844
+ }, ICON.history, " ", item.query);
2823
2845
  }
2824
2846
 
2825
2847
  // ─── Mode Toggle (tab bar) ──────────────────────────────────────────────────
@@ -2858,7 +2880,7 @@
2858
2880
  gap: 2,
2859
2881
  marginTop: 10
2860
2882
  }
2861
- }, tab("nlm", "Quick Lookup", "🔎"), tab("ai", "AI Suggest", "🤖"));
2883
+ }, tab("nlm", "Quick Lookup", ""), tab("ai", "AI Suggest", ""));
2862
2884
  }
2863
2885
 
2864
2886
  // ─── NLM Lookup Panel ────────────────────────────────────────────────────────
@@ -2877,10 +2899,7 @@
2877
2899
  const debounceRef = React.useRef(null);
2878
2900
  const inputRef = React.useRef(null);
2879
2901
  React.useEffect(() => {
2880
- setTimeout(() => {
2881
- var _inputRef$current;
2882
- return (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
2883
- }, 80);
2902
+ setTimeout(() => inputRef.current?.focus(), 80);
2884
2903
  }, []);
2885
2904
  const search = React.useCallback(async term => {
2886
2905
  if (term.length < 2) {
@@ -2893,7 +2912,7 @@
2893
2912
  const data = await getICDSuggestions(term, ICD_MODE.ICD_ONLY);
2894
2913
  const codes = (data.matches || []).map(m => [m.code, m.description]);
2895
2914
  setResults(codes);
2896
- 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" : ""}`);
2897
2916
  } catch (err) {
2898
2917
  setStatus(err.message || "Could not fetch results. Check your connection.");
2899
2918
  setResults([]);
@@ -2929,9 +2948,9 @@
2929
2948
  overflow: "hidden",
2930
2949
  animation: "icd-slide-in 0.2s ease"
2931
2950
  }
2932
- }, /*#__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", {
2933
2952
  style: {
2934
- background: "linear-gradient(135deg, ".concat(C.primary, " 0%, ").concat(C.teal, " 100%)"),
2953
+ background: `linear-gradient(135deg, ${C.primary} 0%, ${C.teal} 100%)`,
2935
2954
  padding: "14px 18px",
2936
2955
  flexShrink: 0
2937
2956
  }
@@ -2947,11 +2966,15 @@
2947
2966
  alignItems: "center",
2948
2967
  gap: 10
2949
2968
  }
2950
- }, /*#__PURE__*/React__default["default"].createElement("span", {
2969
+ }, /*#__PURE__*/React__default["default"].createElement("img", {
2970
+ src: IMG.icdIcon,
2971
+ alt: "ICD-10",
2951
2972
  style: {
2952
- fontSize: 22
2973
+ width: 32,
2974
+ height: 32,
2975
+ objectFit: "contain"
2953
2976
  }
2954
- }, "\uD83E\uDE7A"), /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("div", {
2977
+ }), /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("div", {
2955
2978
  style: {
2956
2979
  color: C.white,
2957
2980
  fontWeight: 700,
@@ -3002,7 +3025,7 @@
3002
3025
  padding: "10px 14px",
3003
3026
  fontSize: 14,
3004
3027
  fontFamily: FONT,
3005
- border: "1.5px solid ".concat(C.border),
3028
+ border: `1.5px solid ${C.border}`,
3006
3029
  borderRadius: 8,
3007
3030
  outline: "none",
3008
3031
  boxSizing: "border-box",
@@ -3010,13 +3033,77 @@
3010
3033
  },
3011
3034
  onFocus: e => e.target.style.borderColor = C.primary,
3012
3035
  onBlur: e => e.target.style.borderColor = C.border
3013
- }), status && /*#__PURE__*/React__default["default"].createElement("p", {
3036
+ }), /*#__PURE__*/React__default["default"].createElement("p", {
3037
+ style: {
3038
+ margin: 0,
3039
+ fontSize: 11,
3040
+ color: "#aaa",
3041
+ lineHeight: 1.6,
3042
+ borderLeft: `3px solid ${C.border}`,
3043
+ paddingLeft: 8
3044
+ }
3045
+ }, /*#__PURE__*/React__default["default"].createElement("strong", null, "Note:"), " Use short, specific keywords for better results, or try", " ", /*#__PURE__*/React__default["default"].createElement("button", {
3046
+ onClick: () => onModeChange("ai"),
3047
+ style: {
3048
+ background: "none",
3049
+ border: "none",
3050
+ padding: 0,
3051
+ color: C.primary,
3052
+ fontWeight: 700,
3053
+ fontSize: 11,
3054
+ cursor: "pointer",
3055
+ textDecoration: "underline",
3056
+ fontFamily: FONT
3057
+ }
3058
+ }, "AI Suggest"), " ", "for broader symptom-based recommendations."), status && results.length > 0 && /*#__PURE__*/React__default["default"].createElement("p", {
3014
3059
  style: {
3015
3060
  margin: 0,
3016
3061
  fontSize: 12,
3017
3062
  color: C.muted
3018
3063
  }
3019
- }, status), /*#__PURE__*/React__default["default"].createElement("div", {
3064
+ }, status), status === "No matching codes found." && results.length === 0 && /*#__PURE__*/React__default["default"].createElement("div", {
3065
+ style: {
3066
+ background: C.warnLight,
3067
+ border: `1px solid #fcd34d`,
3068
+ borderRadius: 10,
3069
+ padding: "14px 16px",
3070
+ display: "flex",
3071
+ gap: 10,
3072
+ alignItems: "flex-start"
3073
+ }
3074
+ }, /*#__PURE__*/React__default["default"].createElement("span", {
3075
+ style: {
3076
+ fontSize: 18,
3077
+ flexShrink: 0
3078
+ }
3079
+ }, "\uD83D\uDD0D"), /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("p", {
3080
+ style: {
3081
+ margin: "0 0 4px",
3082
+ fontSize: 13,
3083
+ fontWeight: 700,
3084
+ color: C.warn
3085
+ }
3086
+ }, "No results found"), /*#__PURE__*/React__default["default"].createElement("p", {
3087
+ style: {
3088
+ margin: 0,
3089
+ fontSize: 12,
3090
+ color: C.warn,
3091
+ lineHeight: 1.6
3092
+ }
3093
+ }, "We couldn't find a match. Try using more accurate keywords or switch to", " ", /*#__PURE__*/React__default["default"].createElement("button", {
3094
+ onClick: () => onModeChange("ai"),
3095
+ style: {
3096
+ background: "none",
3097
+ border: "none",
3098
+ padding: 0,
3099
+ color: C.primary,
3100
+ fontWeight: 700,
3101
+ fontSize: 12,
3102
+ cursor: "pointer",
3103
+ textDecoration: "underline",
3104
+ fontFamily: FONT
3105
+ }
3106
+ }, "AI Suggest"), " ", "for better results."))), /*#__PURE__*/React__default["default"].createElement("div", {
3020
3107
  style: {
3021
3108
  display: "flex",
3022
3109
  flexDirection: "column",
@@ -3032,7 +3119,7 @@
3032
3119
  alignItems: "center",
3033
3120
  gap: 12,
3034
3121
  padding: "10px 14px",
3035
- border: "1px solid ".concat(C.border),
3122
+ border: `1px solid ${C.border}`,
3036
3123
  borderRadius: 8,
3037
3124
  cursor: "pointer",
3038
3125
  background: C.white,
@@ -3068,13 +3155,13 @@
3068
3155
  style: {
3069
3156
  flexShrink: 0,
3070
3157
  padding: "10px 18px",
3071
- borderTop: "1px solid ".concat(C.border),
3158
+ borderTop: `1px solid ${C.border}`,
3072
3159
  background: C.bg,
3073
3160
  fontSize: 11,
3074
3161
  color: "#aaa",
3075
3162
  textAlign: "center"
3076
3163
  }
3077
- }, "\u2695\uFE0F For reference only. Always verify codes with a certified medical coder."));
3164
+ }, ICON.medical, " For reference only. Always verify codes with a certified medical coder."));
3078
3165
  }
3079
3166
 
3080
3167
  // ─── FloatingButton ───────────────────────────────────────────────────────────
@@ -3097,7 +3184,7 @@
3097
3184
  padding: "10px 18px",
3098
3185
  borderRadius: 999,
3099
3186
  border: "none",
3100
- background: "linear-gradient(135deg, ".concat(C.primary, " 0%, ").concat(C.teal, " 100%)"),
3187
+ background: `linear-gradient(135deg, ${C.primary} 0%, ${C.teal} 100%)`,
3101
3188
  color: C.white,
3102
3189
  fontFamily: FONT,
3103
3190
  fontWeight: 700,
@@ -3114,17 +3201,20 @@
3114
3201
  e.currentTarget.style.transform = "translateY(0)";
3115
3202
  e.currentTarget.style.boxShadow = "0 4px 16px rgba(76,77,220,0.35)";
3116
3203
  }
3117
- }, /*#__PURE__*/React__default["default"].createElement("span", {
3204
+ }, /*#__PURE__*/React__default["default"].createElement("img", {
3205
+ src: IMG.icdIcon,
3206
+ alt: "ICD-10",
3118
3207
  style: {
3119
- fontSize: 18
3208
+ width: 22,
3209
+ height: 22,
3210
+ objectFit: "contain"
3120
3211
  }
3121
- }, "\uD83E\uDE7A"), "ICD-10 Assistant");
3212
+ }), "ICD-10 Assistant");
3122
3213
  }
3123
3214
 
3124
3215
  // ─── Panel ────────────────────────────────────────────────────────────────────
3125
3216
  // Defined OUTSIDE the main component so its DOM is never torn down on re-render.
3126
3217
  function Panel(_ref9) {
3127
- var _result$matches;
3128
3218
  let {
3129
3219
  panelRef,
3130
3220
  textareaRef,
@@ -3144,7 +3234,7 @@
3144
3234
  mode,
3145
3235
  onModeChange
3146
3236
  } = _ref9;
3147
- 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") || "";
3148
3238
  return /*#__PURE__*/React__default["default"].createElement("div", {
3149
3239
  style: {
3150
3240
  position: "fixed",
@@ -3163,9 +3253,14 @@
3163
3253
  animation: "icd-slide-in 0.2s ease"
3164
3254
  },
3165
3255
  ref: panelRef
3166
- }, /*#__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", {
3167
3262
  style: {
3168
- background: "linear-gradient(135deg, ".concat(C.primary, " 0%, ").concat(C.teal, " 100%)"),
3263
+ background: `linear-gradient(135deg, ${C.primary} 0%, ${C.teal} 100%)`,
3169
3264
  padding: "14px 18px",
3170
3265
  flexShrink: 0
3171
3266
  }
@@ -3181,11 +3276,15 @@
3181
3276
  alignItems: "center",
3182
3277
  gap: 10
3183
3278
  }
3184
- }, /*#__PURE__*/React__default["default"].createElement("span", {
3279
+ }, /*#__PURE__*/React__default["default"].createElement("img", {
3280
+ src: IMG.icdIcon,
3281
+ alt: "ICD-10",
3185
3282
  style: {
3186
- fontSize: 22
3283
+ width: 32,
3284
+ height: 32,
3285
+ objectFit: "contain"
3187
3286
  }
3188
- }, "\uD83E\uDE7A"), /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("div", {
3287
+ }), /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("div", {
3189
3288
  style: {
3190
3289
  color: C.white,
3191
3290
  fontWeight: 700,
@@ -3257,7 +3356,7 @@
3257
3356
  style: {
3258
3357
  width: "100%",
3259
3358
  padding: "10px 12px",
3260
- border: "1.5px solid ".concat(C.border),
3359
+ border: `1.5px solid ${C.border}`,
3261
3360
  borderRadius: 8,
3262
3361
  fontSize: 13,
3263
3362
  fontFamily: FONT,
@@ -3283,7 +3382,14 @@
3283
3382
  borderRadius: 3,
3284
3383
  fontFamily: "monospace"
3285
3384
  }
3286
- }, "\u2318 Enter"), " to submit")), /*#__PURE__*/React__default["default"].createElement("div", {
3385
+ }, "Enter"), " to submit \xB7 ", /*#__PURE__*/React__default["default"].createElement("kbd", {
3386
+ style: {
3387
+ background: "#f3f4f6",
3388
+ padding: "1px 5px",
3389
+ borderRadius: 3,
3390
+ fontFamily: "monospace"
3391
+ }
3392
+ }, "Shift+Enter"), " for new line")), /*#__PURE__*/React__default["default"].createElement("div", {
3287
3393
  style: {
3288
3394
  display: "flex",
3289
3395
  gap: 8
@@ -3298,7 +3404,7 @@
3298
3404
  justifyContent: "center",
3299
3405
  gap: 8,
3300
3406
  padding: "10px 16px",
3301
- 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%)`,
3302
3408
  color: C.white,
3303
3409
  border: "none",
3304
3410
  borderRadius: 8,
@@ -3308,12 +3414,12 @@
3308
3414
  cursor: !query.trim() || loading ? "not-allowed" : "pointer",
3309
3415
  transition: "background 0.15s"
3310
3416
  }
3311
- }, loading ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Spinner, null), "Searching codes\u2026") : "🔍 Find ICD-10 Codes"), (query || result) && /*#__PURE__*/React__default["default"].createElement("button", {
3417
+ }, loading ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Spinner, null), "Searching codes\u2026") : "Find ICD-10 Codes"), (query || result) && /*#__PURE__*/React__default["default"].createElement("button", {
3312
3418
  onClick: onClear,
3313
3419
  style: {
3314
3420
  padding: "10px 14px",
3315
3421
  background: C.bg,
3316
- border: "1px solid ".concat(C.border),
3422
+ border: `1px solid ${C.border}`,
3317
3423
  borderRadius: 8,
3318
3424
  fontSize: 13,
3319
3425
  fontWeight: 600,
@@ -3324,7 +3430,7 @@
3324
3430
  }, "Clear")), error && /*#__PURE__*/React__default["default"].createElement("div", {
3325
3431
  style: {
3326
3432
  background: C.errorLight,
3327
- border: "1px solid #fca5a5",
3433
+ border: `1px solid #fca5a5`,
3328
3434
  borderRadius: 8,
3329
3435
  padding: "10px 14px",
3330
3436
  fontSize: 13,
@@ -3408,14 +3514,14 @@
3408
3514
  style: {
3409
3515
  flexShrink: 0,
3410
3516
  padding: "12px 18px",
3411
- borderTop: "1px solid ".concat(C.border),
3517
+ borderTop: `1px solid ${C.border}`,
3412
3518
  background: C.bg,
3413
3519
  fontSize: 11,
3414
3520
  color: "#aaa",
3415
3521
  lineHeight: 1.5,
3416
3522
  textAlign: "center"
3417
3523
  }
3418
- }, "\u2695\uFE0F For reference only. Always verify codes with a certified medical coder. Not a substitute for clinical judgment or official coding guidelines."));
3524
+ }, ICON.medical, " For reference only. Always verify codes with a certified medical coder. Not a substitute for clinical judgment or official coding guidelines."));
3419
3525
  }
3420
3526
 
3421
3527
  // ─── Main Component ────────────────────────────────────────────────────────────
@@ -3437,10 +3543,7 @@
3437
3543
  // Focus textarea when panel opens
3438
3544
  React.useEffect(() => {
3439
3545
  if (open && textareaRef.current) {
3440
- setTimeout(() => {
3441
- var _textareaRef$current;
3442
- return (_textareaRef$current = textareaRef.current) === null || _textareaRef$current === void 0 ? void 0 : _textareaRef$current.focus();
3443
- }, 80);
3546
+ setTimeout(() => textareaRef.current?.focus(), 80);
3444
3547
  }
3445
3548
  }, [open]);
3446
3549
 
@@ -3477,24 +3580,22 @@
3477
3580
  }
3478
3581
  }, [query, loading]);
3479
3582
  const handleKeyDown = React.useCallback(e => {
3480
- if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
3583
+ if (e.key === "Enter" && !e.shiftKey) {
3481
3584
  e.preventDefault();
3482
3585
  handleSubmit();
3483
3586
  }
3484
3587
  }, [handleSubmit]);
3485
3588
  const handleClear = React.useCallback(() => {
3486
- var _textareaRef$current2;
3487
3589
  setQuery("");
3488
3590
  setResult(null);
3489
3591
  setError(null);
3490
- (_textareaRef$current2 = textareaRef.current) === null || _textareaRef$current2 === void 0 || _textareaRef$current2.focus();
3592
+ textareaRef.current?.focus();
3491
3593
  }, []);
3492
3594
  const handleHistoryClick = React.useCallback(q => {
3493
- var _textareaRef$current3;
3494
3595
  setQuery(q);
3495
3596
  setResult(null);
3496
3597
  setError(null);
3497
- (_textareaRef$current3 = textareaRef.current) === null || _textareaRef$current3 === void 0 || _textareaRef$current3.focus();
3598
+ textareaRef.current?.focus();
3498
3599
  }, []);
3499
3600
  const handleQueryChange = React.useCallback(e => setQuery(e.target.value), []);
3500
3601
  return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, !open && /*#__PURE__*/React__default["default"].createElement(FloatingButton, {
@@ -3529,14 +3630,14 @@
3529
3630
 
3530
3631
  // SDK for embedding appointment widget
3531
3632
  const BookingSDK = {
3532
- /**
3533
- * Show appointment widget with configuration
3534
- * @param {object} config - Configuration object
3535
- * @param {string} config.apiBaseUrl - Base URL for API
3536
- * @param {string} config.hospitalId - Hospital ID
3537
- * @param {number} config.doctorId - Doctor ID
3538
- * @param {string} config.joinCallUrl - Video call URL
3539
- * @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
3540
3641
  */
3541
3642
  showWidget: (config, onAction) => {
3542
3643
  if (!bookingWidgetInstance) {