medos-sdk 1.1.9 → 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 +22 -8
- package/dist/components/AppointmentConfirmationStep.d.ts +4 -0
- package/dist/components/AppointmentConfirmationStep.js +50 -52
- package/dist/components/AppointmentDateTimeModal.d.ts +4 -0
- package/dist/components/AppointmentDateTimeModal.js +216 -165
- 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 +13 -6
- package/dist/components/ContactPreferenceStep.js +16 -6
- package/dist/components/DoctorSelectModal.d.ts +5 -0
- package/dist/components/DoctorSelectModal.js +169 -74
- package/dist/components/EnquiryForm.js +84 -72
- package/dist/components/Icons/CloseIcon.d.ts +9 -0
- package/dist/components/Icons/CloseIcon.js +5 -0
- package/dist/components/InquiryDetailsStep.js +11 -6
- 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.d.ts +5 -0
- package/dist/components/appointment-booking/AppointmentCalender.js +247 -0
- package/dist/components/appointment-booking/hooks/index.d.ts +3 -0
- package/dist/components/appointment-booking/hooks/index.js +3 -0
- package/dist/components/appointment-booking/hooks/useAppointmentFlow.d.ts +8 -0
- package/dist/components/appointment-booking/hooks/useAppointmentFlow.js +318 -0
- package/dist/components/appointment-booking/hooks/useAppointmentState.d.ts +9 -0
- package/dist/components/appointment-booking/hooks/useAppointmentState.js +125 -0
- package/dist/components/appointment-booking/hooks/useInitializeAddresses.d.ts +1 -0
- package/dist/components/appointment-booking/hooks/useInitializeAddresses.js +55 -0
- package/dist/components/appointment-booking/index.d.ts +5 -0
- package/dist/components/appointment-booking/index.js +3 -0
- package/dist/components/appointment-booking/types.d.ts +291 -0
- package/dist/components/appointment-booking/types.js +49 -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 +12 -139
- package/dist/components/types.js +15 -32
- package/dist/components/uiComponents/SelectDropdown.d.ts +1 -1
- package/dist/components/uiComponents/SelectDropdown.js +24 -24
- 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/enquiry-form/validation.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/react/ThemeProvider.d.ts +2 -1
- package/dist/react/ThemeProvider.js +49 -10
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +1 -1
- 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 +834 -384
- 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 +4 -0
- package/dist/vanilla/components/AppointmentDateTimeModal.d.ts +4 -0
- package/dist/vanilla/components/AppointmentSummaryStep.d.ts +12 -0
- package/dist/vanilla/components/BookingOptionStep.d.ts +14 -0
- package/dist/vanilla/components/DoctorSelectModal.d.ts +5 -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/AppointmentCalender.d.ts +5 -0
- package/dist/vanilla/components/appointment-booking/hooks/index.d.ts +3 -0
- package/dist/vanilla/components/appointment-booking/hooks/useAppointmentFlow.d.ts +8 -0
- package/dist/vanilla/components/appointment-booking/hooks/useAppointmentState.d.ts +9 -0
- package/dist/vanilla/components/appointment-booking/hooks/useInitializeAddresses.d.ts +1 -0
- package/dist/vanilla/components/appointment-booking/index.d.ts +5 -0
- package/dist/vanilla/components/appointment-booking/types.d.ts +291 -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 +12 -139
- package/dist/vanilla/components/uiComponents/SelectDropdown.d.ts +1 -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 +374 -53
- package/dist/vanilla/index.d.ts +3 -1
- package/dist/vanilla/react/ThemeProvider.d.ts +2 -1
- package/dist/vanilla/react/index.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 +6463 -5687
- 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,237 +592,35 @@ 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();
|
|
595
|
+
this.loadSlots();
|
|
555
596
|
},
|
|
556
597
|
});
|
|
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;
|
|
567
|
-
},
|
|
568
|
-
});
|
|
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
|
-
|
|
594
|
-
const canProceed = this.canProceedFromMergedStep();
|
|
595
|
-
return `
|
|
596
|
-
<div class="medos-section-card">
|
|
597
|
-
<div class="medos-section-header">
|
|
598
|
-
${VanillaIcons.mapPin(14)}
|
|
599
|
-
<span class="medos-section-title">Location & Doctor</span>
|
|
600
|
-
</div>
|
|
601
|
-
<div class="medos-section-body">
|
|
602
|
-
<div class="medos-form-group">
|
|
603
|
-
<label class="medos-label">Preferred Location <span class="medos-required">*</span></label>
|
|
604
|
-
<div id="medos-address-select-container"></div>
|
|
605
|
-
</div>
|
|
606
|
-
<div class="medos-form-group">
|
|
607
|
-
<label class="medos-label">Preferred Doctor <span class="medos-required">*</span></label>
|
|
608
|
-
<div id="medos-doctor-select-container"></div>
|
|
609
|
-
</div>
|
|
610
|
-
<div class="medos-form-group">
|
|
611
|
-
<label class="medos-label">Chief Complaint <span class="medos-optional">(optional)</span></label>
|
|
612
|
-
<textarea
|
|
613
|
-
class="medos-textarea"
|
|
614
|
-
id="medos-chief-complaint"
|
|
615
|
-
placeholder="Enter Chief Complaint or Appointment Notes"
|
|
616
|
-
></textarea>
|
|
617
|
-
</div>
|
|
618
|
-
</div>
|
|
619
|
-
</div>
|
|
620
|
-
<div class="medos-actions">
|
|
621
|
-
<button class="medos-btn medos-btn-primary" id="medos-btn-next" ${!canProceed ? "disabled" : ""}>Next</button>
|
|
622
|
-
</div>
|
|
623
|
-
`;
|
|
624
|
-
}
|
|
625
|
-
renderStep1() {
|
|
626
|
-
const dateStr = formatDateToISO(this.state.selectedDate);
|
|
627
|
-
const selectedDoctor = this.doctors.find((d) => d.id === this.state.selectedDoctor);
|
|
628
|
-
const selectedDoctorData = this.doctors.find((d) => d.id === this.state.selectedDoctor);
|
|
629
|
-
const consultationCharge = selectedDoctorData?.consultationCharge ||
|
|
630
|
-
selectedDoctor?.consultationCharge ||
|
|
631
|
-
this.state.consultationCharge ||
|
|
632
|
-
"N/A";
|
|
633
|
-
return `
|
|
634
|
-
<div class="medos-section-card">
|
|
635
|
-
<div class="medos-section-header">
|
|
636
|
-
${VanillaIcons.consultationType(14)}
|
|
637
|
-
<span class="medos-section-title">Consultation Type</span>
|
|
638
|
-
</div>
|
|
639
|
-
<div class="medos-section-body">
|
|
640
|
-
<div class="medos-consultation-options">
|
|
641
|
-
<label class="medos-radio-option ${this.state.consultationMode === "OFFLINE" ? "selected" : ""}">
|
|
642
|
-
<input
|
|
643
|
-
type="radio"
|
|
644
|
-
name="consultationMode"
|
|
645
|
-
value="OFFLINE"
|
|
646
|
-
${this.state.consultationMode === "OFFLINE" ? "checked" : ""}
|
|
647
|
-
class="medos-radio-input"
|
|
648
|
-
/>
|
|
649
|
-
<span class="medos-radio-label">In-Person Visit</span>
|
|
650
|
-
</label>
|
|
651
|
-
<label class="medos-radio-option ${this.state.consultationMode === "ONLINE" ? "selected" : ""}">
|
|
652
|
-
<input
|
|
653
|
-
type="radio"
|
|
654
|
-
name="consultationMode"
|
|
655
|
-
value="ONLINE"
|
|
656
|
-
${this.state.consultationMode === "ONLINE" ? "checked" : ""}
|
|
657
|
-
class="medos-radio-input"
|
|
658
|
-
/>
|
|
659
|
-
<span class="medos-radio-label">Online Consultation</span>
|
|
660
|
-
</label>
|
|
661
|
-
</div>
|
|
662
|
-
<div class="medos-consultation-charge">
|
|
663
|
-
<span class="medos-charge-label">Consultation Charge:</span>
|
|
664
|
-
<span class="medos-charge-value">${consultationCharge !== "N/A"
|
|
665
|
-
? "₹" + consultationCharge
|
|
666
|
-
: consultationCharge}</span>
|
|
667
|
-
</div>
|
|
668
|
-
</div>
|
|
669
|
-
</div>
|
|
670
|
-
|
|
671
|
-
<div class="medos-section-card">
|
|
672
|
-
<div class="medos-section-header">
|
|
673
|
-
${VanillaIcons.dateTime(14)}
|
|
674
|
-
<span class="medos-section-title">Select Date</span>
|
|
675
|
-
</div>
|
|
676
|
-
<div class="medos-section-body">
|
|
677
|
-
<div id="medos-calendar-container"></div>
|
|
678
|
-
</div>
|
|
679
|
-
</div>
|
|
680
|
-
|
|
681
|
-
<div class="medos-actions">
|
|
682
|
-
<button class="medos-btn medos-btn-secondary" id="medos-btn-back">Back</button>
|
|
683
|
-
<button class="medos-btn medos-btn-primary" id="medos-btn-next" ${dateStr ? "" : "disabled"}>Next</button>
|
|
684
|
-
</div>
|
|
685
|
-
`;
|
|
686
|
-
}
|
|
687
|
-
renderStep2() {
|
|
688
|
-
const dateDisplay = this.state.selectedDate
|
|
689
|
-
? this.state.selectedDate.toLocaleDateString("en-US", {
|
|
690
|
-
weekday: "long",
|
|
691
|
-
year: "numeric",
|
|
692
|
-
month: "long",
|
|
693
|
-
day: "numeric",
|
|
694
|
-
})
|
|
695
|
-
: "";
|
|
696
|
-
return `
|
|
697
|
-
<div class="medos-section-card">
|
|
698
|
-
<div class="medos-section-header">
|
|
699
|
-
${VanillaIcons.clock(14)}
|
|
700
|
-
<span class="medos-section-title">Select Time Slot</span>
|
|
701
|
-
</div>
|
|
702
|
-
<div class="medos-section-body">
|
|
703
|
-
<div class="medos-selected-date-display">
|
|
704
|
-
${VanillaIcons.dateTime(16)}
|
|
705
|
-
<span>${dateDisplay}</span>
|
|
706
|
-
</div>
|
|
707
|
-
${this.state.slots.length === 0
|
|
708
|
-
? '<div class="medos-empty-slots">No slots available for selected date</div>'
|
|
709
|
-
: `
|
|
710
|
-
<div class="medos-slots-grid">
|
|
711
|
-
${this.state.slots
|
|
712
|
-
.map((s) => {
|
|
713
|
-
const start = new Date(s.start).toLocaleTimeString([], {
|
|
714
|
-
hour: "2-digit",
|
|
715
|
-
minute: "2-digit",
|
|
716
|
-
});
|
|
717
|
-
const end = new Date(s.end).toLocaleTimeString([], {
|
|
718
|
-
hour: "2-digit",
|
|
719
|
-
minute: "2-digit",
|
|
720
|
-
});
|
|
721
|
-
const selected = this.state.selectedSlot?.start === s.start &&
|
|
722
|
-
this.state.selectedSlot?.end === s.end;
|
|
723
|
-
return `
|
|
724
|
-
<div class="medos-slot-card ${selected ? "selected" : ""}"
|
|
725
|
-
data-slot-id="${this.escapeHtml(s.id || `${s.start}-${s.end}`)}"
|
|
726
|
-
data-slot-start="${this.escapeHtml(s.start)}"
|
|
727
|
-
data-slot-end="${this.escapeHtml(s.end)}">
|
|
728
|
-
<span class="medos-slot-time">${start}</span>
|
|
729
|
-
<span class="medos-slot-separator">-</span>
|
|
730
|
-
<span class="medos-slot-time">${end}</span>
|
|
731
|
-
${selected
|
|
732
|
-
? `<span class="medos-slot-check">${VanillaIcons.check(14)}</span>`
|
|
733
|
-
: ""}
|
|
734
|
-
</div>
|
|
735
|
-
`;
|
|
736
|
-
})
|
|
737
|
-
.join("")}
|
|
738
|
-
</div>
|
|
739
|
-
`}
|
|
740
|
-
</div>
|
|
741
|
-
</div>
|
|
742
|
-
<div class="medos-actions">
|
|
743
|
-
<button class="medos-btn medos-btn-secondary" id="medos-btn-back">Back</button>
|
|
744
|
-
<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>
|
|
745
|
-
</div>
|
|
746
|
-
`;
|
|
747
|
-
}
|
|
748
|
-
renderStep3() {
|
|
623
|
+
renderPhoneVerificationStep() {
|
|
749
624
|
const countryCodeValid = this.state.countryCode && validateCountryCode(this.state.countryCode);
|
|
750
625
|
const phoneValid = this.state.patientPhone && validatePhoneNumber(this.state.patientPhone);
|
|
751
626
|
const canSendOtp = countryCodeValid && phoneValid && !this.state.otpSending;
|
|
@@ -754,10 +629,10 @@ class AppointmentCalendarWidget {
|
|
|
754
629
|
<div class="medos-section-card">
|
|
755
630
|
<div class="medos-section-header">
|
|
756
631
|
${VanillaIcons.phone(14)}
|
|
757
|
-
<span class="medos-section-title">
|
|
632
|
+
<span class="medos-section-title">Search Patient</span>
|
|
758
633
|
</div>
|
|
759
634
|
<div class="medos-section-body">
|
|
760
|
-
<p class="medos-section-description">
|
|
635
|
+
<p class="medos-section-description">Enter Phone Number</p>
|
|
761
636
|
<div class="medos-phone-input-row">
|
|
762
637
|
<div class="medos-country-code-wrapper">
|
|
763
638
|
<div id="medos-country-code-container"></div>
|
|
@@ -767,7 +642,7 @@ class AppointmentCalendarWidget {
|
|
|
767
642
|
type="tel"
|
|
768
643
|
class="medos-input"
|
|
769
644
|
id="medos-phone"
|
|
770
|
-
placeholder="
|
|
645
|
+
placeholder="XXXXXXXXXX"
|
|
771
646
|
value="${this.escapeHtml(this.state.patientPhone)}"
|
|
772
647
|
maxlength="15"
|
|
773
648
|
/>
|
|
@@ -779,8 +654,8 @@ class AppointmentCalendarWidget {
|
|
|
779
654
|
</div>
|
|
780
655
|
</div>
|
|
781
656
|
<div class="medos-actions">
|
|
782
|
-
<button class="medos-btn medos-btn-secondary" id="medos-btn-
|
|
783
|
-
<button class="medos-btn medos-btn-primary" id="medos-btn-send-otp" ${canSendOtp ? "" : "disabled"}>${this.state.otpSending ? "Sending..." : "
|
|
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>
|
|
784
659
|
</div>
|
|
785
660
|
`;
|
|
786
661
|
}
|
|
@@ -789,7 +664,7 @@ class AppointmentCalendarWidget {
|
|
|
789
664
|
<div class="medos-section-card">
|
|
790
665
|
<div class="medos-section-header">
|
|
791
666
|
${VanillaIcons.phone(14)}
|
|
792
|
-
<span class="medos-section-title">
|
|
667
|
+
<span class="medos-section-title">Search Patient</span>
|
|
793
668
|
</div>
|
|
794
669
|
<div class="medos-section-body">
|
|
795
670
|
<div class="medos-verified-badge">
|
|
@@ -800,7 +675,7 @@ class AppointmentCalendarWidget {
|
|
|
800
675
|
</div>
|
|
801
676
|
</div>
|
|
802
677
|
<div class="medos-actions">
|
|
803
|
-
<button class="medos-btn medos-btn-secondary" id="medos-btn-
|
|
678
|
+
<button class="medos-btn medos-btn-secondary" id="medos-btn-cancel">Cancel</button>
|
|
804
679
|
<button class="medos-btn medos-btn-primary" id="medos-btn-next">Continue</button>
|
|
805
680
|
</div>
|
|
806
681
|
`;
|
|
@@ -834,108 +709,605 @@ class AppointmentCalendarWidget {
|
|
|
834
709
|
</div>
|
|
835
710
|
`;
|
|
836
711
|
}
|
|
837
|
-
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
this.state.patientCity &&
|
|
841
|
-
this.state.patientState &&
|
|
842
|
-
this.state.patientCountry &&
|
|
843
|
-
this.state.patientZipcode &&
|
|
844
|
-
this.state.otpVerified;
|
|
712
|
+
renderBookingOptionStep() {
|
|
713
|
+
const hasActivePacks = this.state.userSessionPacks.length > 0;
|
|
714
|
+
const activePack = this.state.userSessionPacks.find((p) => p.remainingSessions > 0);
|
|
845
715
|
return `
|
|
846
716
|
<div class="medos-section-card">
|
|
847
717
|
<div class="medos-section-header">
|
|
848
|
-
${VanillaIcons.
|
|
849
|
-
<span class="medos-section-title">
|
|
718
|
+
${VanillaIcons.calendar(14)}
|
|
719
|
+
<span class="medos-section-title">Choose Booking Option</span>
|
|
850
720
|
</div>
|
|
851
721
|
<div class="medos-section-body">
|
|
852
|
-
<
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
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>
|
|
856
739
|
</div>
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
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>
|
|
860
766
|
</div>
|
|
861
767
|
</div>
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
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() {
|
|
843
|
+
const canProceed = this.canProceedFromMergedStep();
|
|
844
|
+
return `
|
|
845
|
+
<div style="border:1px solid #e5e7eb;border-radius:12px;margin-bottom:24px;background:#fff;">
|
|
846
|
+
<div style="background:#F9FAFB;padding:16px 20px;display:flex;align-items:center;gap:12px;border-bottom:1px solid #E5E7EB;">
|
|
847
|
+
${VanillaIcons.mapPin(18)}
|
|
848
|
+
<h3 style="font-size:18px;font-weight:600;margin:0;">Location & Doctor</h3>
|
|
849
|
+
</div>
|
|
850
|
+
<div style="padding:24px;">
|
|
851
|
+
<div style="margin-bottom:20px;">
|
|
852
|
+
<label style="display:block;font-size:13px;margin-bottom:6px;color:#374151;">
|
|
853
|
+
Preferred Location <span style="color:#EF4444">*</span>
|
|
854
|
+
</label>
|
|
855
|
+
<div id="medos-address-select-container"></div>
|
|
856
|
+
</div>
|
|
857
|
+
<div style="margin-bottom:20px;">
|
|
858
|
+
<label style="display:block;font-size:13px;margin-bottom:6px;color:#374151;">
|
|
859
|
+
Preferred Doctor <span style="color:#EF4444">*</span>
|
|
860
|
+
</label>
|
|
861
|
+
<div id="medos-doctor-select-container"></div>
|
|
862
|
+
</div>
|
|
863
|
+
<div style="margin-bottom:20px;">
|
|
864
|
+
<label style="display:block;font-size:13px;margin-bottom:6px;color:#374151;">
|
|
865
|
+
Chief Complaint <span style="color:#6B7280">(optional)</span>
|
|
866
|
+
</label>
|
|
867
|
+
<textarea
|
|
868
|
+
style="width:100%;padding:10px 12px;border-radius:8px;border:1px solid #e6e9ef;font-size:14px;box-sizing:border-box;"
|
|
869
|
+
class="medos-textarea"
|
|
870
|
+
id="medos-chief-complaint"
|
|
871
|
+
placeholder="Enter Chief Complaint or Appointment Notes"
|
|
872
|
+
></textarea>
|
|
873
|
+
</div>
|
|
874
|
+
</div>
|
|
875
|
+
</div>
|
|
876
|
+
<div style="display:flex;gap:8px;margin-top:16px;justify-content:flex-end;">
|
|
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>
|
|
879
|
+
</div>
|
|
880
|
+
`;
|
|
881
|
+
}
|
|
882
|
+
renderNewAppointmentStep() {
|
|
883
|
+
const dateStr = formatDateToISO(this.state.selectedDate);
|
|
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
|
+
: "";
|
|
902
|
+
return `
|
|
903
|
+
<div class="medos-section-card">
|
|
904
|
+
<div class="medos-section-header">
|
|
905
|
+
${VanillaIcons.consultationType(14)}
|
|
906
|
+
<span class="medos-section-title">Consultation Type</span>
|
|
907
|
+
</div>
|
|
908
|
+
<div class="medos-section-body">
|
|
909
|
+
<label class="medos-form-label">Consultation Mode</label>
|
|
910
|
+
<div class="medos-consultation-options">
|
|
911
|
+
<label class="medos-radio-option ${this.state.consultationMode === "OFFLINE" ? "selected" : ""}">
|
|
912
|
+
<input
|
|
913
|
+
type="radio"
|
|
914
|
+
name="consultationMode"
|
|
915
|
+
value="OFFLINE"
|
|
916
|
+
${this.state.consultationMode === "OFFLINE" ? "checked" : ""}
|
|
917
|
+
class="medos-radio-input"
|
|
918
|
+
/>
|
|
919
|
+
<span class="medos-radio-label">Online</span>
|
|
920
|
+
</label>
|
|
921
|
+
<label class="medos-radio-option ${this.state.consultationMode === "ONLINE" ? "selected" : ""}">
|
|
922
|
+
<input
|
|
923
|
+
type="radio"
|
|
924
|
+
name="consultationMode"
|
|
925
|
+
value="ONLINE"
|
|
926
|
+
${this.state.consultationMode === "ONLINE" ? "checked" : ""}
|
|
927
|
+
class="medos-radio-input"
|
|
928
|
+
/>
|
|
929
|
+
<span class="medos-radio-label">Offline</span>
|
|
930
|
+
</label>
|
|
931
|
+
</div>
|
|
932
|
+
</div>
|
|
933
|
+
</div>
|
|
934
|
+
|
|
935
|
+
<div class="medos-section-card">
|
|
936
|
+
<div class="medos-section-header">
|
|
937
|
+
${VanillaIcons.dateTime(14)}
|
|
938
|
+
<span class="medos-section-title">Date & Time</span>
|
|
939
|
+
</div>
|
|
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>
|
|
871
945
|
</div>
|
|
872
|
-
<div class="medos-
|
|
873
|
-
<label class="medos-label">
|
|
874
|
-
|
|
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>'
|
|
950
|
+
: `
|
|
951
|
+
<div class="medos-slots-grid-compact">
|
|
952
|
+
${this.state.slots
|
|
953
|
+
.map((s) => {
|
|
954
|
+
const start = new Date(s.start).toLocaleTimeString([], {
|
|
955
|
+
hour: "2-digit",
|
|
956
|
+
minute: "2-digit",
|
|
957
|
+
});
|
|
958
|
+
const end = new Date(s.end).toLocaleTimeString([], {
|
|
959
|
+
hour: "2-digit",
|
|
960
|
+
minute: "2-digit",
|
|
961
|
+
});
|
|
962
|
+
const selected = this.state.selectedSlot?.start === s.start &&
|
|
963
|
+
this.state.selectedSlot?.end === s.end;
|
|
964
|
+
return `
|
|
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
|
+
`;
|
|
972
|
+
})
|
|
973
|
+
.join("")}
|
|
974
|
+
</div>
|
|
975
|
+
`}
|
|
875
976
|
</div>
|
|
876
977
|
</div>
|
|
877
978
|
</div>
|
|
878
979
|
|
|
980
|
+
<div class="medos-actions">
|
|
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>
|
|
984
|
+
</div>
|
|
985
|
+
`;
|
|
986
|
+
}
|
|
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
|
+
];
|
|
1073
|
+
return `
|
|
879
1074
|
<div class="medos-section-card">
|
|
880
1075
|
<div class="medos-section-header">
|
|
881
|
-
${VanillaIcons.
|
|
882
|
-
<span class="medos-section-title">
|
|
1076
|
+
${VanillaIcons.users(14)}
|
|
1077
|
+
<span class="medos-section-title">Select Patient</span>
|
|
883
1078
|
</div>
|
|
884
1079
|
<div class="medos-section-body">
|
|
885
|
-
<div class="medos-
|
|
886
|
-
|
|
887
|
-
|
|
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("")}
|
|
888
1098
|
</div>
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
1099
|
+
|
|
1100
|
+
<button class="medos-add-patient-btn" id="medos-btn-add-patient">
|
|
1101
|
+
${VanillaIcons.plus(16)} New Patient
|
|
1102
|
+
</button>
|
|
1103
|
+
</div>
|
|
1104
|
+
</div>
|
|
1105
|
+
<div class="medos-actions">
|
|
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>
|
|
1109
|
+
</div>
|
|
1110
|
+
`;
|
|
1111
|
+
}
|
|
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";
|
|
1157
|
+
return `
|
|
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>
|
|
1162
|
+
</div>
|
|
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>
|
|
1171
|
+
</div>
|
|
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>
|
|
1189
|
+
</div>
|
|
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>
|
|
893
1199
|
</div>
|
|
894
|
-
<div class="medos-
|
|
895
|
-
<
|
|
896
|
-
<
|
|
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>
|
|
897
1205
|
</div>
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
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>
|
|
903
1213
|
</div>
|
|
904
|
-
<div class="medos-
|
|
905
|
-
<
|
|
906
|
-
<
|
|
1214
|
+
<div class="medos-summary-row">
|
|
1215
|
+
<span class="medos-summary-label">Sessions:</span>
|
|
1216
|
+
<span class="medos-summary-value">${sessionInfo || "1 consultation"}</span>
|
|
907
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
|
+
: ""}
|
|
908
1233
|
</div>
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
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>
|
|
912
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>
|
|
913
1248
|
</div>
|
|
914
|
-
</div>
|
|
915
|
-
|
|
916
|
-
<div class="medos-actions">
|
|
917
|
-
<button class="medos-btn medos-btn-secondary" id="medos-btn-back">Back</button>
|
|
918
|
-
<button class="medos-btn medos-btn-primary" id="medos-btn-submit" ${canSubmit && !this.state.loading ? "" : "disabled"}>${this.state.loading ? "Booking..." : "Book Appointment"}</button>
|
|
919
1249
|
</div>
|
|
920
1250
|
`;
|
|
921
1251
|
}
|
|
922
|
-
|
|
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;
|
|
923
1267
|
return `
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1268
|
+
<div class="medos-success-container">
|
|
1269
|
+
<div class="medos-success-header">
|
|
1270
|
+
<h2>Appointment Confirmed</h2>
|
|
1271
|
+
</div>
|
|
1272
|
+
|
|
1273
|
+
<div class="medos-success-content">
|
|
1274
|
+
<div class="medos-success-badge">
|
|
1275
|
+
${VanillaIcons.successBadge(64)}
|
|
1276
|
+
</div>
|
|
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
|
+
: ""}
|
|
1293
|
+
</div>
|
|
1294
|
+
</div>
|
|
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>
|
|
1305
|
+
</div>
|
|
1306
|
+
`
|
|
1307
|
+
: ""}
|
|
1308
|
+
</div>
|
|
1309
|
+
</div>
|
|
1310
|
+
`;
|
|
939
1311
|
}
|
|
940
1312
|
formatDate(dateStr) {
|
|
941
1313
|
try {
|
|
@@ -973,66 +1345,6 @@ class AppointmentCalendarWidget {
|
|
|
973
1345
|
}
|
|
974
1346
|
return 60;
|
|
975
1347
|
}
|
|
976
|
-
renderStep5() {
|
|
977
|
-
const duration = this.calculateDuration();
|
|
978
|
-
const selectedAddress = this.state.addresses.find((addr) => addr.id === this.state.selectedAddress);
|
|
979
|
-
const appointmentDate = this.state.selectedDate
|
|
980
|
-
? this.formatDate(formatDateToISO(this.state.selectedDate))
|
|
981
|
-
: "";
|
|
982
|
-
const startTime = this.state.selectedSlot?.start
|
|
983
|
-
? this.formatTime(new Date(this.state.selectedSlot.start).toTimeString().slice(0, 5))
|
|
984
|
-
: "";
|
|
985
|
-
return `
|
|
986
|
-
<div style="display: flex; flex-direction: column; padding: 0; font-family: Arial, sans-serif; background: #f8f9fa; min-height: 500px;">
|
|
987
|
-
<!-- Header with border -->
|
|
988
|
-
<div style="padding: 20px 24px; font-size: 24px; font-weight: bold; color: #1a365d; border-bottom: 2px solid #e2e8f0; background: white;">
|
|
989
|
-
Appointment Confirmed
|
|
990
|
-
</div>
|
|
991
|
-
|
|
992
|
-
<!-- Main content with border -->
|
|
993
|
-
<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;">
|
|
994
|
-
<!-- Success Title -->
|
|
995
|
-
<h2 style="font-size: 20px; font-weight: 600; color: #006E0F; margin: 0 0 24px 0;">
|
|
996
|
-
Appointment Confirmed
|
|
997
|
-
</h2>
|
|
998
|
-
|
|
999
|
-
<!-- Success Icon -->
|
|
1000
|
-
<div style="margin-bottom: 32px;">
|
|
1001
|
-
${this.renderSuccessIcon()}
|
|
1002
|
-
</div>
|
|
1003
|
-
|
|
1004
|
-
<!-- Appointment Details -->
|
|
1005
|
-
<div style="width: 100%; max-width: 500px; margin-bottom: 32px;">
|
|
1006
|
-
<h3 style="font-size: 18px; font-weight: 600; color: #006E0F; margin-bottom: 24px;">
|
|
1007
|
-
Appointment Details
|
|
1008
|
-
</h3>
|
|
1009
|
-
|
|
1010
|
-
<div style="display: flex; flex-direction: column; gap: 12px; font-size: 16px; line-height: 1.6; color: #4a5568;">
|
|
1011
|
-
<div><strong style="color: #006E0F;">Patient:</strong> ${this.escapeHtml(this.state.patientName || "Patient")}</div>
|
|
1012
|
-
<div><strong style="color: #006E0F;">Visitation Type:</strong> ${this.state.consultationMode === "ONLINE"
|
|
1013
|
-
? "Online Consultation"
|
|
1014
|
-
: "General"}</div>
|
|
1015
|
-
${appointmentDate
|
|
1016
|
-
? `<div><strong style="color: #006E0F;">Date:</strong> ${appointmentDate}</div>`
|
|
1017
|
-
: ""}
|
|
1018
|
-
${startTime
|
|
1019
|
-
? `<div><strong style="color: #006E0F;">Time:</strong> ${startTime}</div>`
|
|
1020
|
-
: ""}
|
|
1021
|
-
<div><strong style="color: #006E0F;">Duration:</strong> ~${duration} minutes</div>
|
|
1022
|
-
${selectedAddress?.label
|
|
1023
|
-
? `<div><strong style="color: #006E0F;">Location:</strong> ${this.escapeHtml(selectedAddress.label)}</div>`
|
|
1024
|
-
: ""}
|
|
1025
|
-
</div>
|
|
1026
|
-
</div>
|
|
1027
|
-
|
|
1028
|
-
<!-- Confirmation Message -->
|
|
1029
|
-
<div style="font-size: 16px; font-style: italic; color: #718096; text-align: center; max-width: 600px; line-height: 1.5;">
|
|
1030
|
-
A confirmation email has been sent to the Patient's Email address.
|
|
1031
|
-
</div>
|
|
1032
|
-
</div>
|
|
1033
|
-
</div>
|
|
1034
|
-
`;
|
|
1035
|
-
}
|
|
1036
1348
|
attachEventListeners() {
|
|
1037
1349
|
const consultationRadios = this.container.querySelectorAll('input[name="consultationMode"]');
|
|
1038
1350
|
consultationRadios.forEach((radio) => {
|
|
@@ -1042,7 +1354,7 @@ class AppointmentCalendarWidget {
|
|
|
1042
1354
|
this.render();
|
|
1043
1355
|
});
|
|
1044
1356
|
});
|
|
1045
|
-
const slotCards = this.container.querySelectorAll(".medos-slot-card");
|
|
1357
|
+
const slotCards = this.container.querySelectorAll(".medos-slot-card, .medos-slot-btn");
|
|
1046
1358
|
slotCards.forEach((card) => {
|
|
1047
1359
|
card.addEventListener("click", () => {
|
|
1048
1360
|
const slotId = card.dataset.slotId;
|
|
@@ -1124,13 +1436,6 @@ class AppointmentCalendarWidget {
|
|
|
1124
1436
|
this.updateSubmitButtonState();
|
|
1125
1437
|
});
|
|
1126
1438
|
}
|
|
1127
|
-
const patientGenderSelect = this.container.querySelector("#medos-patient-gender");
|
|
1128
|
-
if (patientGenderSelect) {
|
|
1129
|
-
patientGenderSelect.addEventListener("change", (e) => {
|
|
1130
|
-
const target = e.target;
|
|
1131
|
-
this.state.patientGender = target.value;
|
|
1132
|
-
});
|
|
1133
|
-
}
|
|
1134
1439
|
const patientAddressInput = this.container.querySelector("#medos-patient-address");
|
|
1135
1440
|
if (patientAddressInput) {
|
|
1136
1441
|
patientAddressInput.addEventListener("input", (e) => {
|
|
@@ -1178,6 +1483,65 @@ class AppointmentCalendarWidget {
|
|
|
1178
1483
|
this.state.patientLandmark = target.value;
|
|
1179
1484
|
});
|
|
1180
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
|
+
});
|
|
1181
1545
|
const nextBtn = this.container.querySelector("#medos-btn-next");
|
|
1182
1546
|
if (nextBtn) {
|
|
1183
1547
|
nextBtn.addEventListener("click", () => {
|
|
@@ -1186,10 +1550,22 @@ class AppointmentCalendarWidget {
|
|
|
1186
1550
|
}
|
|
1187
1551
|
});
|
|
1188
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
|
+
}
|
|
1189
1561
|
const backBtn = this.container.querySelector("#medos-btn-back");
|
|
1190
1562
|
if (backBtn) {
|
|
1191
1563
|
backBtn.addEventListener("click", () => this.goBack());
|
|
1192
1564
|
}
|
|
1565
|
+
const cancelBtn = this.container.querySelector("#medos-btn-cancel");
|
|
1566
|
+
if (cancelBtn) {
|
|
1567
|
+
cancelBtn.addEventListener("click", () => this.reset());
|
|
1568
|
+
}
|
|
1193
1569
|
const sendOtpBtn = this.container.querySelector("#medos-btn-send-otp");
|
|
1194
1570
|
if (sendOtpBtn) {
|
|
1195
1571
|
sendOtpBtn.addEventListener("click", () => {
|
|
@@ -1219,6 +1595,14 @@ class AppointmentCalendarWidget {
|
|
|
1219
1595
|
this.sendOtp();
|
|
1220
1596
|
});
|
|
1221
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
|
+
}
|
|
1222
1606
|
const submitBtn = this.container.querySelector("#medos-btn-submit");
|
|
1223
1607
|
if (submitBtn) {
|
|
1224
1608
|
submitBtn.addEventListener("click", () => {
|
|
@@ -1231,6 +1615,72 @@ class AppointmentCalendarWidget {
|
|
|
1231
1615
|
if (bookAnotherBtn) {
|
|
1232
1616
|
bookAnotherBtn.addEventListener("click", () => this.reset());
|
|
1233
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
|
+
];
|
|
1234
1684
|
}
|
|
1235
1685
|
escapeHtml(text) {
|
|
1236
1686
|
const div = document.createElement("div");
|