medos-sdk 1.1.10 → 1.1.11

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 (97) hide show
  1. package/dist/client/MedosClient.d.ts +1 -0
  2. package/dist/client/MedosClient.js +7 -0
  3. package/dist/components/AppointmentCalender.js +19 -22
  4. package/dist/components/AppointmentConfirmationStep.d.ts +1 -0
  5. package/dist/components/AppointmentConfirmationStep.js +34 -42
  6. package/dist/components/AppointmentDateTimeModal.d.ts +1 -0
  7. package/dist/components/AppointmentDateTimeModal.js +201 -168
  8. package/dist/components/AppointmentSummaryStep.d.ts +12 -0
  9. package/dist/components/AppointmentSummaryStep.js +168 -0
  10. package/dist/components/BookingOptionStep.d.ts +14 -0
  11. package/dist/components/BookingOptionStep.js +346 -0
  12. package/dist/components/ContactInformationStep.js +10 -4
  13. package/dist/components/ContactPreferenceStep.js +10 -1
  14. package/dist/components/DoctorSelectModal.js +105 -59
  15. package/dist/components/EnquiryForm.js +81 -69
  16. package/dist/components/Icons/CloseIcon.d.ts +9 -0
  17. package/dist/components/Icons/CloseIcon.js +5 -0
  18. package/dist/components/InquiryDetailsStep.js +5 -1
  19. package/dist/components/PatientDetailsStep.js +17 -12
  20. package/dist/components/PatientSelectionStep.d.ts +12 -0
  21. package/dist/components/PatientSelectionStep.js +254 -0
  22. package/dist/components/PhoneVerificationStep.js +1 -1
  23. package/dist/components/SuccessStep.js +1 -1
  24. package/dist/components/appointment-booking/AppointmentCalender.js +200 -60
  25. package/dist/components/appointment-booking/hooks/useAppointmentFlow.d.ts +0 -1
  26. package/dist/components/appointment-booking/hooks/useAppointmentFlow.js +110 -25
  27. package/dist/components/appointment-booking/hooks/useAppointmentState.js +32 -0
  28. package/dist/components/appointment-booking/hooks/useInitializeAddresses.js +0 -1
  29. package/dist/components/appointment-booking/types.d.ts +163 -0
  30. package/dist/components/appointment-booking/types.js +16 -0
  31. package/dist/components/appointment-modal-styles.d.ts +259 -0
  32. package/dist/components/appointment-modal-styles.js +395 -0
  33. package/dist/components/constant.d.ts +2 -0
  34. package/dist/components/constant.js +15 -0
  35. package/dist/components/custom-calendar.js +20 -11
  36. package/dist/components/styles.js +93 -52
  37. package/dist/components/theme-styles.d.ts +5 -4
  38. package/dist/components/theme-styles.js +221 -125
  39. package/dist/components/types.d.ts +3 -1
  40. package/dist/components/types.js +15 -0
  41. package/dist/components/utils.d.ts +3 -0
  42. package/dist/components/utils.js +59 -0
  43. package/dist/components/validation.d.ts +2 -0
  44. package/dist/components/validation.js +41 -0
  45. package/dist/core/theme/index.d.ts +1 -0
  46. package/dist/core/theme/index.js +1 -0
  47. package/dist/core/theme/responsive.d.ts +15 -0
  48. package/dist/core/theme/responsive.js +113 -0
  49. package/dist/core/theme/themes.js +16 -4
  50. package/dist/core/theme/types.d.ts +8 -0
  51. package/dist/index.d.ts +2 -0
  52. package/dist/index.js +1 -0
  53. package/dist/react/ThemeProvider.d.ts +2 -1
  54. package/dist/react/ThemeProvider.js +49 -10
  55. package/dist/services/AppointmentService.d.ts +80 -2
  56. package/dist/services/AppointmentService.js +114 -5
  57. package/dist/services/WorkspaceService.d.ts +58 -3
  58. package/dist/services/WorkspaceService.js +10 -1
  59. package/dist/vanilla/AppointmentCalendarWidget.d.ts +9 -7
  60. package/dist/vanilla/AppointmentCalendarWidget.js +820 -377
  61. package/dist/vanilla/EnquiryFormWidget.d.ts +1 -0
  62. package/dist/vanilla/EnquiryFormWidget.js +25 -43
  63. package/dist/vanilla/client/MedosClient.d.ts +1 -0
  64. package/dist/vanilla/components/AppointmentConfirmationStep.d.ts +1 -0
  65. package/dist/vanilla/components/AppointmentDateTimeModal.d.ts +1 -0
  66. package/dist/vanilla/components/AppointmentSummaryStep.d.ts +12 -0
  67. package/dist/vanilla/components/BookingOptionStep.d.ts +14 -0
  68. package/dist/vanilla/components/Icons/CloseIcon.d.ts +9 -0
  69. package/dist/vanilla/components/PatientSelectionStep.d.ts +12 -0
  70. package/dist/vanilla/components/VanillaCalendar.js +33 -18
  71. package/dist/vanilla/components/VanillaIcons.d.ts +5 -0
  72. package/dist/vanilla/components/VanillaIcons.js +92 -0
  73. package/dist/vanilla/components/VanillaSelect.d.ts +3 -0
  74. package/dist/vanilla/components/VanillaSelect.js +93 -5
  75. package/dist/vanilla/components/appointment-booking/hooks/useAppointmentFlow.d.ts +0 -1
  76. package/dist/vanilla/components/appointment-booking/types.d.ts +163 -0
  77. package/dist/vanilla/components/appointment-modal-styles.d.ts +259 -0
  78. package/dist/vanilla/components/constant.d.ts +2 -0
  79. package/dist/vanilla/components/theme-styles.d.ts +5 -4
  80. package/dist/vanilla/components/types.d.ts +3 -1
  81. package/dist/vanilla/components/utils.d.ts +3 -0
  82. package/dist/vanilla/components/validation.d.ts +2 -0
  83. package/dist/vanilla/core/theme/index.d.ts +1 -0
  84. package/dist/vanilla/core/theme/responsive.d.ts +15 -0
  85. package/dist/vanilla/core/theme/types.d.ts +8 -0
  86. package/dist/vanilla/enquiry-widget.js +373 -52
  87. package/dist/vanilla/index.d.ts +2 -0
  88. package/dist/vanilla/react/ThemeProvider.d.ts +2 -1
  89. package/dist/vanilla/services/AppointmentService.d.ts +80 -2
  90. package/dist/vanilla/services/WorkspaceService.d.ts +58 -3
  91. package/dist/vanilla/vanilla/AppointmentCalendarWidget.d.ts +9 -7
  92. package/dist/vanilla/vanilla/EnquiryFormWidget.d.ts +1 -0
  93. package/dist/vanilla/vanilla/components/VanillaIcons.d.ts +5 -0
  94. package/dist/vanilla/vanilla/components/VanillaSelect.d.ts +3 -0
  95. package/dist/vanilla/widget.css +833 -207
  96. package/dist/vanilla/widget.js +6444 -5676
  97. package/package.json +1 -1
@@ -1,7 +1,7 @@
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, GENDER_OPTIONS, BLOOD_GROUP_OPTIONS, } from "../components/types";
4
+ import { INITIAL_STATE, COUNTRY_CODES, mapBloodGroupToApi, } from "../components/types";
5
5
  import { validatePhoneNumber, validateCountryCode, } from "../components/validation";
6
6
  import { formatDateToISO, parsePatientName } from "../components/utils";
7
7
  import { VanillaIcons } from "./components/VanillaIcons";
@@ -215,7 +215,6 @@ class AppointmentCalendarWidget {
215
215
  this.state.patientState &&
216
216
  this.state.patientCountry &&
217
217
  this.state.patientZipcode &&
218
- this.state.patientEmail &&
219
218
  this.state.patientAge &&
220
219
  this.state.otpVerified;
221
220
  submitBtn.disabled = !(canSubmit && !this.state.loading);
@@ -359,11 +358,11 @@ class AppointmentCalendarWidget {
359
358
  workspaceId: this.state.workspaceId,
360
359
  workspaceAddressId: this.state.selectedAddress,
361
360
  doctorId: this.state.selectedDoctor,
362
- mode: "OFFLINE",
361
+ mode: this.state.consultationMode || "OFFLINE",
363
362
  appointmentDate,
364
363
  fromDateTimeTs,
365
364
  toDateTimeTs,
366
- consultationCharge: this.state.consultationCharge || "0",
365
+ consultationCharge: this.state.consultationMode === "ONLINE" ? "500" : "300",
367
366
  type: "CONSULTATION",
368
367
  source: "SDK_POWERED_WEBSITE",
369
368
  patientPayload: {
@@ -378,6 +377,9 @@ class AppointmentCalendarWidget {
378
377
  gender: this.state.patientGender
379
378
  ? this.state.patientGender.toUpperCase()
380
379
  : undefined,
380
+ bloodGroup: this.state.bloodGroup
381
+ ? mapBloodGroupToApi(this.state.bloodGroup)
382
+ : mapBloodGroupToApi("UNKNOWN"),
381
383
  },
382
384
  patientAddress: patientAddressPayload,
383
385
  });
@@ -396,34 +398,92 @@ class AppointmentCalendarWidget {
396
398
  }
397
399
  goToNext() {
398
400
  if (this.state.step === 0) {
401
+ if (!this.state.otpVerified)
402
+ return;
403
+ this.state.step = 1;
404
+ this.render();
405
+ return;
406
+ }
407
+ if (this.state.step === 1) {
408
+ if (!this.state.bookingOptionType)
409
+ return;
410
+ if (this.state.showPackageExplorer) {
411
+ if (this.state.selectedNewPackage) {
412
+ this.state.showPackageExplorer = false;
413
+ this.state.step = 2;
414
+ this.render();
415
+ }
416
+ return;
417
+ }
418
+ this.state.step = 2;
419
+ this.render();
420
+ return;
421
+ }
422
+ if (this.state.step === 2) {
399
423
  if (this.state.addresses.length > 1 && !this.state.selectedAddress)
400
424
  return;
401
425
  if (this.doctors.length > 1 && !this.state.selectedDoctor)
402
426
  return;
427
+ this.state.step = 3;
428
+ const dateStr = formatDateToISO(this.state.selectedDate);
429
+ if (dateStr) {
430
+ this.loadSlots();
431
+ }
432
+ else {
433
+ this.render();
434
+ }
435
+ return;
436
+ }
437
+ if (this.state.step === 3) {
438
+ const dateStr = formatDateToISO(this.state.selectedDate);
439
+ if (!dateStr || !this.state.selectedSlot)
440
+ return;
441
+ this.state.step = 4;
442
+ this.render();
443
+ return;
444
+ }
445
+ if (this.state.step === 4) {
446
+ if (!this.state.selectedPatient)
447
+ return;
448
+ this.state.step = 5;
449
+ this.render();
450
+ return;
451
+ }
452
+ this.state.step = Math.min(6, this.state.step + 1);
453
+ this.render();
454
+ }
455
+ goBack() {
456
+ if (this.state.step === 1) {
457
+ if (this.state.showPackageExplorer) {
458
+ this.state.showPackageExplorer = false;
459
+ this.state.selectedNewPackage = null;
460
+ this.render();
461
+ return;
462
+ }
463
+ this.state.step = 0;
464
+ this.render();
465
+ return;
466
+ }
467
+ if (this.state.step === 2) {
403
468
  this.state.step = 1;
404
469
  this.render();
405
470
  return;
406
471
  }
407
- const dateStr = formatDateToISO(this.state.selectedDate);
408
- if (this.state.step === 1 && dateStr) {
472
+ if (this.state.step === 3) {
409
473
  this.state.step = 2;
410
- this.loadSlots();
474
+ this.render();
411
475
  return;
412
476
  }
413
- if (this.state.step === 2 && this.state.selectedSlot) {
477
+ if (this.state.step === 4) {
414
478
  this.state.step = 3;
415
479
  this.render();
416
480
  return;
417
481
  }
418
- if (this.state.step === 3 && this.state.otpVerified) {
482
+ if (this.state.step === 5) {
419
483
  this.state.step = 4;
420
484
  this.render();
421
485
  return;
422
486
  }
423
- this.state.step = Math.min(5, this.state.step + 1);
424
- this.render();
425
- }
426
- goBack() {
427
487
  this.state.step = Math.max(0, this.state.step - 1);
428
488
  this.render();
429
489
  }
@@ -444,13 +504,6 @@ class AppointmentCalendarWidget {
444
504
  <div class="medos-appointment-card">
445
505
  <div class="medos-appointment-header">
446
506
  <h2 class="medos-appointment-title">Book Appointment</h2>
447
- <div class="medos-appointment-stepper">
448
- <div class="medos-appointment-step-pill ${this.state.step === 0 ? "active" : ""}">1 Address</div>
449
- <div class="medos-appointment-step-pill ${this.state.step === 1 ? "active" : ""}">2 Date</div>
450
- <div class="medos-appointment-step-pill ${this.state.step === 2 ? "active" : ""}">3 Slot</div>
451
- <div class="medos-appointment-step-pill ${this.state.step === 3 ? "active" : ""}">4 Phone</div>
452
- <div class="medos-appointment-step-pill ${this.state.step === 4 ? "active" : ""}">5 Details</div>
453
- </div>
454
507
  </div>
455
508
 
456
509
  ${this.state.loading
@@ -469,6 +522,30 @@ class AppointmentCalendarWidget {
469
522
  }
470
523
  initializeCustomComponents() {
471
524
  if (this.state.step === 0) {
525
+ const countryCodeContainer = this.container.querySelector("#medos-country-code-container");
526
+ if (countryCodeContainer) {
527
+ const countryOptions = COUNTRY_CODES.map((c) => ({
528
+ value: c.code,
529
+ label: c.label,
530
+ }));
531
+ this.countryCodeSelect = new VanillaSelect(countryCodeContainer, countryOptions, {
532
+ placeholder: "Country",
533
+ onValueChange: (value) => {
534
+ this.state.countryCode = value;
535
+ const sendOtpBtn = this.container.querySelector("#medos-btn-send-otp");
536
+ if (sendOtpBtn) {
537
+ const canSendOtp = this.state.countryCode &&
538
+ this.state.patientPhone.length >= 10;
539
+ sendOtpBtn.disabled = !canSendOtp;
540
+ }
541
+ },
542
+ });
543
+ if (this.state.countryCode) {
544
+ this.countryCodeSelect.setValue(this.state.countryCode);
545
+ }
546
+ }
547
+ }
548
+ if (this.state.step === 2 && !this.state.showPackageExplorer) {
472
549
  const addressContainer = this.container.querySelector("#medos-address-select-container");
473
550
  if (addressContainer && this.state.addresses.length > 0) {
474
551
  const addressOptions = this.state.addresses.map((a) => ({
@@ -496,7 +573,7 @@ class AppointmentCalendarWidget {
496
573
  onValueChange: (value) => {
497
574
  this.state.selectedDoctor = Number(value) || null;
498
575
  const selectedDoc = this.doctors.find((d) => d.id === this.state.selectedDoctor);
499
- if (selectedDoc && selectedDoc.consultationCharge) {
576
+ if (selectedDoc?.consultationCharge) {
500
577
  this.state.consultationCharge = selectedDoc.consultationCharge;
501
578
  }
502
579
  this.render();
@@ -507,7 +584,7 @@ class AppointmentCalendarWidget {
507
584
  }
508
585
  }
509
586
  }
510
- if (this.state.step === 1) {
587
+ if (this.state.step === 3) {
511
588
  const calendarContainer = this.container.querySelector("#medos-calendar-container");
512
589
  if (calendarContainer) {
513
590
  this.calendar = new VanillaCalendar(calendarContainer, {
@@ -515,82 +592,254 @@ class AppointmentCalendarWidget {
515
592
  pastDisabled: true,
516
593
  onSelect: (date) => {
517
594
  this.state.selectedDate = date;
518
- this.render();
519
- },
520
- });
521
- }
522
- }
523
- if (this.state.step === 3) {
524
- const countryCodeContainer = this.container.querySelector("#medos-country-code-container");
525
- if (countryCodeContainer) {
526
- const countryOptions = COUNTRY_CODES.map((c) => ({
527
- value: c.code,
528
- label: c.label,
529
- }));
530
- this.countryCodeSelect = new VanillaSelect(countryCodeContainer, countryOptions, {
531
- placeholder: "Country",
532
- onValueChange: (value) => {
533
- this.state.countryCode = value;
534
- const sendOtpBtn = this.container.querySelector("#medos-btn-send-otp");
535
- if (sendOtpBtn) {
536
- const canSendOtp = this.state.countryCode &&
537
- this.state.patientPhone.length >= 10;
538
- sendOtpBtn.disabled = !canSendOtp;
539
- }
540
- },
541
- });
542
- if (this.state.countryCode) {
543
- this.countryCodeSelect.setValue(this.state.countryCode);
544
- }
545
- }
546
- }
547
- if (this.state.step === 4) {
548
- const genderContainer = this.container.querySelector("#medos-gender-container");
549
- if (genderContainer) {
550
- this.genderSelect = new VanillaSelect(genderContainer, GENDER_OPTIONS, {
551
- placeholder: "Select gender",
552
- onValueChange: (value) => {
553
- this.state.patientGender = value;
554
- this.updateSubmitButtonState();
555
- },
556
- });
557
- if (this.state.patientGender) {
558
- this.genderSelect.setValue(this.state.patientGender);
559
- }
560
- }
561
- const bloodGroupContainer = this.container.querySelector("#medos-blood-group-container");
562
- if (bloodGroupContainer) {
563
- this.bloodGroupSelect = new VanillaSelect(bloodGroupContainer, BLOOD_GROUP_OPTIONS, {
564
- placeholder: "Select blood group (optional)",
565
- onValueChange: (value) => {
566
- this.state.bloodGroup = value;
595
+ this.loadSlots();
567
596
  },
568
597
  });
569
- if (this.state.bloodGroup) {
570
- this.bloodGroupSelect.setValue(this.state.bloodGroup);
571
- }
572
598
  }
573
599
  }
574
600
  }
575
601
  renderStep() {
576
602
  switch (this.state.step) {
577
603
  case 0:
578
- return this.renderStep0();
604
+ return this.renderPhoneVerificationStep();
579
605
  case 1:
580
- return this.renderStep1();
606
+ return this.renderBookingOptionStep();
581
607
  case 2:
582
- return this.renderStep2();
608
+ return this.state.showPackageExplorer
609
+ ? this.renderPackageExplorerStep()
610
+ : this.renderLocationDoctorStep();
583
611
  case 3:
584
- return this.renderStep3();
612
+ return this.renderNewAppointmentStep();
585
613
  case 4:
586
- return this.renderStep4();
614
+ return this.renderPatientSelectionStep();
587
615
  case 5:
588
- return this.renderStep5();
616
+ return this.renderAppointmentSummaryStep();
617
+ case 6:
618
+ return this.renderSuccessStep();
589
619
  default:
590
620
  return "";
591
621
  }
592
622
  }
593
- renderStep0() {
623
+ renderPhoneVerificationStep() {
624
+ const countryCodeValid = this.state.countryCode && validateCountryCode(this.state.countryCode);
625
+ const phoneValid = this.state.patientPhone && validatePhoneNumber(this.state.patientPhone);
626
+ const canSendOtp = countryCodeValid && phoneValid && !this.state.otpSending;
627
+ if (!this.state.otpSent) {
628
+ return `
629
+ <div class="medos-section-card">
630
+ <div class="medos-section-header">
631
+ ${VanillaIcons.phone(14)}
632
+ <span class="medos-section-title">Search Patient</span>
633
+ </div>
634
+ <div class="medos-section-body">
635
+ <p class="medos-section-description">Enter Phone Number</p>
636
+ <div class="medos-phone-input-row">
637
+ <div class="medos-country-code-wrapper">
638
+ <div id="medos-country-code-container"></div>
639
+ </div>
640
+ <div class="medos-phone-wrapper">
641
+ <input
642
+ type="tel"
643
+ class="medos-input"
644
+ id="medos-phone"
645
+ placeholder="XXXXXXXXXX"
646
+ value="${this.escapeHtml(this.state.patientPhone)}"
647
+ maxlength="15"
648
+ />
649
+ </div>
650
+ </div>
651
+ ${this.state.patientPhone && !phoneValid
652
+ ? '<div class="medos-validation-error">Phone number should be 7-15 digits</div>'
653
+ : ""}
654
+ </div>
655
+ </div>
656
+ <div class="medos-actions">
657
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
658
+ <button class="medos-btn medos-btn-primary" id="medos-btn-send-otp" ${canSendOtp ? "" : "disabled"}>${this.state.otpSending ? "Sending..." : "Continue"}</button>
659
+ </div>
660
+ `;
661
+ }
662
+ if (this.state.otpVerified) {
663
+ return `
664
+ <div class="medos-section-card">
665
+ <div class="medos-section-header">
666
+ ${VanillaIcons.phone(14)}
667
+ <span class="medos-section-title">Search Patient</span>
668
+ </div>
669
+ <div class="medos-section-body">
670
+ <div class="medos-verified-badge">
671
+ ${VanillaIcons.successBadge(20)}
672
+ <span>Phone verified successfully</span>
673
+ </div>
674
+ <div class="medos-verified-number">${this.escapeHtml(this.state.countryCode)} ${this.escapeHtml(this.state.patientPhone)}</div>
675
+ </div>
676
+ </div>
677
+ <div class="medos-actions">
678
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
679
+ <button class="medos-btn medos-btn-primary" id="medos-btn-next">Continue</button>
680
+ </div>
681
+ `;
682
+ }
683
+ return `
684
+ <div class="medos-section-card">
685
+ <div class="medos-section-header">
686
+ ${VanillaIcons.phone(14)}
687
+ <span class="medos-section-title">Enter OTP</span>
688
+ </div>
689
+ <div class="medos-section-body">
690
+ <p class="medos-section-description">Enter the 6-digit code sent to ${this.escapeHtml(this.state.countryCode)} ${this.escapeHtml(this.state.patientPhone)}</p>
691
+ <div class="medos-otp-input-wrapper">
692
+ <input
693
+ type="text"
694
+ class="medos-input medos-otp-input"
695
+ id="medos-otp"
696
+ placeholder="Enter 6-digit OTP"
697
+ value="${this.escapeHtml(this.state.otpCode)}"
698
+ maxlength="6"
699
+ />
700
+ </div>
701
+ <button class="medos-link-btn" id="medos-btn-change-number">Change phone number</button>
702
+ </div>
703
+ </div>
704
+ <div class="medos-actions">
705
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-resend-otp">Resend OTP</button>
706
+ <button class="medos-btn medos-btn-primary" id="medos-btn-verify-otp" ${this.state.otpCode.length === 6 && !this.state.otpVerifying
707
+ ? ""
708
+ : "disabled"}>${this.state.otpVerifying ? "Verifying..." : "Verify OTP"}</button>
709
+ </div>
710
+ `;
711
+ }
712
+ renderBookingOptionStep() {
713
+ const hasActivePacks = this.state.userSessionPacks.length > 0;
714
+ const activePack = this.state.userSessionPacks.find((p) => p.remainingSessions > 0);
715
+ return `
716
+ <div class="medos-section-card">
717
+ <div class="medos-section-header">
718
+ ${VanillaIcons.calendar(14)}
719
+ <span class="medos-section-title">Choose Booking Option</span>
720
+ </div>
721
+ <div class="medos-section-body">
722
+ <p class="medos-section-description">Select a package to explore on offer</p>
723
+
724
+ ${hasActivePacks && activePack
725
+ ? `
726
+ <div class="medos-active-session-packs">
727
+ <label class="medos-form-label">YOUR ACTIVE SESSION PACKS</label>
728
+ <div class="medos-session-pack-card ${this.state.bookingOptionType === "session-pack"
729
+ ? "selected"
730
+ : ""}" data-pack-id="${activePack.id}">
731
+ <div class="medos-pack-header">
732
+ <span class="medos-pack-name">${this.escapeHtml(activePack.name)}</span>
733
+ <span class="medos-pack-badge">${activePack.remainingSessions} sessions</span>
734
+ </div>
735
+ <div class="medos-pack-details">
736
+ ${activePack.remainingSessions} of ${activePack.totalSessions} sessions • <a href="#" class="medos-link">view details</a>
737
+ </div>
738
+ </div>
739
+ </div>
740
+ `
741
+ : ""}
742
+
743
+ <div class="medos-other-options">
744
+ <label class="medos-form-label">OTHER OPTIONS</label>
745
+
746
+ <div class="medos-option-cards">
747
+ <div class="medos-option-card ${this.state.bookingOptionType === "new-appointment"
748
+ ? "selected"
749
+ : ""}" data-option="new-appointment">
750
+ <div class="medos-option-icon">${VanillaIcons.calendar(24)}</div>
751
+ <div class="medos-option-content">
752
+ <span class="medos-option-title">Standard Consultation</span>
753
+ <span class="medos-option-subtitle">Pay per appointment</span>
754
+ </div>
755
+ </div>
756
+
757
+ <div class="medos-option-card ${this.state.bookingOptionType === "explore-packages"
758
+ ? "selected"
759
+ : ""}" data-option="explore-packages">
760
+ <div class="medos-option-icon">${VanillaIcons.giftBox(24)}</div>
761
+ <div class="medos-option-content">
762
+ <span class="medos-option-title">Session Packs</span>
763
+ <span class="medos-option-subtitle">Explore packs with discounts and offers</span>
764
+ </div>
765
+ </div>
766
+ </div>
767
+ </div>
768
+ </div>
769
+ </div>
770
+ <div class="medos-actions">
771
+ <button class="medos-btn medos-btn-back" id="medos-btn-back">${VanillaIcons.arrowLeft(14)} Back</button>
772
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
773
+ <button class="medos-btn medos-btn-primary" id="medos-btn-continue">Continue</button>
774
+ </div>
775
+ `;
776
+ }
777
+ renderPackageExplorerStep() {
778
+ const packages = this.state.availablePackages.length > 0
779
+ ? this.state.availablePackages
780
+ : [
781
+ {
782
+ id: 1,
783
+ name: "Silver Package",
784
+ description: "• 3 consultations (In clinic & Online appointments)\n• Can redeem for 6 months after\n purchase",
785
+ totalSessions: 3,
786
+ price: 5000,
787
+ validityDays: 180,
788
+ applicableOnline: true,
789
+ applicableOffline: true,
790
+ },
791
+ {
792
+ id: 2,
793
+ name: "Gold Package",
794
+ description: "• 5 consultations (In clinic & Online appointments)\n• Can redeem for 12 months after\n purchase",
795
+ totalSessions: 5,
796
+ price: 8000,
797
+ validityDays: 365,
798
+ applicableOnline: true,
799
+ applicableOffline: true,
800
+ },
801
+ ];
802
+ return `
803
+ <div class="medos-section-card">
804
+ <div class="medos-section-header">
805
+ ${VanillaIcons.giftBox(14)}
806
+ <span class="medos-section-title">Explore Session Packs</span>
807
+ </div>
808
+ <div class="medos-section-body">
809
+ <p class="medos-section-description">Select a package to explore on offer</p>
810
+
811
+ <div class="medos-available-packages">
812
+ <label class="medos-form-label">AVAILABLE PACKAGES</label>
813
+
814
+ ${packages
815
+ .map((pkg, index) => `
816
+ <div class="medos-package-card ${this.state.selectedNewPackage?.id === pkg.id ? "selected" : ""}" data-package-id="${pkg.id}">
817
+ <div class="medos-package-radio">
818
+ <input type="radio" name="package" value="${pkg.id}" ${this.state.selectedNewPackage?.id === pkg.id ? "checked" : ""} />
819
+ </div>
820
+ <div class="medos-package-content">
821
+ <div class="medos-package-name">${this.escapeHtml(pkg.name)}</div>
822
+ <div class="medos-package-description">${this.escapeHtml(pkg.description || "").replace(/\n/g, "<br>")}</div>
823
+ </div>
824
+ <div class="medos-package-price">₹ ${pkg.price.toLocaleString()}</div>
825
+ </div>
826
+ `)
827
+ .join("")}
828
+ </div>
829
+
830
+ <div class="medos-package-note">
831
+ <a href="#" class="medos-link">View full terms and conditions</a>
832
+ </div>
833
+ </div>
834
+ </div>
835
+ <div class="medos-actions">
836
+ <button class="medos-btn medos-btn-back" id="medos-btn-back">${VanillaIcons.arrowLeft(14)} Back</button>
837
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
838
+ <button class="medos-btn medos-btn-primary" id="medos-btn-continue" ${this.state.selectedNewPackage ? "" : "disabled"}>Continue</button>
839
+ </div>
840
+ `;
841
+ }
842
+ renderLocationDoctorStep() {
594
843
  const canProceed = this.canProceedFromMergedStep();
595
844
  return `
596
845
  <div style="border:1px solid #e5e7eb;border-radius:12px;margin-bottom:24px;background:#fff;">
@@ -625,18 +874,31 @@ class AppointmentCalendarWidget {
625
874
  </div>
626
875
  </div>
627
876
  <div style="display:flex;gap:8px;margin-top:16px;justify-content:flex-end;">
628
- <button style="background:#218838;color:#fff;border:none;padding:10px 14px;border-radius:8px;cursor:pointer;font-weight:600;${!canProceed ? "opacity:0.6;" : ""}" id="medos-btn-next" ${!canProceed ? "disabled" : ""}>Next</button>
877
+ <button class="medos-btn medos-btn-back" id="medos-btn-back">${VanillaIcons.arrowLeft(14)} Back</button>
878
+ <button style="background:#218838;color:#fff;border:none;padding:10px 14px;border-radius:8px;cursor:pointer;font-weight:600;${canProceed ? "" : "opacity:0.6;"}" id="medos-btn-next" ${canProceed ? "" : "disabled"}>Continue</button>
629
879
  </div>
630
880
  `;
631
881
  }
632
- renderStep1() {
882
+ renderNewAppointmentStep() {
633
883
  const dateStr = formatDateToISO(this.state.selectedDate);
634
- const selectedDoctor = this.doctors.find((d) => d.id === this.state.selectedDoctor);
635
- const selectedDoctorData = this.doctors.find((d) => d.id === this.state.selectedDoctor);
636
- const consultationCharge = selectedDoctorData?.consultationCharge ||
637
- selectedDoctor?.consultationCharge ||
638
- this.state.consultationCharge ||
639
- "N/A";
884
+ const consultationCharge = this.state.consultationMode === "ONLINE" ? "500" : "300";
885
+ const dateDisplay = this.state.selectedDate
886
+ ? this.state.selectedDate.toLocaleDateString("en-US", {
887
+ year: "numeric",
888
+ month: "long",
889
+ day: "numeric",
890
+ })
891
+ : "";
892
+ const usingSessionPack = this.state.bookingOptionType === "session-pack" &&
893
+ this.state.selectedSessionPack;
894
+ const sessionInfo = usingSessionPack
895
+ ? `
896
+ <div class="medos-session-info">
897
+ <span class="medos-session-label">Sessions:</span>
898
+ <span class="medos-session-value">${this.state.selectedSessionPack?.remainingSessions} appointments now remaining</span>
899
+ </div>
900
+ `
901
+ : "";
640
902
  return `
641
903
  <div class="medos-section-card">
642
904
  <div class="medos-section-header">
@@ -644,6 +906,7 @@ class AppointmentCalendarWidget {
644
906
  <span class="medos-section-title">Consultation Type</span>
645
907
  </div>
646
908
  <div class="medos-section-body">
909
+ <label class="medos-form-label">Consultation Mode</label>
647
910
  <div class="medos-consultation-options">
648
911
  <label class="medos-radio-option ${this.state.consultationMode === "OFFLINE" ? "selected" : ""}">
649
912
  <input
@@ -653,7 +916,7 @@ class AppointmentCalendarWidget {
653
916
  ${this.state.consultationMode === "OFFLINE" ? "checked" : ""}
654
917
  class="medos-radio-input"
655
918
  />
656
- <span class="medos-radio-label">In-Person Visit</span>
919
+ <span class="medos-radio-label">Online</span>
657
920
  </label>
658
921
  <label class="medos-radio-option ${this.state.consultationMode === "ONLINE" ? "selected" : ""}">
659
922
  <input
@@ -663,59 +926,30 @@ class AppointmentCalendarWidget {
663
926
  ${this.state.consultationMode === "ONLINE" ? "checked" : ""}
664
927
  class="medos-radio-input"
665
928
  />
666
- <span class="medos-radio-label">Online Consultation</span>
929
+ <span class="medos-radio-label">Offline</span>
667
930
  </label>
668
931
  </div>
669
- <div class="medos-consultation-charge">
670
- <span class="medos-charge-label">Consultation Charge:</span>
671
- <span class="medos-charge-value">${consultationCharge !== "N/A"
672
- ? "₹" + consultationCharge
673
- : consultationCharge}</span>
674
- </div>
675
932
  </div>
676
933
  </div>
677
934
 
678
935
  <div class="medos-section-card">
679
936
  <div class="medos-section-header">
680
937
  ${VanillaIcons.dateTime(14)}
681
- <span class="medos-section-title">Select Date</span>
682
- </div>
683
- <div class="medos-section-body">
684
- <div id="medos-calendar-container"></div>
685
- </div>
686
- </div>
687
-
688
- <div class="medos-actions">
689
- <button class="medos-btn medos-btn-secondary" id="medos-btn-back">Back</button>
690
- <button class="medos-btn medos-btn-primary" id="medos-btn-next" ${dateStr ? "" : "disabled"}>Next</button>
691
- </div>
692
- `;
693
- }
694
- renderStep2() {
695
- const dateDisplay = this.state.selectedDate
696
- ? this.state.selectedDate.toLocaleDateString("en-US", {
697
- weekday: "long",
698
- year: "numeric",
699
- month: "long",
700
- day: "numeric",
701
- })
702
- : "";
703
- return `
704
- <div class="medos-section-card">
705
- <div class="medos-section-header">
706
- ${VanillaIcons.clock(14)}
707
- <span class="medos-section-title">Select Time Slot</span>
938
+ <span class="medos-section-title">Date & Time</span>
708
939
  </div>
709
- <div class="medos-section-body">
710
- <div class="medos-selected-date-display">
711
- ${VanillaIcons.dateTime(16)}
712
- <span>${dateDisplay}</span>
940
+ <div class="medos-section-body medos-datetime-layout">
941
+ <div class="medos-calendar-section">
942
+ <label class="medos-form-label">Available Dates</label>
943
+ <div class="medos-date-display">${dateDisplay}</div>
944
+ <div id="medos-calendar-container"></div>
713
945
  </div>
714
- ${this.state.slots.length === 0
715
- ? '<div class="medos-empty-slots">No slots available for selected date</div>'
946
+ <div class="medos-slots-section">
947
+ <label class="medos-form-label">Available Slots</label>
948
+ ${this.state.slots.length === 0
949
+ ? '<div class="medos-empty-slots">Select a date to see available slots</div>'
716
950
  : `
717
- <div class="medos-slots-grid">
718
- ${this.state.slots
951
+ <div class="medos-slots-grid-compact">
952
+ ${this.state.slots
719
953
  .map((s) => {
720
954
  const start = new Date(s.start).toLocaleTimeString([], {
721
955
  hour: "2-digit",
@@ -728,221 +962,352 @@ class AppointmentCalendarWidget {
728
962
  const selected = this.state.selectedSlot?.start === s.start &&
729
963
  this.state.selectedSlot?.end === s.end;
730
964
  return `
731
- <div class="medos-slot-card ${selected ? "selected" : ""}"
732
- data-slot-id="${this.escapeHtml(s.id || `${s.start}-${s.end}`)}"
733
- data-slot-start="${this.escapeHtml(s.start)}"
734
- data-slot-end="${this.escapeHtml(s.end)}">
735
- <span class="medos-slot-time">${start}</span>
736
- <span class="medos-slot-separator">-</span>
737
- <span class="medos-slot-time">${end}</span>
738
- ${selected
739
- ? `<span class="medos-slot-check">${VanillaIcons.check(14)}</span>`
740
- : ""}
741
- </div>
742
- `;
965
+ <div class="medos-slot-btn ${selected ? "selected" : ""}"
966
+ data-slot-id="${this.escapeHtml(s.id || `${s.start}-${s.end}`)}"
967
+ data-slot-start="${this.escapeHtml(s.start)}"
968
+ data-slot-end="${this.escapeHtml(s.end)}">
969
+ ${start}
970
+ </div>
971
+ `;
743
972
  })
744
973
  .join("")}
745
- </div>
746
- `}
974
+ </div>
975
+ `}
976
+ </div>
747
977
  </div>
748
978
  </div>
979
+
749
980
  <div class="medos-actions">
750
- <button class="medos-btn medos-btn-secondary" id="medos-btn-back">Back</button>
751
- <button class="medos-btn medos-btn-primary" id="medos-btn-next" ${this.state.selectedSlot ? "" : "disabled"} style="opacity: ${this.state.selectedSlot ? 1 : 0.6}">Next</button>
981
+ <button class="medos-btn medos-btn-back" id="medos-btn-back">${VanillaIcons.arrowLeft(14)} Back</button>
982
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
983
+ <button class="medos-btn medos-btn-primary" id="medos-btn-continue" ${this.state.selectedSlot ? "" : "disabled"}>Continue</button>
752
984
  </div>
753
985
  `;
754
986
  }
755
- renderStep3() {
756
- const countryCodeValid = this.state.countryCode && validateCountryCode(this.state.countryCode);
757
- const phoneValid = this.state.patientPhone && validatePhoneNumber(this.state.patientPhone);
758
- const canSendOtp = countryCodeValid && phoneValid && !this.state.otpSending;
759
- if (!this.state.otpSent) {
760
- return `
761
- <div class="medos-section-card">
762
- <div class="medos-section-header">
763
- ${VanillaIcons.phone(14)}
764
- <span class="medos-section-title">Phone Verification</span>
765
- </div>
766
- <div class="medos-section-body">
767
- <p class="medos-section-description">Please enter your phone number for verification</p>
768
- <div class="medos-phone-input-row">
769
- <div class="medos-country-code-wrapper">
770
- <div id="medos-country-code-container"></div>
771
- </div>
772
- <div class="medos-phone-wrapper">
773
- <input
774
- type="tel"
775
- class="medos-input"
776
- id="medos-phone"
777
- placeholder="Enter phone number"
778
- value="${this.escapeHtml(this.state.patientPhone)}"
779
- maxlength="15"
780
- />
781
- </div>
782
- </div>
783
- ${this.state.patientPhone && !phoneValid
784
- ? '<div class="medos-validation-error">Phone number should be 7-15 digits</div>'
785
- : ""}
786
- </div>
787
- </div>
788
- <div class="medos-actions">
789
- <button class="medos-btn medos-btn-secondary" id="medos-btn-back">Back</button>
790
- <button class="medos-btn medos-btn-primary" id="medos-btn-send-otp" ${canSendOtp ? "" : "disabled"}>${this.state.otpSending ? "Sending..." : "Send OTP"}</button>
791
- </div>
792
- `;
793
- }
794
- if (this.state.otpVerified) {
795
- return `
796
- <div class="medos-section-card">
797
- <div class="medos-section-header">
798
- ${VanillaIcons.phone(14)}
799
- <span class="medos-section-title">Phone Verification</span>
800
- </div>
801
- <div class="medos-section-body">
802
- <div class="medos-verified-badge">
803
- ${VanillaIcons.successBadge(20)}
804
- <span>Phone verified successfully</span>
805
- </div>
806
- <div class="medos-verified-number">${this.escapeHtml(this.state.countryCode)} ${this.escapeHtml(this.state.patientPhone)}</div>
807
- </div>
808
- </div>
809
- <div class="medos-actions">
810
- <button class="medos-btn medos-btn-secondary" id="medos-btn-back">Back</button>
811
- <button class="medos-btn medos-btn-primary" id="medos-btn-next">Continue</button>
812
- </div>
813
- `;
814
- }
987
+ renderPatientSelectionStep() {
988
+ const patients = this.state.verifiedPatients.length > 0
989
+ ? this.state.verifiedPatients
990
+ : [
991
+ {
992
+ id: 1,
993
+ firstName: "Mumma",
994
+ lastName: "Bear",
995
+ email: "mumma@example.com",
996
+ countryCode: "+91",
997
+ phoneNumber: this.state.patientPhone,
998
+ dob: "1970-01-01",
999
+ age: 55,
1000
+ gender: "FEMALE",
1001
+ bloodGroup: "O+",
1002
+ mrn: "MRN001",
1003
+ address: {
1004
+ id: 1,
1005
+ completeAddress: "123 Main St",
1006
+ addressLine1: "123 Main St",
1007
+ addressLine2: "",
1008
+ city: "Mumbai",
1009
+ state: "Maharashtra",
1010
+ country: "India",
1011
+ zipcode: "400001",
1012
+ landmark: "",
1013
+ phoneNumber: this.state.patientPhone,
1014
+ latitude: 0,
1015
+ longitude: 0,
1016
+ },
1017
+ },
1018
+ {
1019
+ id: 2,
1020
+ firstName: "Papa",
1021
+ lastName: "Bear",
1022
+ email: "papa@example.com",
1023
+ countryCode: "+91",
1024
+ phoneNumber: this.state.patientPhone,
1025
+ dob: "1968-01-01",
1026
+ age: 57,
1027
+ gender: "MALE",
1028
+ bloodGroup: "B+",
1029
+ mrn: "MRN002",
1030
+ address: {
1031
+ id: 2,
1032
+ completeAddress: "123 Main St",
1033
+ addressLine1: "123 Main St",
1034
+ addressLine2: "",
1035
+ city: "Mumbai",
1036
+ state: "Maharashtra",
1037
+ country: "India",
1038
+ zipcode: "400001",
1039
+ landmark: "",
1040
+ phoneNumber: this.state.patientPhone,
1041
+ latitude: 0,
1042
+ longitude: 0,
1043
+ },
1044
+ },
1045
+ {
1046
+ id: 3,
1047
+ firstName: "Monty",
1048
+ lastName: "Bear",
1049
+ email: "monty@example.com",
1050
+ countryCode: "+91",
1051
+ phoneNumber: this.state.patientPhone,
1052
+ dob: "1990-01-01",
1053
+ age: 35,
1054
+ gender: "MALE",
1055
+ bloodGroup: "A+",
1056
+ mrn: "MRN003",
1057
+ address: {
1058
+ id: 3,
1059
+ completeAddress: "123 Main St",
1060
+ addressLine1: "123 Main St",
1061
+ addressLine2: "",
1062
+ city: "Mumbai",
1063
+ state: "Maharashtra",
1064
+ country: "India",
1065
+ zipcode: "400001",
1066
+ landmark: "",
1067
+ phoneNumber: this.state.patientPhone,
1068
+ latitude: 0,
1069
+ longitude: 0,
1070
+ },
1071
+ },
1072
+ ];
815
1073
  return `
816
1074
  <div class="medos-section-card">
817
1075
  <div class="medos-section-header">
818
- ${VanillaIcons.phone(14)}
819
- <span class="medos-section-title">Enter OTP</span>
1076
+ ${VanillaIcons.users(14)}
1077
+ <span class="medos-section-title">Select Patient</span>
820
1078
  </div>
821
1079
  <div class="medos-section-body">
822
- <p class="medos-section-description">Enter the 6-digit code sent to ${this.escapeHtml(this.state.countryCode)} ${this.escapeHtml(this.state.patientPhone)}</p>
823
- <div class="medos-otp-input-wrapper">
824
- <input
825
- type="text"
826
- class="medos-input medos-otp-input"
827
- id="medos-otp"
828
- placeholder="Enter 6-digit OTP"
829
- value="${this.escapeHtml(this.state.otpCode)}"
830
- maxlength="6"
831
- />
1080
+ <div class="medos-patient-list">
1081
+ ${patients
1082
+ .map((patient) => `
1083
+ <div class="medos-patient-card ${this.state.selectedPatient?.id === patient.id ? "selected" : ""}" data-patient-id="${patient.id}">
1084
+ <div class="medos-patient-radio">
1085
+ <input type="radio" name="patient" value="${patient.id}" ${this.state.selectedPatient?.id === patient.id ? "checked" : ""} />
1086
+ </div>
1087
+ <div class="medos-patient-avatar">
1088
+ ${patient.firstName.charAt(0)}${patient.lastName.charAt(0)}
1089
+ </div>
1090
+ <div class="medos-patient-info">
1091
+ <div class="medos-patient-name">${this.escapeHtml(patient.firstName)} ${this.escapeHtml(patient.lastName)}</div>
1092
+ <div class="medos-patient-details">${this.escapeHtml(patient.countryCode)} ${this.escapeHtml(patient.phoneNumber)}</div>
1093
+ </div>
1094
+ <div class="medos-patient-select">select</div>
1095
+ </div>
1096
+ `)
1097
+ .join("")}
832
1098
  </div>
833
- <button class="medos-link-btn" id="medos-btn-change-number">Change phone number</button>
1099
+
1100
+ <button class="medos-add-patient-btn" id="medos-btn-add-patient">
1101
+ ${VanillaIcons.plus(16)} New Patient
1102
+ </button>
834
1103
  </div>
835
1104
  </div>
836
1105
  <div class="medos-actions">
837
- <button class="medos-btn medos-btn-secondary" id="medos-btn-resend-otp">Resend OTP</button>
838
- <button class="medos-btn medos-btn-primary" id="medos-btn-verify-otp" ${this.state.otpCode.length === 6 && !this.state.otpVerifying
839
- ? ""
840
- : "disabled"}>${this.state.otpVerifying ? "Verifying..." : "Verify OTP"}</button>
1106
+ <button class="medos-btn medos-btn-back" id="medos-btn-back">${VanillaIcons.arrowLeft(14)} Back</button>
1107
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
1108
+ <button class="medos-btn medos-btn-primary" id="medos-btn-continue" ${this.state.selectedPatient ? "" : "disabled"}>Continue</button>
841
1109
  </div>
842
1110
  `;
843
1111
  }
844
- renderStep4() {
845
- const canSubmit = this.state.patientName &&
846
- this.state.patientAddress &&
847
- this.state.patientCity &&
848
- this.state.patientState &&
849
- this.state.patientCountry &&
850
- this.state.patientZipcode &&
851
- this.state.otpVerified;
1112
+ renderAppointmentSummaryStep() {
1113
+ const selectedDoctor = this.doctors.find((d) => d.id === this.state.selectedDoctor);
1114
+ const selectedAddress = this.state.addresses.find((addr) => addr.id === this.state.selectedAddress);
1115
+ const appointmentDate = this.state.selectedDate
1116
+ ? this.state.selectedDate.toLocaleDateString("en-US", {
1117
+ weekday: "short",
1118
+ year: "numeric",
1119
+ month: "short",
1120
+ day: "numeric",
1121
+ })
1122
+ : "";
1123
+ const startTime = this.state.selectedSlot?.start
1124
+ ? new Date(this.state.selectedSlot.start).toLocaleTimeString([], {
1125
+ hour: "2-digit",
1126
+ minute: "2-digit",
1127
+ })
1128
+ : "";
1129
+ const usingSessionPack = this.state.bookingOptionType === "session-pack" &&
1130
+ this.state.selectedSessionPack;
1131
+ const usingNewPackage = this.state.bookingOptionType === "explore-packages" &&
1132
+ this.state.selectedNewPackage;
1133
+ const consultationCharge = this.state.consultationMode === "ONLINE" ? 500 : 300;
1134
+ let totalAmount = consultationCharge;
1135
+ let sessionInfo = "";
1136
+ let dateOfExpiry = "";
1137
+ if (usingSessionPack) {
1138
+ totalAmount = 0;
1139
+ sessionInfo = `${this.state.selectedSessionPack?.remainingSessions} appointments now remaining`;
1140
+ dateOfExpiry = this.state.selectedSessionPack?.expiryDate || "";
1141
+ }
1142
+ else if (usingNewPackage) {
1143
+ totalAmount = this.state.selectedNewPackage?.price || 0;
1144
+ sessionInfo = `${this.state.selectedNewPackage?.totalSessions} appointments after purchase`;
1145
+ const validityDays = this.state.selectedNewPackage?.validityDays || 365;
1146
+ const expiryDate = new Date();
1147
+ expiryDate.setDate(expiryDate.getDate() + validityDays);
1148
+ dateOfExpiry = expiryDate.toLocaleDateString("en-US", {
1149
+ day: "numeric",
1150
+ month: "long",
1151
+ year: "numeric",
1152
+ });
1153
+ }
1154
+ const patientName = this.state.selectedPatient
1155
+ ? `${this.state.selectedPatient.firstName} ${this.state.selectedPatient.lastName}`
1156
+ : this.state.patientName || "Patient";
852
1157
  return `
853
- <div class="medos-section-card">
854
- <div class="medos-section-header">
855
- ${VanillaIcons.user(14)}
856
- <span class="medos-section-title">Patient Information</span>
1158
+ <div class="medos-appointment-summary">
1159
+ <div class="medos-summary-header">
1160
+ <h3>Appointment Summary</h3>
1161
+ <button class="medos-close-btn" id="medos-btn-close">&times;</button>
857
1162
  </div>
858
- <div class="medos-section-body">
859
- <div class="medos-form-row">
860
- <div class="medos-form-group medos-form-group-flex">
861
- <label class="medos-label">Full Name <span class="medos-required">*</span></label>
862
- <input type="text" class="medos-input" id="medos-patient-name" placeholder="Enter full name" value="${this.escapeHtml(this.state.patientName)}" />
1163
+
1164
+ <div class="medos-summary-section">
1165
+ <label class="medos-form-label">REVIEW APPOINTMENT DETAILS</label>
1166
+
1167
+ <div class="medos-summary-grid">
1168
+ <div class="medos-summary-row">
1169
+ <span class="medos-summary-label">Patient:</span>
1170
+ <span class="medos-summary-value">${this.escapeHtml(patientName)}</span>
863
1171
  </div>
864
- <div class="medos-form-group medos-form-group-small">
865
- <label class="medos-label">Age</label>
866
- <input type="number" class="medos-input" id="medos-patient-age" placeholder="Age" value="${this.escapeHtml(this.state.patientAge)}" />
1172
+ ${this.state.patientAge
1173
+ ? `<div class="medos-summary-row">
1174
+ <span class="medos-summary-label">Age:</span>
1175
+ <span class="medos-summary-value">${this.escapeHtml(this.state.patientAge)} years</span>
1176
+ </div>`
1177
+ : ""}
1178
+ ${this.state.bloodGroup
1179
+ ? `<div class="medos-summary-row">
1180
+ <span class="medos-summary-label">Blood Group:</span>
1181
+ <span class="medos-summary-value">${this.escapeHtml(this.state.bloodGroup)}</span>
1182
+ </div>`
1183
+ : ""}
1184
+ <div class="medos-summary-row">
1185
+ <span class="medos-summary-label">Doctor:</span>
1186
+ <span class="medos-summary-value">${selectedDoctor
1187
+ ? this.escapeHtml(selectedDoctor.name)
1188
+ : "Not selected"}</span>
867
1189
  </div>
868
- </div>
869
- <div class="medos-form-row">
870
- <div class="medos-form-group medos-form-group-flex">
871
- <label class="medos-label">Email</label>
872
- <input type="email" class="medos-input" id="medos-patient-email" placeholder="patient@example.com" value="${this.escapeHtml(this.state.patientEmail)}" />
1190
+ ${selectedAddress
1191
+ ? `<div class="medos-summary-row">
1192
+ <span class="medos-summary-label">Location:</span>
1193
+ <span class="medos-summary-value">${this.escapeHtml(selectedAddress.label || "Unknown Location")}</span>
1194
+ </div>`
1195
+ : ""}
1196
+ <div class="medos-summary-row">
1197
+ <span class="medos-summary-label">Date & Time:</span>
1198
+ <span class="medos-summary-value">${appointmentDate}${startTime ? `, ${startTime}` : ""}</span>
1199
+ </div>
1200
+ <div class="medos-summary-row">
1201
+ <span class="medos-summary-label">Appointment Type:</span>
1202
+ <span class="medos-summary-value">${this.state.consultationMode === "ONLINE"
1203
+ ? "In Clinic Consultation"
1204
+ : "Online Consultation"}</span>
1205
+ </div>
1206
+ <div class="medos-summary-row">
1207
+ <span class="medos-summary-label">Service:</span>
1208
+ <span class="medos-summary-value">${usingSessionPack
1209
+ ? this.escapeHtml(this.state.selectedSessionPack?.name || "Session Pack")
1210
+ : usingNewPackage
1211
+ ? this.escapeHtml(this.state.selectedNewPackage?.name || "Package")
1212
+ : "Standard Consultation"}</span>
873
1213
  </div>
874
- <div class="medos-form-group medos-form-group-small">
875
- <label class="medos-label">Gender</label>
876
- <div id="medos-gender-container"></div>
1214
+ <div class="medos-summary-row">
1215
+ <span class="medos-summary-label">Sessions:</span>
1216
+ <span class="medos-summary-value">${sessionInfo || "1 consultation"}</span>
877
1217
  </div>
1218
+ ${usingSessionPack || usingNewPackage
1219
+ ? `
1220
+ <div class="medos-summary-row">
1221
+ <span class="medos-summary-label">Date of Purchase:</span>
1222
+ <span class="medos-summary-value">${usingSessionPack
1223
+ ? this.state.selectedSessionPack?.purchaseDate ||
1224
+ "Previously"
1225
+ : "Today"}</span>
1226
+ </div>
1227
+ <div class="medos-summary-row">
1228
+ <span class="medos-summary-label">Date of Expiry:</span>
1229
+ <span class="medos-summary-value medos-expiry">${dateOfExpiry}</span>
1230
+ </div>
1231
+ `
1232
+ : ""}
878
1233
  </div>
879
- <div class="medos-form-group">
880
- <label class="medos-label">Blood Group <span class="medos-optional">(optional)</span></label>
881
- <div id="medos-blood-group-container"></div>
1234
+ </div>
1235
+
1236
+ <div class="medos-summary-total">
1237
+ <div class="medos-total-row">
1238
+ <span class="medos-total-label">Total Amount</span>
1239
+ <span class="medos-total-note">${usingSessionPack ? "Using credits from bundle sessions." : ""}</span>
882
1240
  </div>
1241
+ <div class="medos-total-amount">₹${totalAmount.toLocaleString()}</div>
1242
+ </div>
1243
+
1244
+ <div class="medos-actions">
1245
+ <button class="medos-btn medos-btn-back" id="medos-btn-back">${VanillaIcons.arrowLeft(14)} Back</button>
1246
+ <button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
1247
+ <button class="medos-btn medos-btn-primary" id="medos-btn-confirm">Confirm Book</button>
883
1248
  </div>
884
1249
  </div>
885
-
886
- <div class="medos-section-card">
887
- <div class="medos-section-header">
888
- ${VanillaIcons.mapPin(14)}
889
- <span class="medos-section-title">Address Details</span>
1250
+ `;
1251
+ }
1252
+ renderSuccessStep() {
1253
+ const duration = this.calculateDuration();
1254
+ const selectedDoctor = this.doctors.find((d) => d.id === this.state.selectedDoctor);
1255
+ const selectedAddress = this.state.addresses.find((addr) => addr.id === this.state.selectedAddress);
1256
+ const appointmentDate = this.state.selectedDate
1257
+ ? this.formatDate(formatDateToISO(this.state.selectedDate))
1258
+ : "";
1259
+ const startTime = this.state.selectedSlot?.start
1260
+ ? this.formatTime(new Date(this.state.selectedSlot.start).toTimeString().slice(0, 5))
1261
+ : "";
1262
+ const patientName = this.state.selectedPatient
1263
+ ? `${this.state.selectedPatient.firstName} ${this.state.selectedPatient.lastName}`
1264
+ : this.state.patientName || "Patient";
1265
+ const usingSessionPack = this.state.bookingOptionType === "session-pack" &&
1266
+ this.state.selectedSessionPack;
1267
+ return `
1268
+ <div class="medos-success-container">
1269
+ <div class="medos-success-header">
1270
+ <h2>Appointment Confirmed</h2>
890
1271
  </div>
891
- <div class="medos-section-body">
892
- <div class="medos-form-group">
893
- <label class="medos-label">Address Line 1 <span class="medos-required">*</span></label>
894
- <input type="text" class="medos-input" id="medos-patient-address" placeholder="Street address, building name, etc." value="${this.escapeHtml(this.state.patientAddress)}" />
1272
+
1273
+ <div class="medos-success-content">
1274
+ <div class="medos-success-badge">
1275
+ ${VanillaIcons.successBadge(64)}
895
1276
  </div>
896
- <div class="medos-form-row">
897
- <div class="medos-form-group">
898
- <label class="medos-label">City <span class="medos-required">*</span></label>
899
- <input type="text" class="medos-input" id="medos-patient-city" placeholder="City" value="${this.escapeHtml(this.state.patientCity)}" />
900
- </div>
901
- <div class="medos-form-group">
902
- <label class="medos-label">State <span class="medos-required">*</span></label>
903
- <input type="text" class="medos-input" id="medos-patient-state" placeholder="State" value="${this.escapeHtml(this.state.patientState)}" />
1277
+
1278
+ <h3 class="medos-success-title">Appointment Confirmed</h3>
1279
+
1280
+ <div class="medos-success-details">
1281
+ <h4>Appointment Details</h4>
1282
+ <div class="medos-details-text">
1283
+ <p><strong>Patient:</strong> ${this.escapeHtml(patientName)}</p>
1284
+ <p><strong>Type:</strong> ${this.state.consultationMode === "ONLINE"
1285
+ ? "In Clinic Consultation"
1286
+ : "Online"}</p>
1287
+ <p><strong>Date:</strong> ${appointmentDate}</p>
1288
+ <p><strong>Time:</strong> ${startTime}</p>
1289
+ <p><strong>Duration:</strong> ~${duration} minutes</p>
1290
+ ${selectedAddress?.label
1291
+ ? `<p><strong>Location:</strong> ${this.escapeHtml(selectedAddress.label)}</p>`
1292
+ : ""}
904
1293
  </div>
905
1294
  </div>
906
- <div class="medos-form-row">
907
- <div class="medos-form-group">
908
- <label class="medos-label">Country <span class="medos-required">*</span></label>
909
- <input type="text" class="medos-input" id="medos-patient-country" placeholder="Country" value="${this.escapeHtml(this.state.patientCountry)}" />
910
- </div>
911
- <div class="medos-form-group">
912
- <label class="medos-label">Zipcode <span class="medos-required">*</span></label>
913
- <input type="text" class="medos-input" id="medos-patient-zipcode" placeholder="Zipcode" value="${this.escapeHtml(this.state.patientZipcode)}" />
1295
+
1296
+ <p class="medos-confirmation-message">
1297
+ A confirmation message has been sent to the registered Phone Number.
1298
+ </p>
1299
+
1300
+ ${usingSessionPack
1301
+ ? `
1302
+ <div class="medos-session-remaining">
1303
+ <span class="medos-remaining-label">Sessions:</span>
1304
+ <span class="medos-remaining-value">${(this.state.selectedSessionPack?.remainingSessions || 1) - 1} appointments now remaining</span>
914
1305
  </div>
915
- </div>
916
- <div class="medos-form-group">
917
- <label class="medos-label">Landmark <span class="medos-optional">(optional)</span></label>
918
- <input type="text" class="medos-input" id="medos-patient-landmark" placeholder="Nearby landmark" value="${this.escapeHtml(this.state.patientLandmark)}" />
919
- </div>
1306
+ `
1307
+ : ""}
920
1308
  </div>
921
1309
  </div>
922
-
923
- <div class="medos-actions">
924
- <button class="medos-btn medos-btn-secondary" id="medos-btn-back">Back</button>
925
- <button class="medos-btn medos-btn-primary" id="medos-btn-submit" ${canSubmit && !this.state.loading ? "" : "disabled"}>${this.state.loading ? "Booking..." : "Book Appointment"}</button>
926
- </div>
927
1310
  `;
928
- }
929
- renderSuccessIcon() {
930
- return `
931
- <div style="position: relative; display: inline-block;">
932
- <svg width="64" height="64" viewBox="0 0 41 41" fill="none">
933
- <path
934
- d="M31.1309 4.90254C32.388 4.98797 33.0166 5.03069 33.5247 5.25288C34.2598 5.57438 34.8467 6.16126 35.1682 6.8964C35.3904 7.40445 35.4331 8.03302 35.5185 9.29016L35.7135 12.159C35.748 12.6674 35.7653 12.9217 35.8206 13.1645C35.9004 13.5154 36.0391 13.8503 36.2308 14.1549C36.3634 14.3657 36.531 14.5576 36.8661 14.9416L38.7568 17.108C39.5853 18.0574 39.9996 18.532 40.2017 19.0484C40.4942 19.7955 40.4942 20.6255 40.2017 21.3727C39.9996 21.889 39.5853 22.3637 38.7568 23.313L36.8661 25.4795C36.531 25.8634 36.3634 26.0554 36.2308 26.2662C36.0391 26.5708 35.9004 26.9056 35.8206 27.2566C35.7653 27.4994 35.748 27.7536 35.7135 28.2621L35.5185 31.1309C35.4331 32.388 35.3904 33.0166 35.1682 33.5247C34.8467 34.2598 34.2598 34.8467 33.5247 35.1682C33.0166 35.3904 32.388 35.4331 31.1309 35.5185L28.2621 35.7135C27.7536 35.748 27.4994 35.7653 27.2566 35.8206C26.9056 35.9004 26.5708 36.0391 26.2662 36.2308C26.0554 36.3634 25.8634 36.531 25.4795 36.8661L23.313 38.7568C22.3637 39.5853 21.889 39.9996 21.3727 40.2017C20.6255 40.4942 19.7955 40.4942 19.0484 40.2017C18.532 39.9996 18.0574 39.5853 17.108 38.7568L14.9416 36.8661C14.5576 36.531 14.3657 36.3634 14.1549 36.2308C13.8503 36.0391 13.5154 35.9004 13.1645 35.8206C12.9217 35.7653 12.6674 35.748 12.159 35.7135L9.29016 35.5185C8.03302 35.4331 7.40445 35.3904 6.8964 35.1682C6.16126 34.8467 5.57438 34.2598 5.25288 33.5247C5.03069 33.0166 4.98797 32.388 4.90254 31.1309L4.70759 28.2621C4.67304 27.7536 4.65576 27.4994 4.60049 27.2566C4.52063 26.9056 4.38193 26.5708 4.19028 26.2662C4.05764 26.0554 3.89009 25.8634 3.555 25.4795L1.66428 23.313C0.83576 22.3637 0.421499 21.889 0.219363 21.3727C-0.073121 20.6255 -0.0731209 19.7955 0.219363 19.0484C0.421499 18.532 0.83576 18.0574 1.66428 17.108L3.555 14.9416C3.89009 14.5576 4.05764 14.3657 4.19027 14.1549C4.38193 13.8503 4.52063 13.5154 4.60049 13.1645C4.65576 12.9217 4.67304 12.6674 4.70759 12.159L4.90254 9.29016C4.98797 8.03302 5.03069 7.40445 5.25288 6.8964C5.57438 6.16126 6.16126 5.57438 6.8964 5.25288C7.40445 5.03069 8.03302 4.98797 9.29016 4.90254L12.159 4.70759C12.6674 4.67304 12.9217 4.65577 13.1645 4.6005C13.5154 4.52063 13.8503 4.38193 14.1549 4.19028C14.3657 4.05764 14.5576 3.89009 14.9416 3.555L17.108 1.66428C18.0574 0.83576 18.532 0.421499 19.0484 0.219363C19.7955 -0.073121 20.6255 -0.073121 21.3727 0.219363C21.889 0.421499 22.3637 0.83576 23.313 1.66428L25.4795 3.555C25.8634 3.89009 26.0554 4.05764 26.2662 4.19028C26.5708 4.38193 26.9056 4.52063 27.2566 4.6005C27.4994 4.65577 27.7536 4.67304 28.2621 4.70759L31.1309 4.90254Z"
935
- fill="#006E0F"
936
- />
937
- </svg>
938
- <svg width="16" height="12" viewBox="0 0 16 12" fill="none" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">
939
- <path
940
- d="M5.472 11.544L0 6.072L1.368 4.704L5.472 8.808L14.28 0L15.648 1.368L5.472 11.544Z"
941
- fill="white"
942
- />
943
- </svg>
944
- </div>
945
- `;
946
1311
  }
947
1312
  formatDate(dateStr) {
948
1313
  try {
@@ -980,66 +1345,6 @@ class AppointmentCalendarWidget {
980
1345
  }
981
1346
  return 60;
982
1347
  }
983
- renderStep5() {
984
- const duration = this.calculateDuration();
985
- const selectedAddress = this.state.addresses.find((addr) => addr.id === this.state.selectedAddress);
986
- const appointmentDate = this.state.selectedDate
987
- ? this.formatDate(formatDateToISO(this.state.selectedDate))
988
- : "";
989
- const startTime = this.state.selectedSlot?.start
990
- ? this.formatTime(new Date(this.state.selectedSlot.start).toTimeString().slice(0, 5))
991
- : "";
992
- return `
993
- <div style="display: flex; flex-direction: column; padding: 0; font-family: Arial, sans-serif; background: #f8f9fa; min-height: 500px;">
994
- <!-- Header with border -->
995
- <div style="padding: 20px 24px; font-size: 24px; font-weight: bold; color: #1a365d; border-bottom: 2px solid #e2e8f0; background: white;">
996
- Appointment Confirmed
997
- </div>
998
-
999
- <!-- Main content with border -->
1000
- <div style="flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px 24px; border: 2px solid #e2e8f0; border-top: none; background: white; text-align: center;">
1001
- <!-- Success Title -->
1002
- <h2 style="font-size: 20px; font-weight: 600; color: #006E0F; margin: 0 0 24px 0;">
1003
- Appointment Confirmed
1004
- </h2>
1005
-
1006
- <!-- Success Icon -->
1007
- <div style="margin-bottom: 32px;">
1008
- ${this.renderSuccessIcon()}
1009
- </div>
1010
-
1011
- <!-- Appointment Details -->
1012
- <div style="width: 100%; max-width: 500px; margin-bottom: 32px;">
1013
- <h3 style="font-size: 18px; font-weight: 600; color: #006E0F; margin-bottom: 24px;">
1014
- Appointment Details
1015
- </h3>
1016
-
1017
- <div style="display: flex; flex-direction: column; gap: 12px; font-size: 16px; line-height: 1.6; color: #4a5568;">
1018
- <div><strong style="color: #006E0F;">Patient:</strong> ${this.escapeHtml(this.state.patientName || "Patient")}</div>
1019
- <div><strong style="color: #006E0F;">Visitation Type:</strong> ${this.state.consultationMode === "ONLINE"
1020
- ? "Online Consultation"
1021
- : "General"}</div>
1022
- ${appointmentDate
1023
- ? `<div><strong style="color: #006E0F;">Date:</strong> ${appointmentDate}</div>`
1024
- : ""}
1025
- ${startTime
1026
- ? `<div><strong style="color: #006E0F;">Time:</strong> ${startTime}</div>`
1027
- : ""}
1028
- <div><strong style="color: #006E0F;">Duration:</strong> ~${duration} minutes</div>
1029
- ${selectedAddress?.label
1030
- ? `<div><strong style="color: #006E0F;">Location:</strong> ${this.escapeHtml(selectedAddress.label)}</div>`
1031
- : ""}
1032
- </div>
1033
- </div>
1034
-
1035
- <!-- Confirmation Message -->
1036
- <div style="font-size: 16px; font-style: italic; color: #718096; text-align: center; max-width: 600px; line-height: 1.5;">
1037
- A confirmation email has been sent to the Patient's Email address.
1038
- </div>
1039
- </div>
1040
- </div>
1041
- `;
1042
- }
1043
1348
  attachEventListeners() {
1044
1349
  const consultationRadios = this.container.querySelectorAll('input[name="consultationMode"]');
1045
1350
  consultationRadios.forEach((radio) => {
@@ -1049,7 +1354,7 @@ class AppointmentCalendarWidget {
1049
1354
  this.render();
1050
1355
  });
1051
1356
  });
1052
- const slotCards = this.container.querySelectorAll(".medos-slot-card");
1357
+ const slotCards = this.container.querySelectorAll(".medos-slot-card, .medos-slot-btn");
1053
1358
  slotCards.forEach((card) => {
1054
1359
  card.addEventListener("click", () => {
1055
1360
  const slotId = card.dataset.slotId;
@@ -1131,13 +1436,6 @@ class AppointmentCalendarWidget {
1131
1436
  this.updateSubmitButtonState();
1132
1437
  });
1133
1438
  }
1134
- const patientGenderSelect = this.container.querySelector("#medos-patient-gender");
1135
- if (patientGenderSelect) {
1136
- patientGenderSelect.addEventListener("change", (e) => {
1137
- const target = e.target;
1138
- this.state.patientGender = target.value;
1139
- });
1140
- }
1141
1439
  const patientAddressInput = this.container.querySelector("#medos-patient-address");
1142
1440
  if (patientAddressInput) {
1143
1441
  patientAddressInput.addEventListener("input", (e) => {
@@ -1185,6 +1483,65 @@ class AppointmentCalendarWidget {
1185
1483
  this.state.patientLandmark = target.value;
1186
1484
  });
1187
1485
  }
1486
+ const optionCards = this.container.querySelectorAll(".medos-option-card");
1487
+ optionCards.forEach((card) => {
1488
+ card.addEventListener("click", () => {
1489
+ const option = card.dataset.option;
1490
+ if (option === "new-appointment" ||
1491
+ option === "session-pack" ||
1492
+ option === "explore-packages") {
1493
+ this.state.bookingOptionType = option;
1494
+ this.render();
1495
+ }
1496
+ });
1497
+ });
1498
+ const packCards = this.container.querySelectorAll(".medos-session-pack-card");
1499
+ packCards.forEach((card) => {
1500
+ card.addEventListener("click", () => {
1501
+ const packId = Number.parseInt(card.dataset.packId || "0", 10);
1502
+ const pack = this.state.userSessionPacks.find((p) => p.id === packId);
1503
+ if (pack) {
1504
+ this.state.selectedSessionPack = pack;
1505
+ this.state.bookingOptionType = "session-pack";
1506
+ this.render();
1507
+ }
1508
+ });
1509
+ });
1510
+ const packageCards = this.container.querySelectorAll(".medos-package-card");
1511
+ packageCards.forEach((card) => {
1512
+ card.addEventListener("click", () => {
1513
+ const packageId = parseInt(card.dataset.packageId || "0", 10);
1514
+ const pkg = this.state.availablePackages.length > 0
1515
+ ? this.state.availablePackages.find((p) => p.id === packageId)
1516
+ : {
1517
+ id: packageId,
1518
+ name: packageId === 1 ? "Silver Package" : "Gold Package",
1519
+ totalSessions: packageId === 1 ? 3 : 5,
1520
+ price: packageId === 1 ? 5000 : 8000,
1521
+ validityDays: packageId === 1 ? 180 : 365,
1522
+ applicableOnline: true,
1523
+ applicableOffline: true,
1524
+ };
1525
+ if (pkg) {
1526
+ this.state.selectedNewPackage = pkg;
1527
+ this.render();
1528
+ }
1529
+ });
1530
+ });
1531
+ const patientCards = this.container.querySelectorAll(".medos-patient-card");
1532
+ patientCards.forEach((card) => {
1533
+ card.addEventListener("click", () => {
1534
+ const patientId = parseInt(card.dataset.patientId || "0", 10);
1535
+ const patients = this.state.verifiedPatients.length > 0
1536
+ ? this.state.verifiedPatients
1537
+ : this.getPlaceholderPatients();
1538
+ const patient = patients.find((p) => p.id === patientId);
1539
+ if (patient) {
1540
+ this.state.selectedPatient = patient;
1541
+ this.render();
1542
+ }
1543
+ });
1544
+ });
1188
1545
  const nextBtn = this.container.querySelector("#medos-btn-next");
1189
1546
  if (nextBtn) {
1190
1547
  nextBtn.addEventListener("click", () => {
@@ -1193,10 +1550,22 @@ class AppointmentCalendarWidget {
1193
1550
  }
1194
1551
  });
1195
1552
  }
1553
+ const continueBtn = this.container.querySelector("#medos-btn-continue");
1554
+ if (continueBtn) {
1555
+ continueBtn.addEventListener("click", () => {
1556
+ if (!continueBtn.disabled) {
1557
+ this.goToNext();
1558
+ }
1559
+ });
1560
+ }
1196
1561
  const backBtn = this.container.querySelector("#medos-btn-back");
1197
1562
  if (backBtn) {
1198
1563
  backBtn.addEventListener("click", () => this.goBack());
1199
1564
  }
1565
+ const cancelBtn = this.container.querySelector("#medos-btn-cancel");
1566
+ if (cancelBtn) {
1567
+ cancelBtn.addEventListener("click", () => this.reset());
1568
+ }
1200
1569
  const sendOtpBtn = this.container.querySelector("#medos-btn-send-otp");
1201
1570
  if (sendOtpBtn) {
1202
1571
  sendOtpBtn.addEventListener("click", () => {
@@ -1226,6 +1595,14 @@ class AppointmentCalendarWidget {
1226
1595
  this.sendOtp();
1227
1596
  });
1228
1597
  }
1598
+ const confirmBtn = this.container.querySelector("#medos-btn-confirm");
1599
+ if (confirmBtn) {
1600
+ confirmBtn.addEventListener("click", () => {
1601
+ if (!confirmBtn.disabled) {
1602
+ this.submitAppointment();
1603
+ }
1604
+ });
1605
+ }
1229
1606
  const submitBtn = this.container.querySelector("#medos-btn-submit");
1230
1607
  if (submitBtn) {
1231
1608
  submitBtn.addEventListener("click", () => {
@@ -1238,6 +1615,72 @@ class AppointmentCalendarWidget {
1238
1615
  if (bookAnotherBtn) {
1239
1616
  bookAnotherBtn.addEventListener("click", () => this.reset());
1240
1617
  }
1618
+ const addPatientBtn = this.container.querySelector("#medos-btn-add-patient");
1619
+ if (addPatientBtn) {
1620
+ addPatientBtn.addEventListener("click", () => {
1621
+ this.state.selectedPatient = null;
1622
+ this.state.useExistingPatient = false;
1623
+ this.goToNext();
1624
+ });
1625
+ }
1626
+ }
1627
+ getPlaceholderPatients() {
1628
+ return [
1629
+ {
1630
+ id: 1,
1631
+ firstName: "Mumma",
1632
+ lastName: "Bear",
1633
+ email: "mumma@example.com",
1634
+ countryCode: "+91",
1635
+ phoneNumber: this.state.patientPhone,
1636
+ dob: "1970-01-01",
1637
+ age: 55,
1638
+ gender: "FEMALE",
1639
+ bloodGroup: "O+",
1640
+ mrn: "MRN001",
1641
+ address: {
1642
+ id: 1,
1643
+ completeAddress: "123 Main St",
1644
+ addressLine1: "123 Main St",
1645
+ addressLine2: "",
1646
+ city: "Mumbai",
1647
+ state: "Maharashtra",
1648
+ country: "India",
1649
+ zipcode: "400001",
1650
+ landmark: "",
1651
+ phoneNumber: this.state.patientPhone,
1652
+ latitude: 0,
1653
+ longitude: 0,
1654
+ },
1655
+ },
1656
+ {
1657
+ id: 2,
1658
+ firstName: "Papa",
1659
+ lastName: "Bear",
1660
+ email: "papa@example.com",
1661
+ countryCode: "+91",
1662
+ phoneNumber: this.state.patientPhone,
1663
+ dob: "1968-01-01",
1664
+ age: 57,
1665
+ gender: "MALE",
1666
+ bloodGroup: "B+",
1667
+ mrn: "MRN002",
1668
+ address: {
1669
+ id: 2,
1670
+ completeAddress: "123 Main St",
1671
+ addressLine1: "123 Main St",
1672
+ addressLine2: "",
1673
+ city: "Mumbai",
1674
+ state: "Maharashtra",
1675
+ country: "India",
1676
+ zipcode: "400001",
1677
+ landmark: "",
1678
+ phoneNumber: this.state.patientPhone,
1679
+ latitude: 0,
1680
+ longitude: 0,
1681
+ },
1682
+ },
1683
+ ];
1241
1684
  }
1242
1685
  escapeHtml(text) {
1243
1686
  const div = document.createElement("div");