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.
- package/dist/client/MedosClient.d.ts +1 -0
- package/dist/client/MedosClient.js +7 -0
- package/dist/components/AppointmentCalender.js +19 -22
- package/dist/components/AppointmentConfirmationStep.d.ts +1 -0
- package/dist/components/AppointmentConfirmationStep.js +34 -42
- package/dist/components/AppointmentDateTimeModal.d.ts +1 -0
- package/dist/components/AppointmentDateTimeModal.js +201 -168
- package/dist/components/AppointmentSummaryStep.d.ts +12 -0
- package/dist/components/AppointmentSummaryStep.js +168 -0
- package/dist/components/BookingOptionStep.d.ts +14 -0
- package/dist/components/BookingOptionStep.js +346 -0
- package/dist/components/ContactInformationStep.js +10 -4
- package/dist/components/ContactPreferenceStep.js +10 -1
- package/dist/components/DoctorSelectModal.js +105 -59
- package/dist/components/EnquiryForm.js +81 -69
- package/dist/components/Icons/CloseIcon.d.ts +9 -0
- package/dist/components/Icons/CloseIcon.js +5 -0
- package/dist/components/InquiryDetailsStep.js +5 -1
- package/dist/components/PatientDetailsStep.js +17 -12
- package/dist/components/PatientSelectionStep.d.ts +12 -0
- package/dist/components/PatientSelectionStep.js +254 -0
- package/dist/components/PhoneVerificationStep.js +1 -1
- package/dist/components/SuccessStep.js +1 -1
- package/dist/components/appointment-booking/AppointmentCalender.js +200 -60
- package/dist/components/appointment-booking/hooks/useAppointmentFlow.d.ts +0 -1
- package/dist/components/appointment-booking/hooks/useAppointmentFlow.js +110 -25
- package/dist/components/appointment-booking/hooks/useAppointmentState.js +32 -0
- package/dist/components/appointment-booking/hooks/useInitializeAddresses.js +0 -1
- package/dist/components/appointment-booking/types.d.ts +163 -0
- package/dist/components/appointment-booking/types.js +16 -0
- package/dist/components/appointment-modal-styles.d.ts +259 -0
- package/dist/components/appointment-modal-styles.js +395 -0
- package/dist/components/constant.d.ts +2 -0
- package/dist/components/constant.js +15 -0
- package/dist/components/custom-calendar.js +20 -11
- package/dist/components/styles.js +93 -52
- package/dist/components/theme-styles.d.ts +5 -4
- package/dist/components/theme-styles.js +221 -125
- package/dist/components/types.d.ts +3 -1
- package/dist/components/types.js +15 -0
- package/dist/components/utils.d.ts +3 -0
- package/dist/components/utils.js +59 -0
- package/dist/components/validation.d.ts +2 -0
- package/dist/components/validation.js +41 -0
- package/dist/core/theme/index.d.ts +1 -0
- package/dist/core/theme/index.js +1 -0
- package/dist/core/theme/responsive.d.ts +15 -0
- package/dist/core/theme/responsive.js +113 -0
- package/dist/core/theme/themes.js +16 -4
- package/dist/core/theme/types.d.ts +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/react/ThemeProvider.d.ts +2 -1
- package/dist/react/ThemeProvider.js +49 -10
- package/dist/services/AppointmentService.d.ts +80 -2
- package/dist/services/AppointmentService.js +114 -5
- package/dist/services/WorkspaceService.d.ts +58 -3
- package/dist/services/WorkspaceService.js +10 -1
- package/dist/vanilla/AppointmentCalendarWidget.d.ts +9 -7
- package/dist/vanilla/AppointmentCalendarWidget.js +820 -377
- package/dist/vanilla/EnquiryFormWidget.d.ts +1 -0
- package/dist/vanilla/EnquiryFormWidget.js +25 -43
- package/dist/vanilla/client/MedosClient.d.ts +1 -0
- package/dist/vanilla/components/AppointmentConfirmationStep.d.ts +1 -0
- package/dist/vanilla/components/AppointmentDateTimeModal.d.ts +1 -0
- package/dist/vanilla/components/AppointmentSummaryStep.d.ts +12 -0
- package/dist/vanilla/components/BookingOptionStep.d.ts +14 -0
- package/dist/vanilla/components/Icons/CloseIcon.d.ts +9 -0
- package/dist/vanilla/components/PatientSelectionStep.d.ts +12 -0
- package/dist/vanilla/components/VanillaCalendar.js +33 -18
- package/dist/vanilla/components/VanillaIcons.d.ts +5 -0
- package/dist/vanilla/components/VanillaIcons.js +92 -0
- package/dist/vanilla/components/VanillaSelect.d.ts +3 -0
- package/dist/vanilla/components/VanillaSelect.js +93 -5
- package/dist/vanilla/components/appointment-booking/hooks/useAppointmentFlow.d.ts +0 -1
- package/dist/vanilla/components/appointment-booking/types.d.ts +163 -0
- package/dist/vanilla/components/appointment-modal-styles.d.ts +259 -0
- package/dist/vanilla/components/constant.d.ts +2 -0
- package/dist/vanilla/components/theme-styles.d.ts +5 -4
- package/dist/vanilla/components/types.d.ts +3 -1
- package/dist/vanilla/components/utils.d.ts +3 -0
- package/dist/vanilla/components/validation.d.ts +2 -0
- package/dist/vanilla/core/theme/index.d.ts +1 -0
- package/dist/vanilla/core/theme/responsive.d.ts +15 -0
- package/dist/vanilla/core/theme/types.d.ts +8 -0
- package/dist/vanilla/enquiry-widget.js +373 -52
- package/dist/vanilla/index.d.ts +2 -0
- package/dist/vanilla/react/ThemeProvider.d.ts +2 -1
- package/dist/vanilla/services/AppointmentService.d.ts +80 -2
- package/dist/vanilla/services/WorkspaceService.d.ts +58 -3
- package/dist/vanilla/vanilla/AppointmentCalendarWidget.d.ts +9 -7
- package/dist/vanilla/vanilla/EnquiryFormWidget.d.ts +1 -0
- package/dist/vanilla/vanilla/components/VanillaIcons.d.ts +5 -0
- package/dist/vanilla/vanilla/components/VanillaSelect.d.ts +3 -0
- package/dist/vanilla/widget.css +833 -207
- package/dist/vanilla/widget.js +6444 -5676
- 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,
|
|
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.
|
|
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
|
-
|
|
408
|
-
if (this.state.step === 1 && dateStr) {
|
|
472
|
+
if (this.state.step === 3) {
|
|
409
473
|
this.state.step = 2;
|
|
410
|
-
this.
|
|
474
|
+
this.render();
|
|
411
475
|
return;
|
|
412
476
|
}
|
|
413
|
-
if (this.state.step ===
|
|
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 ===
|
|
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
|
|
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 ===
|
|
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.
|
|
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.
|
|
604
|
+
return this.renderPhoneVerificationStep();
|
|
579
605
|
case 1:
|
|
580
|
-
return this.
|
|
606
|
+
return this.renderBookingOptionStep();
|
|
581
607
|
case 2:
|
|
582
|
-
return this.
|
|
608
|
+
return this.state.showPackageExplorer
|
|
609
|
+
? this.renderPackageExplorerStep()
|
|
610
|
+
: this.renderLocationDoctorStep();
|
|
583
611
|
case 3:
|
|
584
|
-
return this.
|
|
612
|
+
return this.renderNewAppointmentStep();
|
|
585
613
|
case 4:
|
|
586
|
-
return this.
|
|
614
|
+
return this.renderPatientSelectionStep();
|
|
587
615
|
case 5:
|
|
588
|
-
return this.
|
|
616
|
+
return this.renderAppointmentSummaryStep();
|
|
617
|
+
case 6:
|
|
618
|
+
return this.renderSuccessStep();
|
|
589
619
|
default:
|
|
590
620
|
return "";
|
|
591
621
|
}
|
|
592
622
|
}
|
|
593
|
-
|
|
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
|
|
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
|
-
|
|
882
|
+
renderNewAppointmentStep() {
|
|
633
883
|
const dateStr = formatDateToISO(this.state.selectedDate);
|
|
634
|
-
const
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
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">
|
|
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">
|
|
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">
|
|
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-
|
|
711
|
-
|
|
712
|
-
<
|
|
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
|
-
|
|
715
|
-
|
|
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
|
-
|
|
718
|
-
|
|
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
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
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
|
-
|
|
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-
|
|
751
|
-
<button class="medos-btn medos-btn-
|
|
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
|
-
|
|
756
|
-
const
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
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.
|
|
819
|
-
<span class="medos-section-title">
|
|
1076
|
+
${VanillaIcons.users(14)}
|
|
1077
|
+
<span class="medos-section-title">Select Patient</span>
|
|
820
1078
|
</div>
|
|
821
1079
|
<div class="medos-section-body">
|
|
822
|
-
<
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
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
|
-
|
|
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-
|
|
838
|
-
<button class="medos-btn medos-btn-
|
|
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
|
-
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
this.state.
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
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-
|
|
854
|
-
<div class="medos-
|
|
855
|
-
|
|
856
|
-
<
|
|
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">×</button>
|
|
857
1162
|
</div>
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
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
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
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-
|
|
875
|
-
<
|
|
876
|
-
<
|
|
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
|
-
|
|
880
|
-
|
|
881
|
-
|
|
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
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1272
|
+
|
|
1273
|
+
<div class="medos-success-content">
|
|
1274
|
+
<div class="medos-success-badge">
|
|
1275
|
+
${VanillaIcons.successBadge(64)}
|
|
895
1276
|
</div>
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
</
|
|
901
|
-
<div class="medos-
|
|
902
|
-
<
|
|
903
|
-
<
|
|
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
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
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
|
-
|
|
916
|
-
|
|
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");
|