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 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
- The widget is available as a bundled UMD module. After building the package, you'll find:
379
+ #### Option 1: NPM Package (Recommended)
367
380
 
368
- - `dist/vanilla/widget.js` - JavaScript bundle
369
- - `dist/vanilla/widget.css` - Stylesheet
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
- ### Basic Usage
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
- ### Using Session Token (Recommended for Production)
443
+ #### CDN Integration Example
401
444
 
402
- For better security, obtain the session token server-side:
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
- <script>
406
- window.MedosAppointmentCalendar.init({
407
- containerId: "appointment-calendar",
408
- sessionToken: "your-session-token", // Obtained from your server
409
- baseURL: "https://api.medos.one/v1",
410
- onError: (err) => console.error(err),
411
- });
412
- </script>
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
- ### PHP Integration Example
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
- ### Configuration Options
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
- - `containerId` (string, required) - ID of the HTML element where the widget will be rendered
447
- - `apiKey` (string, optional) - Your Medos API key (if not using sessionToken)
448
- - `sessionToken` (string, optional) - Session token obtained from your server (if not using apiKey)
449
- - `baseURL` (string, optional) - API base URL (defaults to `https://api.medos.one/v1`)
450
- - `onError` (function, optional) - Callback function for error handling
451
- - `onSuccess` (function, optional) - Callback function called when appointment is successfully booked
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
- ### Styling
747
+ <!-- Enquiry Widget -->
748
+ <div id="enquiry-widget"></div>
454
749
 
455
- The widget comes with default styles. You can customize them by overriding CSS classes:
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
- .medos-appointment-btn-primary {
459
- background: #your-color;
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
- .medos-appointment-card {
463
- border-radius: 8px;
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
- See `dist/vanilla/widget.css` for all available classes.
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