medos-sdk 1.1.11 → 1.1.13

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.
Files changed (195) hide show
  1. package/dist/client/MedosClient.js +1 -1
  2. package/dist/components/appointment-booking/AppointmentCalender.js +10 -72
  3. package/dist/components/appointment-booking/appointment-modal-styles.d.ts +272 -0
  4. package/dist/components/appointment-booking/appointment-modal-styles.js +419 -0
  5. package/dist/components/appointment-booking/components/AppointmentConfirmationStep.d.ts +28 -0
  6. package/dist/components/appointment-booking/components/AppointmentConfirmationStep.js +107 -0
  7. package/dist/components/appointment-booking/components/AppointmentDateTimeModal.d.ts +18 -0
  8. package/dist/components/appointment-booking/components/AppointmentDateTimeModal.js +306 -0
  9. package/dist/components/appointment-booking/components/AppointmentSummaryStep.d.ts +12 -0
  10. package/dist/components/appointment-booking/components/AppointmentSummaryStep.js +194 -0
  11. package/dist/components/appointment-booking/components/BookingOptionStep.d.ts +14 -0
  12. package/dist/components/appointment-booking/components/BookingOptionStep.js +350 -0
  13. package/dist/components/appointment-booking/components/DoctorSelectModal.d.ts +14 -0
  14. package/dist/components/appointment-booking/components/DoctorSelectModal.js +213 -0
  15. package/dist/components/appointment-booking/components/PatientDetailsStep.d.ts +3 -0
  16. package/dist/components/appointment-booking/components/PatientDetailsStep.js +96 -0
  17. package/dist/components/appointment-booking/components/PatientSelectionStep.d.ts +12 -0
  18. package/dist/components/appointment-booking/components/PatientSelectionStep.js +254 -0
  19. package/dist/components/appointment-booking/components/PhoneVerificationStep.d.ts +3 -0
  20. package/dist/components/appointment-booking/components/PhoneVerificationStep.js +49 -0
  21. package/dist/components/appointment-booking/components/SuccessStep.d.ts +5 -0
  22. package/dist/components/appointment-booking/components/SuccessStep.js +9 -0
  23. package/dist/components/appointment-booking/components/index.d.ts +9 -0
  24. package/dist/components/appointment-booking/components/index.js +9 -0
  25. package/dist/components/appointment-booking/hooks/useAppointmentFlow.js +1 -0
  26. package/dist/components/appointment-booking/index.d.ts +2 -4
  27. package/dist/components/appointment-booking/index.js +2 -2
  28. package/dist/components/appointment-booking/types.d.ts +4 -0
  29. package/dist/components/constants/constant.d.ts +2 -0
  30. package/dist/components/constants/constant.js +15 -0
  31. package/dist/components/constants/index.d.ts +3 -0
  32. package/dist/components/constants/index.js +24 -0
  33. package/dist/components/constants/options.d.ts +13 -0
  34. package/dist/components/constants/options.js +35 -0
  35. package/dist/components/constants/validation.d.ts +6 -0
  36. package/dist/components/constants/validation.js +16 -0
  37. package/dist/components/enquiry-form/EnquiryForm.d.ts +7 -0
  38. package/dist/components/enquiry-form/EnquiryForm.js +238 -0
  39. package/dist/components/enquiry-form/components/ContactInformationStep.d.ts +13 -0
  40. package/dist/components/enquiry-form/components/ContactInformationStep.js +21 -0
  41. package/dist/components/enquiry-form/components/ContactPreferenceStep.d.ts +9 -0
  42. package/dist/components/enquiry-form/components/ContactPreferenceStep.js +20 -0
  43. package/dist/components/enquiry-form/components/InquiryDetailsStep.d.ts +10 -0
  44. package/dist/components/enquiry-form/components/InquiryDetailsStep.js +20 -0
  45. package/dist/components/enquiry-form/components/index.d.ts +3 -0
  46. package/dist/components/enquiry-form/components/index.js +3 -0
  47. package/dist/components/enquiry-form/index.d.ts +2 -0
  48. package/dist/components/enquiry-form/index.js +2 -0
  49. package/dist/components/index.d.ts +7 -0
  50. package/dist/components/index.js +7 -0
  51. package/dist/components/shared/icons/Check.d.ts +6 -0
  52. package/dist/components/shared/icons/Check.js +2 -0
  53. package/dist/components/shared/icons/ChevronDownIcon.d.ts +4 -0
  54. package/dist/components/shared/icons/ChevronDownIcon.js +2 -0
  55. package/dist/components/shared/icons/ChevronLeft.d.ts +3 -0
  56. package/dist/components/shared/icons/ChevronLeft.js +3 -0
  57. package/dist/components/shared/icons/ChevronRight.d.ts +3 -0
  58. package/dist/components/shared/icons/ChevronRight.js +3 -0
  59. package/dist/components/shared/icons/CloseIcon.d.ts +9 -0
  60. package/dist/components/shared/icons/CloseIcon.js +5 -0
  61. package/dist/components/shared/icons/ConfirmationCheck.d.ts +1 -0
  62. package/dist/components/shared/icons/ConfirmationCheck.js +9 -0
  63. package/dist/components/shared/icons/ConsultationType.d.ts +1 -0
  64. package/dist/components/shared/icons/ConsultationType.js +2 -0
  65. package/dist/components/shared/icons/Date&TimeIcon.d.ts +1 -0
  66. package/dist/components/shared/icons/Date&TimeIcon.js +2 -0
  67. package/dist/components/shared/icons/MapIcon.d.ts +1 -0
  68. package/dist/components/shared/icons/MapIcon.js +2 -0
  69. package/dist/components/shared/icons/MedosLogo.d.ts +3 -0
  70. package/dist/components/shared/icons/MedosLogo.js +3 -0
  71. package/dist/components/shared/icons/PaymentMethodIcon.d.ts +1 -0
  72. package/dist/components/shared/icons/PaymentMethodIcon.js +2 -0
  73. package/dist/components/shared/icons/SuccessIcon.d.ts +8 -0
  74. package/dist/components/shared/icons/SuccessIcon.js +14 -0
  75. package/dist/components/shared/icons/UserIcon.d.ts +1 -0
  76. package/dist/components/shared/icons/UserIcon.js +2 -0
  77. package/dist/components/shared/icons/index.d.ts +13 -0
  78. package/dist/components/shared/icons/index.js +13 -0
  79. package/dist/components/shared/index.d.ts +2 -0
  80. package/dist/components/shared/index.js +2 -0
  81. package/dist/components/shared/ui/Calendar.d.ts +5 -0
  82. package/dist/components/shared/ui/Calendar.js +167 -0
  83. package/dist/components/shared/ui/SelectDropdown.d.ts +41 -0
  84. package/dist/components/shared/ui/SelectDropdown.js +301 -0
  85. package/dist/components/shared/ui/index.d.ts +2 -0
  86. package/dist/components/shared/ui/index.js +2 -0
  87. package/dist/components/styles/appointment.d.ts +4 -0
  88. package/dist/components/styles/appointment.js +220 -0
  89. package/dist/components/styles/enquiry.d.ts +2 -0
  90. package/dist/components/styles/enquiry.js +3 -0
  91. package/dist/components/styles/index.d.ts +2 -0
  92. package/dist/components/styles/index.js +2 -0
  93. package/dist/components/styles/shared.d.ts +3 -0
  94. package/dist/components/styles/shared.js +78 -0
  95. package/dist/components/styles.d.ts +1 -6
  96. package/dist/components/styles.js +1 -298
  97. package/dist/components/theme-styles.js +18 -0
  98. package/dist/components/types/appointment.d.ts +42 -0
  99. package/dist/components/types/appointment.js +1 -0
  100. package/dist/components/types/common.d.ts +24 -0
  101. package/dist/components/types/common.js +1 -0
  102. package/dist/components/types/enquiry.d.ts +59 -0
  103. package/dist/components/types/enquiry.js +1 -0
  104. package/dist/components/types/index.d.ts +4 -0
  105. package/dist/components/types/index.js +4 -0
  106. package/dist/components/types.d.ts +1 -54
  107. package/dist/components/types.js +1 -38
  108. package/dist/components/utils/date.d.ts +4 -0
  109. package/dist/components/utils/date.js +65 -0
  110. package/dist/components/utils/formatting.d.ts +4 -0
  111. package/dist/components/utils/formatting.js +9 -0
  112. package/dist/components/utils/index.d.ts +3 -0
  113. package/dist/components/utils/index.js +3 -0
  114. package/dist/components/utils/validation.d.ts +4 -0
  115. package/dist/components/utils/validation.js +37 -0
  116. package/dist/components/utils.d.ts +1 -8
  117. package/dist/components/utils.js +1 -74
  118. package/dist/components/validation.d.ts +1 -4
  119. package/dist/components/validation.js +1 -48
  120. package/dist/constants/index.d.ts +1 -1
  121. package/dist/constants/index.js +1 -1
  122. package/dist/index.d.ts +2 -2
  123. package/dist/index.js +1 -1
  124. package/dist/react/index.d.ts +3 -3
  125. package/dist/react/index.js +1 -1
  126. package/dist/services/AppointmentService.js +26 -9
  127. package/dist/services/AuthService.js +1 -1
  128. package/dist/vanilla/AppointmentCalendarWidget.d.ts +8 -0
  129. package/dist/vanilla/AppointmentCalendarWidget.js +598 -20
  130. package/dist/vanilla/components/appointment-booking/appointment-modal-styles.d.ts +272 -0
  131. package/dist/vanilla/components/appointment-booking/components/AppointmentConfirmationStep.d.ts +28 -0
  132. package/dist/vanilla/components/appointment-booking/components/AppointmentDateTimeModal.d.ts +18 -0
  133. package/dist/vanilla/components/appointment-booking/components/AppointmentSummaryStep.d.ts +12 -0
  134. package/dist/vanilla/components/appointment-booking/components/BookingOptionStep.d.ts +14 -0
  135. package/dist/vanilla/components/appointment-booking/components/DoctorSelectModal.d.ts +14 -0
  136. package/dist/vanilla/components/appointment-booking/components/PatientDetailsStep.d.ts +3 -0
  137. package/dist/vanilla/components/appointment-booking/components/PatientSelectionStep.d.ts +12 -0
  138. package/dist/vanilla/components/appointment-booking/components/PhoneVerificationStep.d.ts +3 -0
  139. package/dist/vanilla/components/appointment-booking/components/SuccessStep.d.ts +5 -0
  140. package/dist/vanilla/components/appointment-booking/components/index.d.ts +9 -0
  141. package/dist/vanilla/components/appointment-booking/index.d.ts +2 -4
  142. package/dist/vanilla/components/appointment-booking/types.d.ts +4 -0
  143. package/dist/vanilla/components/constants/constant.d.ts +2 -0
  144. package/dist/vanilla/components/constants/index.d.ts +3 -0
  145. package/dist/vanilla/components/constants/options.d.ts +13 -0
  146. package/dist/vanilla/components/constants/validation.d.ts +6 -0
  147. package/dist/vanilla/components/enquiry-form/EnquiryForm.d.ts +7 -0
  148. package/dist/vanilla/components/enquiry-form/components/ContactInformationStep.d.ts +13 -0
  149. package/dist/vanilla/components/enquiry-form/components/ContactPreferenceStep.d.ts +9 -0
  150. package/dist/vanilla/components/enquiry-form/components/InquiryDetailsStep.d.ts +10 -0
  151. package/dist/vanilla/components/enquiry-form/components/index.d.ts +3 -0
  152. package/dist/vanilla/components/enquiry-form/index.d.ts +2 -0
  153. package/dist/vanilla/components/index.d.ts +7 -3
  154. package/dist/vanilla/components/shared/icons/Check.d.ts +6 -0
  155. package/dist/vanilla/components/shared/icons/ChevronDownIcon.d.ts +4 -0
  156. package/dist/vanilla/components/shared/icons/ChevronLeft.d.ts +3 -0
  157. package/dist/vanilla/components/shared/icons/ChevronRight.d.ts +3 -0
  158. package/dist/vanilla/components/shared/icons/CloseIcon.d.ts +9 -0
  159. package/dist/vanilla/components/shared/icons/ConfirmationCheck.d.ts +1 -0
  160. package/dist/vanilla/components/shared/icons/ConsultationType.d.ts +1 -0
  161. package/dist/vanilla/components/shared/icons/Date&TimeIcon.d.ts +1 -0
  162. package/dist/vanilla/components/shared/icons/MapIcon.d.ts +1 -0
  163. package/dist/vanilla/components/shared/icons/MedosLogo.d.ts +3 -0
  164. package/dist/vanilla/components/shared/icons/PaymentMethodIcon.d.ts +1 -0
  165. package/dist/vanilla/components/shared/icons/SuccessIcon.d.ts +8 -0
  166. package/dist/vanilla/components/shared/icons/UserIcon.d.ts +1 -0
  167. package/dist/vanilla/components/shared/icons/index.d.ts +13 -0
  168. package/dist/vanilla/components/shared/index.d.ts +2 -0
  169. package/dist/vanilla/components/shared/ui/Calendar.d.ts +5 -0
  170. package/dist/vanilla/components/shared/ui/SelectDropdown.d.ts +41 -0
  171. package/dist/vanilla/components/shared/ui/index.d.ts +2 -0
  172. package/dist/vanilla/components/styles/appointment.d.ts +4 -0
  173. package/dist/vanilla/components/styles/enquiry.d.ts +2 -0
  174. package/dist/vanilla/components/styles/index.d.ts +2 -0
  175. package/dist/vanilla/components/styles/shared.d.ts +3 -0
  176. package/dist/vanilla/components/styles.d.ts +1 -6
  177. package/dist/vanilla/components/types/appointment.d.ts +42 -0
  178. package/dist/vanilla/components/types/common.d.ts +24 -0
  179. package/dist/vanilla/components/types/enquiry.d.ts +59 -0
  180. package/dist/vanilla/components/types/index.d.ts +4 -0
  181. package/dist/vanilla/components/types.d.ts +1 -54
  182. package/dist/vanilla/components/utils/date.d.ts +4 -0
  183. package/dist/vanilla/components/utils/formatting.d.ts +4 -0
  184. package/dist/vanilla/components/utils/index.d.ts +3 -0
  185. package/dist/vanilla/components/utils/validation.d.ts +4 -0
  186. package/dist/vanilla/components/utils.d.ts +1 -8
  187. package/dist/vanilla/components/validation.d.ts +1 -4
  188. package/dist/vanilla/constants/index.d.ts +1 -1
  189. package/dist/vanilla/enquiry-widget.js +3277 -56
  190. package/dist/vanilla/index.d.ts +2 -2
  191. package/dist/vanilla/react/index.d.ts +3 -3
  192. package/dist/vanilla/vanilla/AppointmentCalendarWidget.d.ts +8 -0
  193. package/dist/vanilla/widget.css +214 -0
  194. package/dist/vanilla/widget.js +4047 -187
  195. package/package.json +2 -2
@@ -1,8 +1,9 @@
1
1
  import { AppointmentService, } from "../services/AppointmentService";
2
2
  import { PatientService } from "../services/PatientService";
3
3
  import { MedosClient } from "../client/MedosClient";
4
- import { INITIAL_STATE, COUNTRY_CODES, mapBloodGroupToApi, } from "../components/types";
5
- import { validatePhoneNumber, validateCountryCode, } from "../components/validation";
4
+ import { INITIAL_STATE, } from "../components/appointment-booking/types";
5
+ import { COUNTRY_CODES, GENDER_OPTIONS, BLOOD_GROUP_OPTIONS, mapBloodGroupToApi, } from "../components/constants/options";
6
+ import { validatePhoneNumber, validateCountryCode, validateDateOfBirth, validateBloodGroup, } from "../components/validation";
6
7
  import { formatDateToISO, parsePatientName } from "../components/utils";
7
8
  import { VanillaIcons } from "./components/VanillaIcons";
8
9
  import { VanillaSelect } from "./components/VanillaSelect";
@@ -207,17 +208,58 @@ class AppointmentCalendarWidget {
207
208
  return true;
208
209
  }
209
210
  updateSubmitButtonState() {
210
- const submitBtn = this.container.querySelector("#medos-btn-submit");
211
- if (submitBtn) {
212
- const canSubmit = this.state.patientName &&
213
- this.state.patientAddress &&
214
- this.state.patientCity &&
215
- this.state.patientState &&
216
- this.state.patientCountry &&
217
- this.state.patientZipcode &&
218
- this.state.patientAge &&
219
- this.state.otpVerified;
220
- submitBtn.disabled = !(canSubmit && !this.state.loading);
211
+ try {
212
+ const submitBtn = this.container.querySelector("#medos-btn-submit");
213
+ if (submitBtn) {
214
+ const canSubmit = this.state.patientName &&
215
+ this.state.patientAddress &&
216
+ this.state.patientCity &&
217
+ this.state.patientState &&
218
+ this.state.patientCountry &&
219
+ this.state.patientZipcode &&
220
+ this.state.patientAge &&
221
+ this.state.patientGender &&
222
+ this.state.otpVerified &&
223
+ (!(this.state.patientDob && this.state.patientDob.trim() !== "") ||
224
+ this.isValidDateOfBirth(this.state.patientDob)) &&
225
+ (!(this.state.bloodGroup && this.state.bloodGroup.trim() !== "") ||
226
+ this.isValidBloodGroup(this.state.bloodGroup));
227
+ submitBtn.disabled = !(canSubmit && !this.state.loading);
228
+ }
229
+ }
230
+ catch (error) {
231
+ console.error("Error updating submit button state:", error);
232
+ const submitBtn = this.container.querySelector("#medos-btn-submit");
233
+ if (submitBtn) {
234
+ submitBtn.disabled = true;
235
+ }
236
+ }
237
+ }
238
+ updatePatientDetailsButtonState() {
239
+ try {
240
+ const continueBtn = this.container.querySelector("#medos-btn-continue");
241
+ if (continueBtn) {
242
+ const isFormValid = this.state.patientName &&
243
+ this.state.patientAge &&
244
+ this.state.patientGender &&
245
+ this.state.patientAddress &&
246
+ this.state.patientCity &&
247
+ this.state.patientState &&
248
+ this.state.patientCountry &&
249
+ this.state.patientZipcode &&
250
+ (!(this.state.patientDob && this.state.patientDob.trim() !== "") ||
251
+ this.isValidDateOfBirth(this.state.patientDob)) &&
252
+ (!(this.state.bloodGroup && this.state.bloodGroup.trim() !== "") ||
253
+ this.isValidBloodGroup(this.state.bloodGroup));
254
+ continueBtn.disabled = !isFormValid;
255
+ }
256
+ }
257
+ catch (error) {
258
+ console.error("Error updating patient details button state:", error);
259
+ const continueBtn = this.container.querySelector("#medos-btn-continue");
260
+ if (continueBtn) {
261
+ continueBtn.disabled = true;
262
+ }
221
263
  }
222
264
  }
223
265
  async sendOtp() {
@@ -318,6 +360,9 @@ class AppointmentCalendarWidget {
318
360
  !this.state.selectedSlot ||
319
361
  !this.state.workspaceId ||
320
362
  !this.state.selectedAddress ||
363
+ !this.state.patientName ||
364
+ !this.state.patientAge ||
365
+ !this.state.patientGender ||
321
366
  !this.state.patientAddress ||
322
367
  !this.state.patientCity ||
323
368
  !this.state.patientState ||
@@ -332,6 +377,40 @@ class AppointmentCalendarWidget {
332
377
  this.setState({ error: "Please verify your phone number first." });
333
378
  return;
334
379
  }
380
+ if (this.state.patientDob && this.state.patientDob.trim() !== "") {
381
+ if (!this.isValidDateOfBirth(this.state.patientDob)) {
382
+ const dobValue = this.state.patientDob;
383
+ const today = new Date();
384
+ const inputDate = new Date(dobValue);
385
+ if (inputDate > today) {
386
+ this.displayFieldValidationError("dateOfBirth", "future");
387
+ }
388
+ else if (!/^\d{4}-\d{2}-\d{2}$/.test(dobValue)) {
389
+ this.displayFieldValidationError("dateOfBirth", "format");
390
+ }
391
+ else {
392
+ this.displayFieldValidationError("dateOfBirth", "invalid");
393
+ }
394
+ return;
395
+ }
396
+ }
397
+ if (this.state.bloodGroup && this.state.bloodGroup.trim() !== "") {
398
+ if (!this.isValidBloodGroup(this.state.bloodGroup)) {
399
+ this.displayFieldValidationError("bloodGroup", "invalid");
400
+ return;
401
+ }
402
+ try {
403
+ const mappedValue = this.safeMapBloodGroupToApi(this.state.bloodGroup);
404
+ if (mappedValue === "UNKNOWN" && this.state.bloodGroup !== "UNKNOWN") {
405
+ this.displayFieldValidationError("bloodGroup", "mapping");
406
+ return;
407
+ }
408
+ }
409
+ catch (error) {
410
+ this.displayFieldValidationError("bloodGroup", "mapping");
411
+ return;
412
+ }
413
+ }
335
414
  this.setState({ loading: true });
336
415
  this.render();
337
416
  try {
@@ -377,13 +456,12 @@ class AppointmentCalendarWidget {
377
456
  gender: this.state.patientGender
378
457
  ? this.state.patientGender.toUpperCase()
379
458
  : undefined,
380
- bloodGroup: this.state.bloodGroup
381
- ? mapBloodGroupToApi(this.state.bloodGroup)
382
- : mapBloodGroupToApi("UNKNOWN"),
459
+ dob: this.safeFormatDateOfBirth(this.state.patientDob),
460
+ bloodGroup: this.safeMapBloodGroupToApi(this.state.bloodGroup),
383
461
  },
384
462
  patientAddress: patientAddressPayload,
385
463
  });
386
- this.state.step = 5;
464
+ this.state.step = 7;
387
465
  this.options.onSuccess?.();
388
466
  }
389
467
  catch (e) {
@@ -449,7 +527,22 @@ class AppointmentCalendarWidget {
449
527
  this.render();
450
528
  return;
451
529
  }
452
- this.state.step = Math.min(6, this.state.step + 1);
530
+ if (this.state.step === 5) {
531
+ const isFormValid = this.state.patientName &&
532
+ this.state.patientAge &&
533
+ this.state.patientGender &&
534
+ this.state.patientAddress &&
535
+ this.state.patientCity &&
536
+ this.state.patientState &&
537
+ this.state.patientCountry &&
538
+ this.state.patientZipcode;
539
+ if (!isFormValid)
540
+ return;
541
+ this.state.step = 6;
542
+ this.render();
543
+ return;
544
+ }
545
+ this.state.step = Math.min(7, this.state.step + 1);
453
546
  this.render();
454
547
  }
455
548
  goBack() {
@@ -484,6 +577,11 @@ class AppointmentCalendarWidget {
484
577
  this.render();
485
578
  return;
486
579
  }
580
+ if (this.state.step === 6) {
581
+ this.state.step = 5;
582
+ this.render();
583
+ return;
584
+ }
487
585
  this.state.step = Math.max(0, this.state.step - 1);
488
586
  this.render();
489
587
  }
@@ -494,7 +592,25 @@ class AppointmentCalendarWidget {
494
592
  this.render();
495
593
  }
496
594
  setState(updates) {
497
- this.state = { ...this.state, ...updates };
595
+ try {
596
+ const safeUpdates = { ...updates };
597
+ if ("bloodGroup" in safeUpdates && safeUpdates.bloodGroup === undefined) {
598
+ safeUpdates.bloodGroup = "";
599
+ }
600
+ if ("patientDob" in safeUpdates && safeUpdates.patientDob === undefined) {
601
+ safeUpdates.patientDob = "";
602
+ }
603
+ this.state = { ...this.state, ...safeUpdates };
604
+ if (safeUpdates.bloodGroup !== undefined ||
605
+ safeUpdates.patientDob !== undefined) {
606
+ this.updatePatientDetailsButtonState();
607
+ this.updateSubmitButtonState();
608
+ }
609
+ }
610
+ catch (error) {
611
+ console.error("Error updating state:", error);
612
+ this.state = { ...this.state, ...updates };
613
+ }
498
614
  }
499
615
  render() {
500
616
  if (!this.mounted)
@@ -597,6 +713,61 @@ class AppointmentCalendarWidget {
597
713
  });
598
714
  }
599
715
  }
716
+ if (this.state.step === 5) {
717
+ const genderContainer = this.container.querySelector("#medos-gender-select-container");
718
+ if (genderContainer) {
719
+ const genderOptions = GENDER_OPTIONS.map((g) => ({
720
+ value: g.value,
721
+ label: g.label,
722
+ }));
723
+ this.genderSelect = new VanillaSelect(genderContainer, genderOptions, {
724
+ placeholder: "Select gender",
725
+ onValueChange: (value) => {
726
+ this.state.patientGender = value;
727
+ this.updatePatientDetailsButtonState();
728
+ },
729
+ });
730
+ if (this.state.patientGender) {
731
+ this.genderSelect.setValue(this.state.patientGender);
732
+ }
733
+ }
734
+ const bloodGroupContainer = this.container.querySelector("#medos-blood-group-select-container");
735
+ if (bloodGroupContainer) {
736
+ const bloodGroupOptions = BLOOD_GROUP_OPTIONS.map((bg) => ({
737
+ value: bg.value,
738
+ label: bg.label,
739
+ }));
740
+ this.bloodGroupSelect = new VanillaSelect(bloodGroupContainer, bloodGroupOptions, {
741
+ placeholder: "Select blood group (optional)",
742
+ onValueChange: (value) => {
743
+ this.setState({ error: null });
744
+ try {
745
+ if (value && value.trim() !== "") {
746
+ if (!this.isValidBloodGroup(value)) {
747
+ this.displayFieldValidationError("bloodGroup", "invalid");
748
+ return;
749
+ }
750
+ const mappedValue = this.safeMapBloodGroupToApi(value);
751
+ if (mappedValue === "UNKNOWN" && value !== "UNKNOWN") {
752
+ this.displayFieldValidationError("bloodGroup", "mapping");
753
+ return;
754
+ }
755
+ }
756
+ this.setState({ bloodGroup: value });
757
+ this.updatePatientDetailsButtonState();
758
+ this.updateSubmitButtonState();
759
+ }
760
+ catch (error) {
761
+ console.error("Blood group selection error:", error);
762
+ this.displayFieldValidationError("bloodGroup", "mapping");
763
+ }
764
+ },
765
+ });
766
+ if (this.state.bloodGroup) {
767
+ this.bloodGroupSelect.setValue(this.state.bloodGroup);
768
+ }
769
+ }
770
+ }
600
771
  }
601
772
  renderStep() {
602
773
  switch (this.state.step) {
@@ -613,8 +784,10 @@ class AppointmentCalendarWidget {
613
784
  case 4:
614
785
  return this.renderPatientSelectionStep();
615
786
  case 5:
616
- return this.renderAppointmentSummaryStep();
787
+ return this.renderPatientDetailsStep();
617
788
  case 6:
789
+ return this.renderAppointmentSummaryStep();
790
+ case 7:
618
791
  return this.renderSuccessStep();
619
792
  default:
620
793
  return "";
@@ -1109,6 +1282,203 @@ class AppointmentCalendarWidget {
1109
1282
  </div>
1110
1283
  `;
1111
1284
  }
1285
+ renderPatientDetailsStep() {
1286
+ const isFormValid = this.state.patientName &&
1287
+ this.state.patientAge &&
1288
+ this.state.patientGender &&
1289
+ this.state.patientAddress &&
1290
+ this.state.patientCity &&
1291
+ this.state.patientState &&
1292
+ this.state.patientCountry &&
1293
+ this.state.patientZipcode;
1294
+ return `
1295
+ <!-- Patient Information Section -->
1296
+ <div class="medos-section-card">
1297
+ <div class="medos-section-header">
1298
+ ${VanillaIcons.user(14)}
1299
+ <span class="medos-section-title">Patient Information</span>
1300
+ </div>
1301
+ <div class="medos-section-body">
1302
+ <div class="medos-form-row">
1303
+ <div class="medos-form-field">
1304
+ <label class="medos-form-label">
1305
+ First Name <span style="color: #EF4444;">*</span>
1306
+ </label>
1307
+ <input
1308
+ type="text"
1309
+ class="medos-appointment-input"
1310
+ id="medos-patient-first-name"
1311
+ placeholder="Jane"
1312
+ value="${this.escapeHtml(this.state.patientName.split(" ")[0] || "")}"
1313
+ />
1314
+ </div>
1315
+ <div class="medos-form-field">
1316
+ <label class="medos-form-label">
1317
+ Last Name <span style="color: #EF4444;">*</span>
1318
+ </label>
1319
+ <input
1320
+ type="text"
1321
+ class="medos-appointment-input"
1322
+ id="medos-patient-last-name"
1323
+ placeholder="Doe"
1324
+ value="${this.escapeHtml(this.state.patientName.split(" ").slice(1).join(" ") || "")}"
1325
+ />
1326
+ </div>
1327
+ </div>
1328
+
1329
+ <div class="medos-form-row">
1330
+ <div class="medos-form-field">
1331
+ <label class="medos-form-label">
1332
+ Age <span style="color: #EF4444;">*</span>
1333
+ </label>
1334
+ <input
1335
+ type="number"
1336
+ class="medos-appointment-input"
1337
+ id="medos-patient-age"
1338
+ placeholder="25"
1339
+ min="0"
1340
+ max="120"
1341
+ value="${this.escapeHtml(this.state.patientAge)}"
1342
+ />
1343
+ </div>
1344
+ <div class="medos-form-field">
1345
+ <label class="medos-form-label">Email</label>
1346
+ <input
1347
+ type="email"
1348
+ class="medos-appointment-input"
1349
+ id="medos-patient-email"
1350
+ placeholder="jane@example.com (optional)"
1351
+ value="${this.escapeHtml(this.state.patientEmail)}"
1352
+ />
1353
+ </div>
1354
+ </div>
1355
+
1356
+ <div class="medos-form-row">
1357
+ <div class="medos-form-field">
1358
+ <label class="medos-form-label">
1359
+ Gender <span style="color: #EF4444;">*</span>
1360
+ </label>
1361
+ <div id="medos-gender-select-container"></div>
1362
+ </div>
1363
+ <div class="medos-form-field">
1364
+ <label class="medos-form-label">Blood Group</label>
1365
+ <div id="medos-blood-group-select-container"></div>
1366
+ </div>
1367
+ </div>
1368
+
1369
+ <div class="medos-form-row">
1370
+ <div class="medos-form-field">
1371
+ <label class="medos-form-label">Date of Birth</label>
1372
+ <input
1373
+ type="date"
1374
+ class="medos-appointment-input"
1375
+ id="medos-patient-dob"
1376
+ value="${this.escapeHtml(this.state.patientDob)}"
1377
+ />
1378
+ ${this.state.patientDob &&
1379
+ this.state.patientDob.trim() !== "" &&
1380
+ !this.isValidDateOfBirth(this.state.patientDob)
1381
+ ? this.getDateOfBirthErrorMessage(this.state.patientDob)
1382
+ : ""}
1383
+ </div>
1384
+ </div>
1385
+ </div>
1386
+ </div>
1387
+
1388
+ <!-- Address Information Section -->
1389
+ <div class="medos-section-card">
1390
+ <div class="medos-section-header">
1391
+ ${VanillaIcons.mapPin(14)}
1392
+ <span class="medos-section-title">Address Information</span>
1393
+ </div>
1394
+ <div class="medos-section-body">
1395
+ <div class="medos-form-field">
1396
+ <label class="medos-form-label">
1397
+ Address <span style="color: #EF4444;">*</span>
1398
+ </label>
1399
+ <input
1400
+ type="text"
1401
+ class="medos-appointment-input"
1402
+ id="medos-patient-address"
1403
+ placeholder="123 Main Street"
1404
+ value="${this.escapeHtml(this.state.patientAddress)}"
1405
+ />
1406
+ </div>
1407
+
1408
+ <div class="medos-form-row">
1409
+ <div class="medos-form-field">
1410
+ <label class="medos-form-label">
1411
+ City <span style="color: #EF4444;">*</span>
1412
+ </label>
1413
+ <input
1414
+ type="text"
1415
+ class="medos-appointment-input"
1416
+ id="medos-patient-city"
1417
+ placeholder="New York"
1418
+ value="${this.escapeHtml(this.state.patientCity)}"
1419
+ />
1420
+ </div>
1421
+ <div class="medos-form-field">
1422
+ <label class="medos-form-label">
1423
+ State <span style="color: #EF4444;">*</span>
1424
+ </label>
1425
+ <input
1426
+ type="text"
1427
+ class="medos-appointment-input"
1428
+ id="medos-patient-state"
1429
+ placeholder="NY"
1430
+ value="${this.escapeHtml(this.state.patientState)}"
1431
+ />
1432
+ </div>
1433
+ </div>
1434
+
1435
+ <div class="medos-form-row">
1436
+ <div class="medos-form-field">
1437
+ <label class="medos-form-label">
1438
+ Country <span style="color: #EF4444;">*</span>
1439
+ </label>
1440
+ <input
1441
+ type="text"
1442
+ class="medos-appointment-input"
1443
+ id="medos-patient-country"
1444
+ placeholder="United States"
1445
+ value="${this.escapeHtml(this.state.patientCountry)}"
1446
+ />
1447
+ </div>
1448
+ <div class="medos-form-field">
1449
+ <label class="medos-form-label">
1450
+ Zipcode <span style="color: #EF4444;">*</span>
1451
+ </label>
1452
+ <input
1453
+ type="text"
1454
+ class="medos-appointment-input"
1455
+ id="medos-patient-zipcode"
1456
+ placeholder="10001"
1457
+ value="${this.escapeHtml(this.state.patientZipcode)}"
1458
+ />
1459
+ </div>
1460
+ </div>
1461
+
1462
+ <div class="medos-form-field" style="margin-top: 20px;">
1463
+ <label class="medos-form-label">Landmark</label>
1464
+ <input
1465
+ type="text"
1466
+ class="medos-appointment-input"
1467
+ id="medos-patient-landmark"
1468
+ placeholder="Near Central Park"
1469
+ value="${this.escapeHtml(this.state.patientLandmark)}"
1470
+ />
1471
+ </div>
1472
+ </div>
1473
+ </div>
1474
+
1475
+ <div class="medos-actions">
1476
+ <button class="medos-btn medos-btn-back" id="medos-btn-back">${VanillaIcons.arrowLeft(14)} Back</button>
1477
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
1478
+ <button class="medos-btn medos-btn-primary" id="medos-btn-continue" ${isFormValid ? "" : "disabled"}>Continue</button>
1479
+ </div>
1480
+ `;
1481
+ }
1112
1482
  renderAppointmentSummaryStep() {
1113
1483
  const selectedDoctor = this.doctors.find((d) => d.id === this.state.selectedDoctor);
1114
1484
  const selectedAddress = this.state.addresses.find((addr) => addr.id === this.state.selectedAddress);
@@ -1426,6 +1796,7 @@ class AppointmentCalendarWidget {
1426
1796
  const target = e.target;
1427
1797
  this.state.patientAge = target.value;
1428
1798
  this.updateSubmitButtonState();
1799
+ this.updatePatientDetailsButtonState();
1429
1800
  });
1430
1801
  }
1431
1802
  const patientEmailInput = this.container.querySelector("#medos-patient-email");
@@ -1442,6 +1813,7 @@ class AppointmentCalendarWidget {
1442
1813
  const target = e.target;
1443
1814
  this.state.patientAddress = target.value;
1444
1815
  this.updateSubmitButtonState();
1816
+ this.updatePatientDetailsButtonState();
1445
1817
  });
1446
1818
  }
1447
1819
  const patientCityInput = this.container.querySelector("#medos-patient-city");
@@ -1450,6 +1822,7 @@ class AppointmentCalendarWidget {
1450
1822
  const target = e.target;
1451
1823
  this.state.patientCity = target.value;
1452
1824
  this.updateSubmitButtonState();
1825
+ this.updatePatientDetailsButtonState();
1453
1826
  });
1454
1827
  }
1455
1828
  const patientStateInput = this.container.querySelector("#medos-patient-state");
@@ -1458,6 +1831,7 @@ class AppointmentCalendarWidget {
1458
1831
  const target = e.target;
1459
1832
  this.state.patientState = target.value;
1460
1833
  this.updateSubmitButtonState();
1834
+ this.updatePatientDetailsButtonState();
1461
1835
  });
1462
1836
  }
1463
1837
  const patientCountryInput = this.container.querySelector("#medos-patient-country");
@@ -1466,6 +1840,7 @@ class AppointmentCalendarWidget {
1466
1840
  const target = e.target;
1467
1841
  this.state.patientCountry = target.value;
1468
1842
  this.updateSubmitButtonState();
1843
+ this.updatePatientDetailsButtonState();
1469
1844
  });
1470
1845
  }
1471
1846
  const patientZipcodeInput = this.container.querySelector("#medos-patient-zipcode");
@@ -1474,6 +1849,7 @@ class AppointmentCalendarWidget {
1474
1849
  const target = e.target;
1475
1850
  this.state.patientZipcode = target.value;
1476
1851
  this.updateSubmitButtonState();
1852
+ this.updatePatientDetailsButtonState();
1477
1853
  });
1478
1854
  }
1479
1855
  const patientLandmarkInput = this.container.querySelector("#medos-patient-landmark");
@@ -1483,6 +1859,92 @@ class AppointmentCalendarWidget {
1483
1859
  this.state.patientLandmark = target.value;
1484
1860
  });
1485
1861
  }
1862
+ const patientFirstNameInput = this.container.querySelector("#medos-patient-first-name");
1863
+ if (patientFirstNameInput) {
1864
+ patientFirstNameInput.addEventListener("input", (e) => {
1865
+ const target = e.target;
1866
+ const lastName = this.state.patientName.split(" ").slice(1).join(" ") || "";
1867
+ this.state.patientName = `${target.value} ${lastName}`.trim();
1868
+ this.updatePatientDetailsButtonState();
1869
+ });
1870
+ }
1871
+ const patientLastNameInput = this.container.querySelector("#medos-patient-last-name");
1872
+ if (patientLastNameInput) {
1873
+ patientLastNameInput.addEventListener("input", (e) => {
1874
+ const target = e.target;
1875
+ const firstName = this.state.patientName.split(" ")[0] || "";
1876
+ this.state.patientName = `${firstName} ${target.value}`.trim();
1877
+ this.updatePatientDetailsButtonState();
1878
+ });
1879
+ }
1880
+ const patientDobInput = this.container.querySelector("#medos-patient-dob");
1881
+ if (patientDobInput) {
1882
+ patientDobInput.addEventListener("input", (e) => {
1883
+ const target = e.target;
1884
+ const dobValue = target.value;
1885
+ this.setState({ patientDob: dobValue });
1886
+ this.setState({ error: null });
1887
+ if (dobValue && dobValue.trim() !== "") {
1888
+ try {
1889
+ if (!this.isValidDateOfBirth(dobValue)) {
1890
+ target.classList.add("medos-input-error");
1891
+ const today = new Date();
1892
+ const inputDate = new Date(dobValue);
1893
+ if (inputDate > today) {
1894
+ target.title = "Date of birth cannot be in the future";
1895
+ }
1896
+ else if (!/^\d{4}-\d{2}-\d{2}$/.test(dobValue)) {
1897
+ target.title = "Please use YYYY-MM-DD format";
1898
+ }
1899
+ else {
1900
+ target.title = "Please enter a valid date";
1901
+ }
1902
+ }
1903
+ else {
1904
+ target.classList.remove("medos-input-error");
1905
+ target.title = "";
1906
+ }
1907
+ }
1908
+ catch (error) {
1909
+ console.warn("Date validation error:", error);
1910
+ target.classList.add("medos-input-error");
1911
+ target.title = "Date validation failed";
1912
+ }
1913
+ }
1914
+ else {
1915
+ target.classList.remove("medos-input-error");
1916
+ target.title = "";
1917
+ }
1918
+ this.updatePatientDetailsButtonState();
1919
+ this.updateSubmitButtonState();
1920
+ });
1921
+ patientDobInput.addEventListener("blur", (e) => {
1922
+ const target = e.target;
1923
+ const dobValue = target.value;
1924
+ if (dobValue && dobValue.trim() !== "") {
1925
+ try {
1926
+ if (!this.isValidDateOfBirth(dobValue)) {
1927
+ target.classList.add("medos-input-error");
1928
+ const today = new Date();
1929
+ const inputDate = new Date(dobValue);
1930
+ if (inputDate > today) {
1931
+ this.displayFieldValidationError("dateOfBirth", "future");
1932
+ }
1933
+ else if (!/^\d{4}-\d{2}-\d{2}$/.test(dobValue)) {
1934
+ this.displayFieldValidationError("dateOfBirth", "format");
1935
+ }
1936
+ else {
1937
+ this.displayFieldValidationError("dateOfBirth", "invalid");
1938
+ }
1939
+ }
1940
+ }
1941
+ catch (error) {
1942
+ console.warn("Date validation error on blur:", error);
1943
+ this.displayFieldValidationError("dateOfBirth", "invalid");
1944
+ }
1945
+ }
1946
+ });
1947
+ }
1486
1948
  const optionCards = this.container.querySelectorAll(".medos-option-card");
1487
1949
  optionCards.forEach((card) => {
1488
1950
  card.addEventListener("click", () => {
@@ -1687,6 +2149,122 @@ class AppointmentCalendarWidget {
1687
2149
  div.textContent = text;
1688
2150
  return div.innerHTML;
1689
2151
  }
2152
+ isValidDateOfBirth(dob) {
2153
+ try {
2154
+ return validateDateOfBirth(dob);
2155
+ }
2156
+ catch (error) {
2157
+ console.warn("Date of birth validation error:", error);
2158
+ return false;
2159
+ }
2160
+ }
2161
+ isValidBloodGroup(bloodGroup) {
2162
+ try {
2163
+ return validateBloodGroup(bloodGroup);
2164
+ }
2165
+ catch (error) {
2166
+ console.warn("Blood group validation error:", error);
2167
+ return false;
2168
+ }
2169
+ }
2170
+ safeMapBloodGroupToApi(bloodGroup) {
2171
+ try {
2172
+ if (!bloodGroup) {
2173
+ return "UNKNOWN";
2174
+ }
2175
+ if (!this.isValidBloodGroup(bloodGroup)) {
2176
+ console.warn(`Invalid blood group provided: ${bloodGroup}, using UNKNOWN`);
2177
+ return "UNKNOWN";
2178
+ }
2179
+ const mapped = mapBloodGroupToApi(bloodGroup);
2180
+ if (!mapped || mapped === "") {
2181
+ console.warn(`Blood group mapping failed for: ${bloodGroup}, using UNKNOWN`);
2182
+ return "UNKNOWN";
2183
+ }
2184
+ return mapped;
2185
+ }
2186
+ catch (error) {
2187
+ console.error("Blood group mapping error:", error);
2188
+ return "UNKNOWN";
2189
+ }
2190
+ }
2191
+ safeFormatDateOfBirth(dob) {
2192
+ try {
2193
+ if (!dob) {
2194
+ return undefined;
2195
+ }
2196
+ if (!this.isValidDateOfBirth(dob)) {
2197
+ console.warn(`Invalid date of birth provided: ${dob}, excluding from payload`);
2198
+ return undefined;
2199
+ }
2200
+ return dob;
2201
+ }
2202
+ catch (error) {
2203
+ console.error("Date of birth formatting error:", error);
2204
+ return undefined;
2205
+ }
2206
+ }
2207
+ getDateOfBirthErrorMessage(dobValue) {
2208
+ try {
2209
+ const today = new Date();
2210
+ const inputDate = new Date(dobValue);
2211
+ if (inputDate > today) {
2212
+ return '<div class="medos-validation-error">Date of birth cannot be in the future</div>';
2213
+ }
2214
+ else if (!/^\d{4}-\d{2}-\d{2}$/.test(dobValue)) {
2215
+ return '<div class="medos-validation-error">Please use YYYY-MM-DD format</div>';
2216
+ }
2217
+ else {
2218
+ return '<div class="medos-validation-error">Please enter a valid date of birth</div>';
2219
+ }
2220
+ }
2221
+ catch (error) {
2222
+ console.warn("Error generating date of birth error message:", error);
2223
+ return '<div class="medos-validation-error">Please enter a valid date of birth</div>';
2224
+ }
2225
+ }
2226
+ displayFieldValidationError(fieldName, errorType) {
2227
+ let errorMessage = "";
2228
+ switch (fieldName) {
2229
+ case "bloodGroup":
2230
+ switch (errorType) {
2231
+ case "invalid":
2232
+ errorMessage =
2233
+ "Please select a valid blood group from the dropdown or leave it empty.";
2234
+ break;
2235
+ case "mapping":
2236
+ errorMessage =
2237
+ "Blood group selection failed. Please try selecting again or leave it empty.";
2238
+ break;
2239
+ default:
2240
+ errorMessage =
2241
+ "Blood group validation failed. Please check your selection.";
2242
+ }
2243
+ break;
2244
+ case "dateOfBirth":
2245
+ switch (errorType) {
2246
+ case "invalid":
2247
+ errorMessage =
2248
+ "Please enter a valid date of birth in YYYY-MM-DD format or leave it empty.";
2249
+ break;
2250
+ case "future":
2251
+ errorMessage =
2252
+ "Date of birth cannot be in the future. Please enter a valid past date.";
2253
+ break;
2254
+ case "format":
2255
+ errorMessage =
2256
+ "Please enter date of birth in the correct format (YYYY-MM-DD).";
2257
+ break;
2258
+ default:
2259
+ errorMessage =
2260
+ "Date of birth validation failed. Please check the date format.";
2261
+ }
2262
+ break;
2263
+ default:
2264
+ errorMessage = `Validation failed for ${fieldName}. Please check your input.`;
2265
+ }
2266
+ this.setState({ error: errorMessage });
2267
+ }
1690
2268
  destroy() {
1691
2269
  this.mounted = false;
1692
2270
  this.container.innerHTML = "";