medos-sdk 1.1.12 → 1.1.14
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/README.md +831 -32
- package/dist/components/appointment-booking/types.d.ts +1 -0
- package/dist/components/appointment-booking/types.js +1 -0
- package/dist/components/constants/index.d.ts +1 -1
- package/dist/components/constants/index.js +1 -1
- package/dist/services/AuthService.js +1 -1
- package/dist/vanilla/AppointmentCalendarWidget.d.ts +76 -0
- package/dist/vanilla/AppointmentCalendarWidget.js +819 -563
- package/dist/vanilla/components/appointment-booking/types.d.ts +1 -0
- package/dist/vanilla/components/constants/index.d.ts +1 -1
- package/dist/vanilla/components/theme-injector.js +527 -0
- package/dist/vanilla/enquiry-widget.js +1124 -3802
- package/dist/vanilla/vanilla/AppointmentCalendarWidget.d.ts +76 -0
- package/dist/vanilla/widget-themed.css +1291 -0
- package/dist/vanilla/widget.css +157 -0
- package/dist/vanilla/widget.js +7667 -10020
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -28,9 +28,22 @@ npm install medos-sdk
|
|
|
28
28
|
- [Usage](#usage)
|
|
29
29
|
- [React Integration](#react-integration)
|
|
30
30
|
- [Vanilla JavaScript](#vanilla-javascript--html-integration)
|
|
31
|
+
- [Installation Options](#installation-options)
|
|
32
|
+
- [Appointment Booking Widget](#appointment-booking-widget)
|
|
33
|
+
- [Enquiry Form Widget](#enquiry-form-widget)
|
|
34
|
+
- [Widget Step Flow](#widget-step-flow)
|
|
35
|
+
- [Configuration Options](#configuration-options)
|
|
36
|
+
- [Authentication Methods](#authentication-methods)
|
|
37
|
+
- [Server-Side Integration Examples](#server-side-integration-examples)
|
|
38
|
+
- [Multiple Widgets on Same Page](#multiple-widgets-on-same-page)
|
|
39
|
+
- [Global API Reference](#global-api-reference)
|
|
40
|
+
- [Widget Lifecycle Management](#widget-lifecycle-management)
|
|
41
|
+
- [Theme Customization](#theme-customization)
|
|
42
|
+
- [Troubleshooting Guide](#troubleshooting-guide)
|
|
31
43
|
- [TypeScript](#typescript)
|
|
32
44
|
- [API Reference](#api-reference)
|
|
33
45
|
- [Error Handling](#error-handling)
|
|
46
|
+
- [Examples and Documentation](#examples-and-documentation)
|
|
34
47
|
- [Requirements](#requirements)
|
|
35
48
|
|
|
36
49
|
## Quick Start
|
|
@@ -359,16 +372,40 @@ import { AppointmentCalender } from "medos-sdk/react";
|
|
|
359
372
|
|
|
360
373
|
## Vanilla JavaScript / HTML Integration
|
|
361
374
|
|
|
362
|
-
For websites using plain HTML, CSS, and JavaScript (no React), use the vanilla widget.
|
|
375
|
+
For websites using plain HTML, CSS, and JavaScript (no React), use the vanilla widget. The SDK provides two widgets: **Appointment Booking** and **Enquiry Form**.
|
|
363
376
|
|
|
364
|
-
### Installation
|
|
377
|
+
### Installation Options
|
|
365
378
|
|
|
366
|
-
|
|
379
|
+
#### Option 1: NPM Package (Recommended)
|
|
367
380
|
|
|
368
|
-
|
|
369
|
-
|
|
381
|
+
```bash
|
|
382
|
+
npm install medos-sdk
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
After building, you'll find the widget files in:
|
|
386
|
+
|
|
387
|
+
- `dist/vanilla/widget.js` - JavaScript bundle (UMD format)
|
|
388
|
+
- `dist/vanilla/widget.css` - Base stylesheet
|
|
389
|
+
- `dist/vanilla/widget-themed.css` - Advanced theming stylesheet
|
|
390
|
+
|
|
391
|
+
#### Option 2: CDN Integration
|
|
392
|
+
|
|
393
|
+
Load directly from CDN (replace with actual CDN URL when available):
|
|
394
|
+
|
|
395
|
+
```html
|
|
396
|
+
<!-- CSS -->
|
|
397
|
+
<link
|
|
398
|
+
rel="stylesheet"
|
|
399
|
+
href="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.css"
|
|
400
|
+
/>
|
|
401
|
+
|
|
402
|
+
<!-- JavaScript -->
|
|
403
|
+
<script src="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.js"></script>
|
|
404
|
+
```
|
|
370
405
|
|
|
371
|
-
###
|
|
406
|
+
### Appointment Booking Widget
|
|
407
|
+
|
|
408
|
+
#### Basic Usage
|
|
372
409
|
|
|
373
410
|
```html
|
|
374
411
|
<!DOCTYPE html>
|
|
@@ -381,6 +418,7 @@ The widget is available as a bundled UMD module. After building the package, you
|
|
|
381
418
|
|
|
382
419
|
<script src="path/to/widget.js"></script>
|
|
383
420
|
<script>
|
|
421
|
+
// Method 1: Global API (Recommended)
|
|
384
422
|
window.MedosAppointmentCalendar.init({
|
|
385
423
|
containerId: "appointment-calendar",
|
|
386
424
|
apiKey: "your-api-key",
|
|
@@ -392,31 +430,234 @@ The widget is available as a bundled UMD module. After building the package, you
|
|
|
392
430
|
console.log("Appointment booked successfully!");
|
|
393
431
|
},
|
|
394
432
|
});
|
|
433
|
+
|
|
434
|
+
// Method 2: Class-based API (Alternative)
|
|
435
|
+
// const widget = new window.MedosAppointmentWidget('appointment-calendar', {
|
|
436
|
+
// apiKey: 'your-api-key'
|
|
437
|
+
// });
|
|
395
438
|
</script>
|
|
396
439
|
</body>
|
|
397
440
|
</html>
|
|
398
441
|
```
|
|
399
442
|
|
|
400
|
-
|
|
443
|
+
#### CDN Integration Example
|
|
401
444
|
|
|
402
|
-
|
|
445
|
+
```html
|
|
446
|
+
<!DOCTYPE html>
|
|
447
|
+
<html>
|
|
448
|
+
<head>
|
|
449
|
+
<link
|
|
450
|
+
rel="stylesheet"
|
|
451
|
+
href="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.css"
|
|
452
|
+
/>
|
|
453
|
+
</head>
|
|
454
|
+
<body>
|
|
455
|
+
<div id="appointment-widget"></div>
|
|
456
|
+
|
|
457
|
+
<script src="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.js"></script>
|
|
458
|
+
<script>
|
|
459
|
+
window.MedosAppointmentCalendar.init({
|
|
460
|
+
containerId: "appointment-widget",
|
|
461
|
+
sessionToken: "your-session-token", // Obtained from your server
|
|
462
|
+
baseURL: "https://api.medos.one/v1",
|
|
463
|
+
onError: (err) => console.error(err),
|
|
464
|
+
onSuccess: () => console.log("Success!"),
|
|
465
|
+
});
|
|
466
|
+
</script>
|
|
467
|
+
</body>
|
|
468
|
+
</html>
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Enquiry Form Widget
|
|
472
|
+
|
|
473
|
+
#### Basic Usage
|
|
403
474
|
|
|
404
475
|
```html
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
476
|
+
<!DOCTYPE html>
|
|
477
|
+
<html>
|
|
478
|
+
<head>
|
|
479
|
+
<link rel="stylesheet" href="path/to/widget.css" />
|
|
480
|
+
</head>
|
|
481
|
+
<body>
|
|
482
|
+
<div id="enquiry-form"></div>
|
|
483
|
+
|
|
484
|
+
<script src="path/to/widget.js"></script>
|
|
485
|
+
<script>
|
|
486
|
+
// Method 1: Global API (Recommended)
|
|
487
|
+
window.MedosEnquiryForm.init({
|
|
488
|
+
containerId: "enquiry-form",
|
|
489
|
+
apiKey: "your-api-key",
|
|
490
|
+
onError: (err) => console.error(err),
|
|
491
|
+
onSuccess: (enquiry) => {
|
|
492
|
+
console.log("Enquiry submitted:", enquiry);
|
|
493
|
+
alert("Thank you! Your enquiry has been submitted.");
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// Method 2: Class-based API (Alternative)
|
|
498
|
+
// const widget = new window.MedosEnquiryWidget('enquiry-form', {
|
|
499
|
+
// apiKey: 'your-api-key'
|
|
500
|
+
// });
|
|
501
|
+
</script>
|
|
502
|
+
</body>
|
|
503
|
+
</html>
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Widget Step Flow
|
|
507
|
+
|
|
508
|
+
#### Appointment Booking Steps
|
|
509
|
+
|
|
510
|
+
The appointment widget follows this exact step sequence (matching React component):
|
|
511
|
+
|
|
512
|
+
1. **Step 0: Phone Verification** - Country code selection, phone input, OTP verification
|
|
513
|
+
2. **Step 1: Booking Option Selection** - Session packs vs. new appointment (auto-skipped if no packages)
|
|
514
|
+
3. **Step 2: Location & Doctor Selection** - Address and doctor selection with chief complaint
|
|
515
|
+
4. **Step 3: Date & Time Selection** - Calendar, consultation mode, and time slot selection
|
|
516
|
+
5. **Step 4: Patient Selection** - Choose existing patient or create new
|
|
517
|
+
6. **Step 5: Patient Details Form** - Patient information and address (for new patients)
|
|
518
|
+
7. **Step 6: Appointment Summary** - Review all details and cost breakdown
|
|
519
|
+
8. **Step 7: Success Confirmation** - Confirmation with appointment details
|
|
520
|
+
|
|
521
|
+
#### Enquiry Form Steps
|
|
522
|
+
|
|
523
|
+
1. **Step 1: Contact Information** - Name, email, phone number
|
|
524
|
+
2. **Step 2: Inquiry Details** - Subject and detailed message
|
|
525
|
+
3. **Step 3: Contact Preference** - Preferred contact method (email, phone, both)
|
|
526
|
+
4. **Step 4: Success Confirmation** - Submission confirmation
|
|
527
|
+
|
|
528
|
+
### Configuration Options
|
|
529
|
+
|
|
530
|
+
Complete API reference for widget initialization:
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
interface WidgetOptions {
|
|
534
|
+
containerId: string; // Required: ID of container element
|
|
535
|
+
apiKey?: string; // Optional: API key for authentication
|
|
536
|
+
sessionToken?: string; // Optional: Session token (alternative to apiKey)
|
|
537
|
+
baseURL?: string; // Optional: API base URL (default: https://api.medos.one/v1)
|
|
538
|
+
onError?: (error: Error) => void; // Optional: Error callback
|
|
539
|
+
onSuccess?: (data?: any) => void; // Optional: Success callback
|
|
540
|
+
onStepChange?: (step: number) => void; // Optional: Step change callback
|
|
541
|
+
theme?: "default" | "modern" | string; // Optional: Theme selection
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
#### Configuration Examples
|
|
546
|
+
|
|
547
|
+
**Basic Configuration:**
|
|
548
|
+
|
|
549
|
+
```javascript
|
|
550
|
+
window.MedosAppointmentCalendar.init({
|
|
551
|
+
containerId: "appointment-widget",
|
|
552
|
+
apiKey: "your-api-key",
|
|
553
|
+
});
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**Advanced Configuration with Callbacks:**
|
|
557
|
+
|
|
558
|
+
```javascript
|
|
559
|
+
window.MedosAppointmentCalendar.init({
|
|
560
|
+
containerId: "appointment-widget",
|
|
561
|
+
sessionToken: "user-session-token",
|
|
562
|
+
baseURL: "https://api.medos.one/v1",
|
|
563
|
+
theme: "modern",
|
|
564
|
+
onError: (error) => {
|
|
565
|
+
console.error("Widget error:", error);
|
|
566
|
+
// Show user-friendly error message
|
|
567
|
+
document.getElementById("error-message").textContent =
|
|
568
|
+
"Unable to load appointment booking. Please try again.";
|
|
569
|
+
document.getElementById("error-message").style.display = "block";
|
|
570
|
+
},
|
|
571
|
+
onSuccess: (appointment) => {
|
|
572
|
+
console.log("Appointment booked successfully", appointment);
|
|
573
|
+
// Redirect or show success message
|
|
574
|
+
window.location.href = "/appointment-confirmation";
|
|
575
|
+
},
|
|
576
|
+
onStepChange: (step) => {
|
|
577
|
+
console.log("Current step:", step);
|
|
578
|
+
// Track user progress for analytics
|
|
579
|
+
if (typeof analytics !== "undefined") {
|
|
580
|
+
analytics.track("appointment_step_change", { step });
|
|
581
|
+
}
|
|
582
|
+
},
|
|
583
|
+
});
|
|
413
584
|
```
|
|
414
585
|
|
|
415
|
-
|
|
586
|
+
**Environment-Specific Configuration:**
|
|
587
|
+
|
|
588
|
+
```javascript
|
|
589
|
+
const isProduction = window.location.hostname !== "localhost";
|
|
590
|
+
const config = {
|
|
591
|
+
containerId: "appointment-widget",
|
|
592
|
+
baseURL: isProduction
|
|
593
|
+
? "https://api.medos.one/v1"
|
|
594
|
+
: "https://dev-api.medos.one/v1",
|
|
595
|
+
sessionToken: await getSessionToken(), // Fetch from your backend
|
|
596
|
+
onError: (error) => handleWidgetError(error),
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
window.MedosAppointmentCalendar.init(config);
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### Authentication Methods
|
|
603
|
+
|
|
604
|
+
#### Using Session Token (Recommended for Production)
|
|
605
|
+
|
|
606
|
+
For better security, obtain the session token server-side:
|
|
607
|
+
|
|
608
|
+
```javascript
|
|
609
|
+
// Fetch session token from your backend
|
|
610
|
+
async function initializeWidget() {
|
|
611
|
+
try {
|
|
612
|
+
const response = await fetch("/api/get-session-token");
|
|
613
|
+
const { sessionToken } = await response.json();
|
|
614
|
+
|
|
615
|
+
window.MedosAppointmentCalendar.init({
|
|
616
|
+
containerId: "appointment-calendar",
|
|
617
|
+
sessionToken: sessionToken,
|
|
618
|
+
baseURL: "https://api.medos.one/v1",
|
|
619
|
+
onError: (err) => console.error(err),
|
|
620
|
+
});
|
|
621
|
+
} catch (error) {
|
|
622
|
+
console.error("Failed to get session token:", error);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
initializeWidget();
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
#### Using API Key (Development Only)
|
|
630
|
+
|
|
631
|
+
```javascript
|
|
632
|
+
window.MedosAppointmentCalendar.init({
|
|
633
|
+
containerId: "appointment-calendar",
|
|
634
|
+
apiKey: "your-api-key", // Only for development/testing
|
|
635
|
+
onError: (err) => console.error(err),
|
|
636
|
+
});
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
### Server-Side Integration Examples
|
|
640
|
+
|
|
641
|
+
#### PHP Integration
|
|
416
642
|
|
|
417
643
|
```php
|
|
418
644
|
<?php
|
|
419
645
|
// Get session token from your backend
|
|
646
|
+
function getSessionTokenFromBackend() {
|
|
647
|
+
// Your implementation to get session token
|
|
648
|
+
// This should call your backend API that exchanges API key for session token
|
|
649
|
+
$apiKey = 'your-api-key';
|
|
650
|
+
$response = file_get_contents('https://api.medos.one/v1/auth/session', false, stream_context_create([
|
|
651
|
+
'http' => [
|
|
652
|
+
'method' => 'POST',
|
|
653
|
+
'header' => "Authorization: Bearer $apiKey\r\nContent-Type: application/json\r\n",
|
|
654
|
+
'content' => json_encode(['apiKey' => $apiKey])
|
|
655
|
+
]
|
|
656
|
+
]));
|
|
657
|
+
$data = json_decode($response, true);
|
|
658
|
+
return $data['sessionToken'];
|
|
659
|
+
}
|
|
660
|
+
|
|
420
661
|
$sessionToken = getSessionTokenFromBackend();
|
|
421
662
|
?>
|
|
422
663
|
<!DOCTYPE html>
|
|
@@ -431,9 +672,14 @@ $sessionToken = getSessionTokenFromBackend();
|
|
|
431
672
|
window.MedosAppointmentCalendar.init({
|
|
432
673
|
containerId: 'appointment-calendar',
|
|
433
674
|
sessionToken: '<?php echo htmlspecialchars($sessionToken); ?>',
|
|
434
|
-
onError: (err)
|
|
675
|
+
onError: function(err) {
|
|
435
676
|
console.error('Error:', err);
|
|
436
677
|
alert('An error occurred. Please try again.');
|
|
678
|
+
},
|
|
679
|
+
onSuccess: function() {
|
|
680
|
+
console.log('Appointment booked successfully!');
|
|
681
|
+
// Redirect to confirmation page
|
|
682
|
+
window.location.href = '/appointment-confirmation.php';
|
|
437
683
|
}
|
|
438
684
|
});
|
|
439
685
|
</script>
|
|
@@ -441,30 +687,555 @@ $sessionToken = getSessionTokenFromBackend();
|
|
|
441
687
|
</html>
|
|
442
688
|
```
|
|
443
689
|
|
|
444
|
-
|
|
690
|
+
#### Node.js/Express Integration
|
|
691
|
+
|
|
692
|
+
```javascript
|
|
693
|
+
// Backend route to get session token
|
|
694
|
+
app.get("/api/session-token", async (req, res) => {
|
|
695
|
+
try {
|
|
696
|
+
const response = await axios.post("https://api.medos.one/v1/auth/session", {
|
|
697
|
+
apiKey: process.env.MEDOS_API_KEY,
|
|
698
|
+
});
|
|
699
|
+
res.json({ sessionToken: response.data.sessionToken });
|
|
700
|
+
} catch (error) {
|
|
701
|
+
res.status(500).json({ error: "Failed to get session token" });
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
```html
|
|
707
|
+
<!-- Frontend HTML -->
|
|
708
|
+
<!DOCTYPE html>
|
|
709
|
+
<html>
|
|
710
|
+
<head>
|
|
711
|
+
<link rel="stylesheet" href="/dist/vanilla/widget.css" />
|
|
712
|
+
</head>
|
|
713
|
+
<body>
|
|
714
|
+
<div id="appointment-widget"></div>
|
|
715
|
+
<script src="/dist/vanilla/widget.js"></script>
|
|
716
|
+
<script>
|
|
717
|
+
fetch("/api/session-token")
|
|
718
|
+
.then((response) => response.json())
|
|
719
|
+
.then((data) => {
|
|
720
|
+
window.MedosAppointmentCalendar.init({
|
|
721
|
+
containerId: "appointment-widget",
|
|
722
|
+
sessionToken: data.sessionToken,
|
|
723
|
+
onError: (err) => console.error(err),
|
|
724
|
+
onSuccess: () => console.log("Success!"),
|
|
725
|
+
});
|
|
726
|
+
})
|
|
727
|
+
.catch((error) => console.error("Failed to initialize widget:", error));
|
|
728
|
+
</script>
|
|
729
|
+
</body>
|
|
730
|
+
</html>
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### Multiple Widgets on Same Page
|
|
445
734
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
735
|
+
You can use multiple widgets independently on the same page:
|
|
736
|
+
|
|
737
|
+
```html
|
|
738
|
+
<!DOCTYPE html>
|
|
739
|
+
<html>
|
|
740
|
+
<head>
|
|
741
|
+
<link rel="stylesheet" href="path/to/widget.css" />
|
|
742
|
+
</head>
|
|
743
|
+
<body>
|
|
744
|
+
<!-- Appointment Widget -->
|
|
745
|
+
<div id="appointment-widget"></div>
|
|
452
746
|
|
|
453
|
-
|
|
747
|
+
<!-- Enquiry Widget -->
|
|
748
|
+
<div id="enquiry-widget"></div>
|
|
454
749
|
|
|
455
|
-
|
|
750
|
+
<script src="path/to/widget.js"></script>
|
|
751
|
+
<script>
|
|
752
|
+
// Initialize appointment widget
|
|
753
|
+
window.MedosAppointmentCalendar.init({
|
|
754
|
+
containerId: "appointment-widget",
|
|
755
|
+
apiKey: "your-api-key",
|
|
756
|
+
onSuccess: () => console.log("Appointment booked!"),
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
// Initialize enquiry widget
|
|
760
|
+
window.MedosEnquiryForm.init({
|
|
761
|
+
containerId: "enquiry-widget",
|
|
762
|
+
apiKey: "your-api-key",
|
|
763
|
+
onSuccess: (enquiry) => console.log("Enquiry submitted:", enquiry),
|
|
764
|
+
});
|
|
765
|
+
</script>
|
|
766
|
+
</body>
|
|
767
|
+
</html>
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### Global API Reference
|
|
771
|
+
|
|
772
|
+
After loading the widget script, these global objects are available:
|
|
773
|
+
|
|
774
|
+
```javascript
|
|
775
|
+
// Global initialization functions
|
|
776
|
+
window.MedosAppointmentCalendar.init(options); // Appointment widget
|
|
777
|
+
window.MedosEnquiryForm.init(options); // Enquiry form widget
|
|
778
|
+
|
|
779
|
+
// Widget classes for advanced usage
|
|
780
|
+
window.MedosAppointmentWidget; // Appointment widget class
|
|
781
|
+
window.MedosEnquiryWidget; // Enquiry widget class
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
### Widget Lifecycle Management
|
|
785
|
+
|
|
786
|
+
#### Destroying Widgets
|
|
787
|
+
|
|
788
|
+
```javascript
|
|
789
|
+
// For class-based initialization
|
|
790
|
+
const widget = new window.MedosAppointmentWidget("container", options);
|
|
791
|
+
// Later...
|
|
792
|
+
widget.destroy(); // Clean up event listeners and DOM
|
|
793
|
+
|
|
794
|
+
// For global API initialization
|
|
795
|
+
// Widgets are automatically cleaned up when container is removed from DOM
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
#### Reinitializing Widgets
|
|
799
|
+
|
|
800
|
+
```javascript
|
|
801
|
+
// Clear container and reinitialize
|
|
802
|
+
const container = document.getElementById("appointment-widget");
|
|
803
|
+
container.innerHTML = ""; // Clear existing widget
|
|
804
|
+
|
|
805
|
+
window.MedosAppointmentCalendar.init({
|
|
806
|
+
containerId: "appointment-widget",
|
|
807
|
+
apiKey: "your-api-key",
|
|
808
|
+
});
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
### Theme Customization
|
|
812
|
+
|
|
813
|
+
The SDK provides comprehensive theming capabilities through CSS variables. Choose between two CSS files based on your customization needs:
|
|
814
|
+
|
|
815
|
+
#### Basic Theming (`widget.css`)
|
|
816
|
+
|
|
817
|
+
For simple customization with minimal variables:
|
|
818
|
+
|
|
819
|
+
```html
|
|
820
|
+
<link rel="stylesheet" href="dist/vanilla/widget.css" />
|
|
821
|
+
<style>
|
|
822
|
+
.my-theme {
|
|
823
|
+
--medos-primary-color: #7c3aed;
|
|
824
|
+
--medos-primary-color-hover: #6d28d9;
|
|
825
|
+
--medos-bg-color: #ffffff;
|
|
826
|
+
--medos-text-color: #1f2937;
|
|
827
|
+
}
|
|
828
|
+
</style>
|
|
829
|
+
<div id="widget" class="my-theme"></div>
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
#### Advanced Theming (`widget-themed.css`)
|
|
833
|
+
|
|
834
|
+
For comprehensive design system customization:
|
|
835
|
+
|
|
836
|
+
```html
|
|
837
|
+
<link rel="stylesheet" href="dist/vanilla/widget-themed.css" />
|
|
838
|
+
<style>
|
|
839
|
+
.my-advanced-theme {
|
|
840
|
+
/* Colors */
|
|
841
|
+
--medos-color-primary: #7c3aed;
|
|
842
|
+
--medos-color-background: #ffffff;
|
|
843
|
+
--medos-color-text: #1f2937;
|
|
844
|
+
|
|
845
|
+
/* Typography */
|
|
846
|
+
--medos-typography-font-family: "Georgia", serif;
|
|
847
|
+
--medos-typography-font-size-md: 18px;
|
|
848
|
+
|
|
849
|
+
/* Spacing & Layout */
|
|
850
|
+
--medos-spacing-md: 16px;
|
|
851
|
+
--medos-radius-md: 20px;
|
|
852
|
+
--medos-shadow-lg: 0 20px 40px rgba(124, 58, 237, 0.15);
|
|
853
|
+
}
|
|
854
|
+
</style>
|
|
855
|
+
<div id="widget" class="my-advanced-theme"></div>
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
#### Dynamic Theme Switching
|
|
859
|
+
|
|
860
|
+
```javascript
|
|
861
|
+
// Apply theme programmatically
|
|
862
|
+
const container = document.getElementById("widget-container");
|
|
863
|
+
|
|
864
|
+
// Method 1: CSS classes
|
|
865
|
+
container.classList.add("dark-theme");
|
|
866
|
+
|
|
867
|
+
// Method 2: Direct CSS variables
|
|
868
|
+
container.style.setProperty("--medos-color-primary", "#7c3aed");
|
|
869
|
+
container.style.setProperty("--medos-color-background", "#1f2937");
|
|
870
|
+
|
|
871
|
+
// Method 3: Theme objects
|
|
872
|
+
const themes = {
|
|
873
|
+
purple: {
|
|
874
|
+
"--medos-color-primary": "#7c3aed",
|
|
875
|
+
"--medos-color-secondary": "#a855f7",
|
|
876
|
+
},
|
|
877
|
+
green: {
|
|
878
|
+
"--medos-color-primary": "#10b981",
|
|
879
|
+
"--medos-color-secondary": "#34d399",
|
|
880
|
+
},
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
function applyTheme(themeName) {
|
|
884
|
+
const theme = themes[themeName];
|
|
885
|
+
Object.entries(theme).forEach(([property, value]) => {
|
|
886
|
+
container.style.setProperty(property, value);
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
#### Theme Examples
|
|
892
|
+
|
|
893
|
+
Explore comprehensive theming examples in the `examples/` directory:
|
|
894
|
+
|
|
895
|
+
- `theme-customization-basic.html` - Basic CSS variable overrides
|
|
896
|
+
- `theme-customization-advanced.html` - Multiple theme comparisons
|
|
897
|
+
- `theme-customization-javascript.html` - Dynamic theme switching
|
|
898
|
+
- `theme-comparison.html` - Side-by-side CSS file comparison
|
|
899
|
+
- `enquiry-form-theming.html` - Enquiry form specific themes
|
|
900
|
+
|
|
901
|
+
#### Available CSS Variables
|
|
902
|
+
|
|
903
|
+
**Basic Variables (widget.css):**
|
|
904
|
+
|
|
905
|
+
- `--medos-primary-color`, `--medos-primary-color-hover`
|
|
906
|
+
- `--medos-bg-color`, `--medos-bg-color-secondary`
|
|
907
|
+
- `--medos-text-color`, `--medos-text-color-secondary`
|
|
908
|
+
- `--medos-border-color`, `--medos-border-radius`
|
|
909
|
+
|
|
910
|
+
**Complete Variables (widget-themed.css):**
|
|
911
|
+
|
|
912
|
+
- **Colors:** 15+ color tokens for comprehensive theming
|
|
913
|
+
- **Typography:** Font family, sizes, weights
|
|
914
|
+
- **Spacing:** Consistent spacing scale (xs, sm, md, lg, xl)
|
|
915
|
+
- **Layout:** Border radius, shadows, transitions
|
|
916
|
+
|
|
917
|
+
See `examples/README-THEME-CUSTOMIZATION.md` for complete documentation.
|
|
918
|
+
|
|
919
|
+
### Troubleshooting Guide
|
|
920
|
+
|
|
921
|
+
#### Common Issues and Solutions
|
|
922
|
+
|
|
923
|
+
**1. Widget Not Loading**
|
|
924
|
+
|
|
925
|
+
_Problem:_ Widget container remains empty, no errors in console.
|
|
926
|
+
|
|
927
|
+
_Solutions:_
|
|
928
|
+
|
|
929
|
+
```javascript
|
|
930
|
+
// Check if widget script loaded
|
|
931
|
+
if (typeof window.MedosAppointmentCalendar === "undefined") {
|
|
932
|
+
console.error("Widget script not loaded. Check script src path.");
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// Ensure container exists
|
|
936
|
+
const container = document.getElementById("your-container-id");
|
|
937
|
+
if (!container) {
|
|
938
|
+
console.error("Container element not found. Check containerId.");
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// Wait for DOM ready
|
|
942
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
943
|
+
window.MedosAppointmentCalendar.init({
|
|
944
|
+
containerId: "appointment-widget",
|
|
945
|
+
apiKey: "your-api-key",
|
|
946
|
+
});
|
|
947
|
+
});
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
**2. Authentication Errors**
|
|
951
|
+
|
|
952
|
+
_Problem:_ "Invalid API key" or "Authentication failed" errors.
|
|
953
|
+
|
|
954
|
+
_Solutions:_
|
|
955
|
+
|
|
956
|
+
```javascript
|
|
957
|
+
// Verify API key format
|
|
958
|
+
const apiKey = "your-api-key";
|
|
959
|
+
if (!apiKey || apiKey === "your-api-key") {
|
|
960
|
+
console.error("Please replace with your actual API key");
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// Use session token for production
|
|
964
|
+
window.MedosAppointmentCalendar.init({
|
|
965
|
+
containerId: "widget",
|
|
966
|
+
sessionToken: "your-session-token", // More secure
|
|
967
|
+
baseURL: "https://api.medos.one/v1",
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
// Check API endpoint
|
|
971
|
+
fetch("https://api.medos.one/v1/health")
|
|
972
|
+
.then((response) => console.log("API accessible:", response.ok))
|
|
973
|
+
.catch((error) => console.error("API not accessible:", error));
|
|
974
|
+
```
|
|
975
|
+
|
|
976
|
+
**3. CSS Styling Issues**
|
|
977
|
+
|
|
978
|
+
_Problem:_ Widget appears unstyled or has layout issues.
|
|
979
|
+
|
|
980
|
+
_Solutions:_
|
|
981
|
+
|
|
982
|
+
```html
|
|
983
|
+
<!-- Ensure CSS is loaded before JavaScript -->
|
|
984
|
+
<link rel="stylesheet" href="path/to/widget.css" />
|
|
985
|
+
<script src="path/to/widget.js"></script>
|
|
986
|
+
|
|
987
|
+
<!-- Check for CSS conflicts -->
|
|
988
|
+
<style>
|
|
989
|
+
/* Ensure widget container has proper styling */
|
|
990
|
+
#appointment-widget {
|
|
991
|
+
width: 100%;
|
|
992
|
+
max-width: 800px;
|
|
993
|
+
margin: 0 auto;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/* Reset any conflicting styles */
|
|
997
|
+
.medos-appointment-container * {
|
|
998
|
+
box-sizing: border-box;
|
|
999
|
+
}
|
|
1000
|
+
</style>
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
**4. Network/CORS Errors**
|
|
1004
|
+
|
|
1005
|
+
_Problem:_ "CORS policy" or network request failures.
|
|
1006
|
+
|
|
1007
|
+
_Solutions:_
|
|
1008
|
+
|
|
1009
|
+
```javascript
|
|
1010
|
+
// Check baseURL configuration
|
|
1011
|
+
window.MedosAppointmentCalendar.init({
|
|
1012
|
+
containerId: "widget",
|
|
1013
|
+
apiKey: "your-api-key",
|
|
1014
|
+
baseURL: "https://api.medos.one/v1", // Ensure correct URL
|
|
1015
|
+
onError: (error) => {
|
|
1016
|
+
if (error.message.includes("CORS")) {
|
|
1017
|
+
console.error("CORS error: Ensure your domain is whitelisted");
|
|
1018
|
+
}
|
|
1019
|
+
if (error.message.includes("Network")) {
|
|
1020
|
+
console.error("Network error: Check internet connection and API status");
|
|
1021
|
+
}
|
|
1022
|
+
},
|
|
1023
|
+
});
|
|
1024
|
+
|
|
1025
|
+
// Test API connectivity
|
|
1026
|
+
async function testAPIConnection() {
|
|
1027
|
+
try {
|
|
1028
|
+
const response = await fetch("https://api.medos.one/v1/health");
|
|
1029
|
+
console.log("API Status:", response.status);
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
console.error("Cannot reach API:", error);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
**5. Multiple Widget Conflicts**
|
|
1037
|
+
|
|
1038
|
+
_Problem:_ Multiple widgets interfering with each other.
|
|
1039
|
+
|
|
1040
|
+
_Solutions:_
|
|
1041
|
+
|
|
1042
|
+
```javascript
|
|
1043
|
+
// Use unique container IDs
|
|
1044
|
+
window.MedosAppointmentCalendar.init({
|
|
1045
|
+
containerId: "appointment-widget-1", // Unique ID
|
|
1046
|
+
apiKey: "your-api-key",
|
|
1047
|
+
});
|
|
1048
|
+
|
|
1049
|
+
window.MedosEnquiryForm.init({
|
|
1050
|
+
containerId: "enquiry-widget-1", // Different unique ID
|
|
1051
|
+
apiKey: "your-api-key",
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1054
|
+
// Clean up widgets when needed
|
|
1055
|
+
const widget = new window.MedosAppointmentWidget("container", options);
|
|
1056
|
+
// Later...
|
|
1057
|
+
widget.destroy(); // Prevents memory leaks
|
|
1058
|
+
```
|
|
1059
|
+
|
|
1060
|
+
**6. Mobile/Responsive Issues**
|
|
1061
|
+
|
|
1062
|
+
_Problem:_ Widget doesn't display properly on mobile devices.
|
|
1063
|
+
|
|
1064
|
+
_Solutions:_
|
|
1065
|
+
|
|
1066
|
+
```html
|
|
1067
|
+
<!-- Ensure viewport meta tag -->
|
|
1068
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
1069
|
+
|
|
1070
|
+
<style>
|
|
1071
|
+
/* Responsive container */
|
|
1072
|
+
.widget-container {
|
|
1073
|
+
width: 100%;
|
|
1074
|
+
max-width: 100vw;
|
|
1075
|
+
padding: 10px;
|
|
1076
|
+
box-sizing: border-box;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/* Mobile-specific adjustments */
|
|
1080
|
+
@media (max-width: 768px) {
|
|
1081
|
+
.widget-container {
|
|
1082
|
+
padding: 5px;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
</style>
|
|
1086
|
+
```
|
|
1087
|
+
|
|
1088
|
+
**7. Theme Not Applying**
|
|
1089
|
+
|
|
1090
|
+
_Problem:_ Custom CSS variables not taking effect.
|
|
1091
|
+
|
|
1092
|
+
_Solutions:_
|
|
456
1093
|
|
|
457
1094
|
```css
|
|
458
|
-
|
|
459
|
-
|
|
1095
|
+
/* Ensure proper CSS specificity */
|
|
1096
|
+
.my-theme .medos-appointment-container {
|
|
1097
|
+
--medos-color-primary: #7c3aed !important;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/* Or apply to widget container directly */
|
|
1101
|
+
#appointment-widget {
|
|
1102
|
+
--medos-color-primary: #7c3aed;
|
|
1103
|
+
--medos-color-background: #ffffff;
|
|
1104
|
+
}
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
```javascript
|
|
1108
|
+
// Apply theme programmatically
|
|
1109
|
+
const container = document.getElementById("appointment-widget");
|
|
1110
|
+
container.style.setProperty("--medos-color-primary", "#7c3aed");
|
|
1111
|
+
|
|
1112
|
+
// Verify theme variables are applied
|
|
1113
|
+
const computedStyle = getComputedStyle(container);
|
|
1114
|
+
const primaryColor = computedStyle.getPropertyValue("--medos-color-primary");
|
|
1115
|
+
console.log("Applied primary color:", primaryColor);
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
#### Debugging Tips
|
|
1119
|
+
|
|
1120
|
+
**Enable Debug Mode:**
|
|
1121
|
+
|
|
1122
|
+
```javascript
|
|
1123
|
+
// Add debug logging
|
|
1124
|
+
window.MedosAppointmentCalendar.init({
|
|
1125
|
+
containerId: "widget",
|
|
1126
|
+
apiKey: "your-api-key",
|
|
1127
|
+
debug: true, // Enable debug mode if available
|
|
1128
|
+
onError: (error) => {
|
|
1129
|
+
console.error("Widget Error Details:", {
|
|
1130
|
+
message: error.message,
|
|
1131
|
+
stack: error.stack,
|
|
1132
|
+
timestamp: new Date().toISOString(),
|
|
1133
|
+
});
|
|
1134
|
+
},
|
|
1135
|
+
onStepChange: (step) => {
|
|
1136
|
+
console.log("Step changed to:", step);
|
|
1137
|
+
},
|
|
1138
|
+
});
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
**Check Widget State:**
|
|
1142
|
+
|
|
1143
|
+
```javascript
|
|
1144
|
+
// Inspect widget instance
|
|
1145
|
+
const container = document.getElementById("appointment-widget");
|
|
1146
|
+
const widgetInstance = container._medosWidget; // Internal reference
|
|
1147
|
+
if (widgetInstance) {
|
|
1148
|
+
console.log("Widget state:", widgetInstance.getState());
|
|
460
1149
|
}
|
|
461
1150
|
|
|
462
|
-
|
|
463
|
-
|
|
1151
|
+
// Check global objects
|
|
1152
|
+
console.log("Available globals:", {
|
|
1153
|
+
MedosAppointmentCalendar: typeof window.MedosAppointmentCalendar,
|
|
1154
|
+
MedosEnquiryForm: typeof window.MedosEnquiryForm,
|
|
1155
|
+
MedosAppointmentWidget: typeof window.MedosAppointmentWidget,
|
|
1156
|
+
MedosEnquiryWidget: typeof window.MedosEnquiryWidget,
|
|
1157
|
+
});
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
**Network Debugging:**
|
|
1161
|
+
|
|
1162
|
+
```javascript
|
|
1163
|
+
// Monitor API calls
|
|
1164
|
+
const originalFetch = window.fetch;
|
|
1165
|
+
window.fetch = function (...args) {
|
|
1166
|
+
console.log("API Request:", args[0]);
|
|
1167
|
+
return originalFetch
|
|
1168
|
+
.apply(this, args)
|
|
1169
|
+
.then((response) => {
|
|
1170
|
+
console.log("API Response:", response.status, response.url);
|
|
1171
|
+
return response;
|
|
1172
|
+
})
|
|
1173
|
+
.catch((error) => {
|
|
1174
|
+
console.error("API Error:", error);
|
|
1175
|
+
throw error;
|
|
1176
|
+
});
|
|
1177
|
+
};
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
#### Performance Optimization
|
|
1181
|
+
|
|
1182
|
+
**Lazy Loading:**
|
|
1183
|
+
|
|
1184
|
+
```javascript
|
|
1185
|
+
// Load widget only when needed
|
|
1186
|
+
function loadWidget() {
|
|
1187
|
+
if (!document.getElementById("widget-script")) {
|
|
1188
|
+
const script = document.createElement("script");
|
|
1189
|
+
script.id = "widget-script";
|
|
1190
|
+
script.src = "path/to/widget.js";
|
|
1191
|
+
script.onload = () => {
|
|
1192
|
+
window.MedosAppointmentCalendar.init({
|
|
1193
|
+
containerId: "appointment-widget",
|
|
1194
|
+
apiKey: "your-api-key",
|
|
1195
|
+
});
|
|
1196
|
+
};
|
|
1197
|
+
document.head.appendChild(script);
|
|
1198
|
+
}
|
|
464
1199
|
}
|
|
1200
|
+
|
|
1201
|
+
// Load on user interaction
|
|
1202
|
+
document
|
|
1203
|
+
.getElementById("book-appointment-btn")
|
|
1204
|
+
.addEventListener("click", loadWidget);
|
|
1205
|
+
```
|
|
1206
|
+
|
|
1207
|
+
**Resource Optimization:**
|
|
1208
|
+
|
|
1209
|
+
```html
|
|
1210
|
+
<!-- Preload critical resources -->
|
|
1211
|
+
<link rel="preload" href="path/to/widget.css" as="style" />
|
|
1212
|
+
<link rel="preload" href="path/to/widget.js" as="script" />
|
|
1213
|
+
|
|
1214
|
+
<!-- Use appropriate CSS file for your needs -->
|
|
1215
|
+
<!-- widget.css for basic theming (smaller file) -->
|
|
1216
|
+
<link rel="stylesheet" href="dist/vanilla/widget.css" />
|
|
1217
|
+
|
|
1218
|
+
<!-- widget-themed.css for advanced theming (larger file) -->
|
|
1219
|
+
<link rel="stylesheet" href="dist/vanilla/widget-themed.css" />
|
|
465
1220
|
```
|
|
466
1221
|
|
|
467
|
-
|
|
1222
|
+
#### Getting Help
|
|
1223
|
+
|
|
1224
|
+
If you encounter issues not covered in this guide:
|
|
1225
|
+
|
|
1226
|
+
1. **Check Browser Console:** Look for error messages and warnings
|
|
1227
|
+
2. **Verify Network Tab:** Check if API requests are successful
|
|
1228
|
+
3. **Test with Examples:** Compare with working examples in `examples/` directory
|
|
1229
|
+
4. **Check Version Compatibility:** Ensure you're using compatible versions
|
|
1230
|
+
5. **Review Documentation:** Check `docs/VANILLA_WIDGET.md` for additional details
|
|
1231
|
+
|
|
1232
|
+
**Common Error Messages:**
|
|
1233
|
+
|
|
1234
|
+
- `"Container element not found"` → Check `containerId` parameter
|
|
1235
|
+
- `"Invalid API key"` → Verify API key or use session token
|
|
1236
|
+
- `"Network request failed"` → Check internet connection and API status
|
|
1237
|
+
- `"Widget already initialized"` → Clear container before reinitializing
|
|
1238
|
+
- `"Theme variables not applied"` → Check CSS specificity and variable names
|
|
468
1239
|
|
|
469
1240
|
### Package Exports
|
|
470
1241
|
|
|
@@ -476,6 +1247,34 @@ The SDK provides multiple entry points for different use cases:
|
|
|
476
1247
|
- `medos-sdk/core` - Core services only (no framework dependencies)
|
|
477
1248
|
- `medos-sdk/widget` - Widget bundle with CSS
|
|
478
1249
|
|
|
1250
|
+
### Examples and Documentation
|
|
1251
|
+
|
|
1252
|
+
Comprehensive examples and documentation are available:
|
|
1253
|
+
|
|
1254
|
+
#### HTML Examples (`examples/` directory)
|
|
1255
|
+
|
|
1256
|
+
- **`vanilla-appointment-booking.html`** - Basic appointment widget with local files
|
|
1257
|
+
- **`cdn-appointment-booking.html`** - CDN integration example with fallback strategies
|
|
1258
|
+
- **`enquiry-form.html`** - Enquiry form widget with both local and CDN options
|
|
1259
|
+
- **`theme-customization-basic.html`** - Basic CSS variable overrides and theming
|
|
1260
|
+
- **`theme-customization-advanced.html`** - Advanced theming with multiple theme comparisons
|
|
1261
|
+
- **`theme-customization-javascript.html`** - Dynamic theme switching and programmatic theming
|
|
1262
|
+
- **`theme-comparison.html`** - Side-by-side comparison of CSS files
|
|
1263
|
+
- **`enquiry-form-theming.html`** - Enquiry form specific theming examples
|
|
1264
|
+
|
|
1265
|
+
#### Documentation (`docs/` directory)
|
|
1266
|
+
|
|
1267
|
+
- **`VANILLA_WIDGET.md`** - Comprehensive vanilla widget documentation
|
|
1268
|
+
- **`CDN_INTEGRATION.md`** - Complete CDN integration guide with best practices
|
|
1269
|
+
- **`BUILD.md`** - Build system and development setup
|
|
1270
|
+
- **`IMPLEMENTATION_STATUS.md`** - Current implementation status and roadmap
|
|
1271
|
+
|
|
1272
|
+
#### Theme Documentation
|
|
1273
|
+
|
|
1274
|
+
- **`examples/README-THEME-CUSTOMIZATION.md`** - Complete theming guide with examples
|
|
1275
|
+
- CSS variable reference for both `widget.css` and `widget-themed.css`
|
|
1276
|
+
- Dynamic theme switching examples and best practices
|
|
1277
|
+
|
|
479
1278
|
## API Reference
|
|
480
1279
|
|
|
481
1280
|
### MedosClient
|