medos-sdk 1.0.2 → 1.1.0
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 +39 -0
- package/dist/client/MedosClient.d.ts +3 -5
- package/dist/client/MedosClient.js +4 -4
- package/dist/components/AppointmentCalender.d.ts +1 -4
- package/dist/components/AppointmentCalender.js +323 -530
- package/dist/components/AppointmentDateTimeModal.d.ts +14 -0
- package/dist/components/AppointmentDateTimeModal.js +220 -0
- package/dist/components/ConfigurableCard.d.ts +12 -0
- package/dist/components/ConfigurableCard.js +29 -0
- package/dist/components/ContactInformationStep.d.ts +13 -0
- package/dist/components/ContactInformationStep.js +14 -0
- package/dist/components/ContactPreferenceStep.d.ts +9 -0
- package/dist/components/ContactPreferenceStep.js +16 -0
- package/dist/components/DoctorSelectModal.d.ts +7 -0
- package/dist/components/DoctorSelectModal.js +93 -0
- package/dist/components/EnquiryForm.d.ts +7 -0
- package/dist/components/EnquiryForm.js +212 -0
- package/dist/components/Icons/Check.d.ts +6 -0
- package/dist/components/Icons/Check.js +2 -0
- package/dist/components/Icons/ChevronDownIcon.d.ts +4 -0
- package/dist/components/Icons/ChevronDownIcon.js +2 -0
- package/dist/components/Icons/ChevronLeft.d.ts +3 -0
- package/dist/components/Icons/ChevronLeft.js +3 -0
- package/dist/components/Icons/ChevronRight.d.ts +3 -0
- package/dist/components/Icons/ChevronRight.js +3 -0
- package/dist/components/Icons/ConfirmationCheck.d.ts +1 -0
- package/dist/components/Icons/ConfirmationCheck.js +9 -0
- package/dist/components/Icons/ConsultationType.d.ts +1 -0
- package/dist/components/Icons/ConsultationType.js +2 -0
- package/dist/components/Icons/Date&TimeIcon.d.ts +1 -0
- package/dist/components/Icons/Date&TimeIcon.js +2 -0
- package/dist/components/Icons/MapIcon.d.ts +1 -0
- package/dist/components/Icons/MapIcon.js +2 -0
- package/dist/components/Icons/PaymentMethodIcon.d.ts +1 -0
- package/dist/components/Icons/PaymentMethodIcon.js +2 -0
- package/dist/components/Icons/UserIcon.d.ts +1 -0
- package/dist/components/Icons/UserIcon.js +2 -0
- package/dist/components/InquiryDetailsStep.d.ts +10 -0
- package/dist/components/InquiryDetailsStep.js +15 -0
- package/dist/components/PatientDetailsStep.d.ts +3 -0
- package/dist/components/PatientDetailsStep.js +84 -0
- package/dist/components/PhoneVerificationStep.d.ts +3 -0
- package/dist/components/PhoneVerificationStep.js +49 -0
- package/dist/components/SuccessStep.d.ts +5 -0
- package/dist/components/SuccessStep.js +9 -0
- package/dist/components/custom-calendar.d.ts +5 -0
- package/dist/components/custom-calendar.js +171 -0
- package/dist/components/styles.d.ts +6 -0
- package/dist/components/styles.js +257 -0
- package/dist/components/theme-styles.d.ts +12 -0
- package/dist/components/theme-styles.js +319 -0
- package/dist/components/types.d.ts +181 -0
- package/dist/components/types.js +55 -0
- package/dist/components/ui/select.d.ts +10 -0
- package/dist/components/ui/select.js +21 -0
- package/dist/components/uiComponents/SelectDropdown.d.ts +41 -0
- package/dist/components/uiComponents/SelectDropdown.js +302 -0
- package/dist/components/utils.d.ts +5 -0
- package/dist/components/utils.js +15 -0
- package/dist/components/validation.d.ts +2 -0
- package/dist/components/validation.js +7 -0
- package/dist/context/TemplateContext.d.ts +12 -0
- package/dist/context/TemplateContext.js +19 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +4 -0
- package/dist/core/theme/index.d.ts +3 -0
- package/dist/core/theme/index.js +3 -0
- package/dist/core/theme/themes.d.ts +8 -0
- package/dist/core/theme/themes.js +178 -0
- package/dist/core/theme/types.d.ts +106 -0
- package/dist/core/theme/types.js +1 -0
- package/dist/core/theme/utils.d.ts +8 -0
- package/dist/core/theme/utils.js +135 -0
- package/dist/enquiry-form/index.d.ts +4 -0
- package/dist/enquiry-form/index.js +4 -0
- package/dist/enquiry-form/provider.d.ts +3 -0
- package/dist/enquiry-form/provider.js +9 -0
- package/dist/enquiry-form/serialization.d.ts +4 -0
- package/dist/enquiry-form/serialization.js +57 -0
- package/dist/enquiry-form/types.d.ts +38 -0
- package/dist/enquiry-form/types.js +1 -0
- package/dist/enquiry-form/validation.d.ts +6 -0
- package/dist/enquiry-form/validation.js +21 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +7 -0
- package/dist/lib/templateUtils.d.ts +3 -0
- package/dist/lib/templateUtils.js +28 -0
- package/dist/react/ThemeProvider.d.ts +18 -0
- package/dist/react/ThemeProvider.js +45 -0
- package/dist/react/hooks/useTheme.d.ts +1 -0
- package/dist/react/hooks/useTheme.js +1 -0
- package/dist/react/index.d.ts +5 -0
- package/dist/react/index.js +3 -0
- package/dist/services/AppointmentService.d.ts +4 -5
- package/dist/services/AppointmentService.js +12 -10
- package/dist/services/EnquiryService.d.ts +5 -0
- package/dist/services/EnquiryService.js +30 -0
- package/dist/templates/registry.d.ts +12 -0
- package/dist/templates/registry.js +58 -0
- package/dist/vanilla/AppointmentCalendarWidget.d.ts +2 -34
- package/dist/vanilla/AppointmentCalendarWidget.js +264 -275
- package/dist/vanilla/EnquiryFormWidget.d.ts +35 -0
- package/dist/vanilla/EnquiryFormWidget.js +425 -0
- package/dist/vanilla/client/MedosClient.d.ts +3 -5
- package/dist/vanilla/components/AppointmentCalender.d.ts +1 -4
- package/dist/vanilla/components/AppointmentDateTimeModal.d.ts +14 -0
- package/dist/vanilla/components/ConfigurableCard.d.ts +12 -0
- package/dist/vanilla/components/ContactInformationStep.d.ts +13 -0
- package/dist/vanilla/components/ContactPreferenceStep.d.ts +9 -0
- package/dist/vanilla/components/DoctorSelectModal.d.ts +7 -0
- package/dist/vanilla/components/EnquiryForm.d.ts +7 -0
- package/dist/vanilla/components/Icons/Check.d.ts +6 -0
- package/dist/vanilla/components/Icons/ChevronDownIcon.d.ts +4 -0
- package/dist/vanilla/components/Icons/ChevronLeft.d.ts +3 -0
- package/dist/vanilla/components/Icons/ChevronRight.d.ts +3 -0
- package/dist/vanilla/components/Icons/ConfirmationCheck.d.ts +1 -0
- package/dist/vanilla/components/Icons/ConsultationType.d.ts +1 -0
- package/dist/vanilla/components/Icons/Date&TimeIcon.d.ts +1 -0
- package/dist/vanilla/components/Icons/MapIcon.d.ts +1 -0
- package/dist/vanilla/components/Icons/PaymentMethodIcon.d.ts +1 -0
- package/dist/vanilla/components/Icons/UserIcon.d.ts +1 -0
- package/dist/vanilla/components/InquiryDetailsStep.d.ts +10 -0
- package/dist/vanilla/components/PatientDetailsStep.d.ts +3 -0
- package/dist/vanilla/components/PhoneVerificationStep.d.ts +3 -0
- package/dist/vanilla/components/SuccessStep.d.ts +5 -0
- package/dist/vanilla/components/custom-calendar.d.ts +5 -0
- package/dist/vanilla/components/styles.d.ts +6 -0
- package/dist/vanilla/components/theme-styles.d.ts +12 -0
- package/dist/vanilla/components/types.d.ts +181 -0
- package/dist/vanilla/components/ui/select.d.ts +10 -0
- package/dist/vanilla/components/uiComponents/SelectDropdown.d.ts +41 -0
- package/dist/vanilla/components/utils.d.ts +5 -0
- package/dist/vanilla/components/validation.d.ts +2 -0
- package/dist/vanilla/context/TemplateContext.d.ts +12 -0
- package/dist/vanilla/core/index.d.ts +4 -0
- package/dist/vanilla/core/theme/index.d.ts +3 -0
- package/dist/vanilla/core/theme/themes.d.ts +8 -0
- package/dist/vanilla/core/theme/types.d.ts +106 -0
- package/dist/vanilla/core/theme/utils.d.ts +8 -0
- package/dist/vanilla/enquiry-form/index.d.ts +4 -0
- package/dist/vanilla/enquiry-form/provider.d.ts +3 -0
- package/dist/vanilla/enquiry-form/serialization.d.ts +4 -0
- package/dist/vanilla/enquiry-form/types.d.ts +38 -0
- package/dist/vanilla/enquiry-form/validation.d.ts +6 -0
- package/dist/vanilla/enquiry-widget.js +4650 -0
- package/dist/vanilla/index.d.ts +9 -0
- package/dist/vanilla/index.js +3 -1
- package/dist/vanilla/lib/templateUtils.d.ts +3 -0
- package/dist/vanilla/react/ThemeProvider.d.ts +18 -0
- package/dist/vanilla/react/hooks/useTheme.d.ts +1 -0
- package/dist/vanilla/react/index.d.ts +5 -0
- package/dist/vanilla/services/AppointmentService.d.ts +4 -5
- package/dist/vanilla/services/EnquiryService.d.ts +5 -0
- package/dist/vanilla/templates/alternative.css +13 -0
- package/dist/vanilla/templates/default.css +13 -0
- package/dist/vanilla/templates/registry.d.ts +12 -0
- package/dist/vanilla/theme-injector.d.ts +6 -0
- package/dist/vanilla/theme-injector.js +44 -0
- package/dist/vanilla/vanilla/AppointmentCalendarWidget.d.ts +2 -34
- package/dist/vanilla/vanilla/EnquiryFormWidget.d.ts +35 -0
- package/dist/vanilla/vanilla/index.d.ts +3 -1
- package/dist/vanilla/vanilla/theme-injector.d.ts +6 -0
- package/dist/vanilla/vanilla/widget.d.ts +6 -1
- package/dist/vanilla/widget.css +173 -0
- package/dist/vanilla/widget.d.ts +6 -1
- package/dist/vanilla/widget.js +813 -288
- package/package.json +9 -4
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export interface ThemeColors {
|
|
2
|
+
primary: string;
|
|
3
|
+
primaryHover: string;
|
|
4
|
+
primaryActive: string;
|
|
5
|
+
secondary: string;
|
|
6
|
+
secondaryHover: string;
|
|
7
|
+
accent: string;
|
|
8
|
+
accentHover: string;
|
|
9
|
+
background: string;
|
|
10
|
+
backgroundSecondary: string;
|
|
11
|
+
backgroundTertiary: string;
|
|
12
|
+
surface: string;
|
|
13
|
+
surfaceHover: string;
|
|
14
|
+
border: string;
|
|
15
|
+
borderHover: string;
|
|
16
|
+
borderFocus: string;
|
|
17
|
+
text: string;
|
|
18
|
+
textSecondary: string;
|
|
19
|
+
textTertiary: string;
|
|
20
|
+
textDisabled: string;
|
|
21
|
+
textOnPrimary: string;
|
|
22
|
+
textOnSecondary: string;
|
|
23
|
+
success: string;
|
|
24
|
+
successBackground: string;
|
|
25
|
+
successBorder: string;
|
|
26
|
+
error: string;
|
|
27
|
+
errorBackground: string;
|
|
28
|
+
errorBorder: string;
|
|
29
|
+
warning: string;
|
|
30
|
+
warningBackground: string;
|
|
31
|
+
warningBorder: string;
|
|
32
|
+
info: string;
|
|
33
|
+
infoBackground: string;
|
|
34
|
+
infoBorder: string;
|
|
35
|
+
}
|
|
36
|
+
export interface ThemeTypography {
|
|
37
|
+
fontFamily: string;
|
|
38
|
+
fontFamilyHeading: string;
|
|
39
|
+
fontSizeXs: string;
|
|
40
|
+
fontSizeSm: string;
|
|
41
|
+
fontSizeMd: string;
|
|
42
|
+
fontSizeLg: string;
|
|
43
|
+
fontSizeXl: string;
|
|
44
|
+
fontSize2xl: string;
|
|
45
|
+
fontSize3xl: string;
|
|
46
|
+
fontWeightNormal: string;
|
|
47
|
+
fontWeightMedium: string;
|
|
48
|
+
fontWeightSemibold: string;
|
|
49
|
+
fontWeightBold: string;
|
|
50
|
+
lineHeightTight: string;
|
|
51
|
+
lineHeightNormal: string;
|
|
52
|
+
lineHeightRelaxed: string;
|
|
53
|
+
}
|
|
54
|
+
export interface ThemeSpacing {
|
|
55
|
+
xs: string;
|
|
56
|
+
sm: string;
|
|
57
|
+
md: string;
|
|
58
|
+
lg: string;
|
|
59
|
+
xl: string;
|
|
60
|
+
"2xl": string;
|
|
61
|
+
"3xl": string;
|
|
62
|
+
"4xl": string;
|
|
63
|
+
}
|
|
64
|
+
export interface ThemeShadows {
|
|
65
|
+
sm: string;
|
|
66
|
+
md: string;
|
|
67
|
+
lg: string;
|
|
68
|
+
xl: string;
|
|
69
|
+
"2xl": string;
|
|
70
|
+
none: string;
|
|
71
|
+
}
|
|
72
|
+
export interface ThemeRadii {
|
|
73
|
+
none: string;
|
|
74
|
+
sm: string;
|
|
75
|
+
md: string;
|
|
76
|
+
lg: string;
|
|
77
|
+
xl: string;
|
|
78
|
+
full: string;
|
|
79
|
+
}
|
|
80
|
+
export interface ThemeTransitions {
|
|
81
|
+
fast: string;
|
|
82
|
+
normal: string;
|
|
83
|
+
slow: string;
|
|
84
|
+
}
|
|
85
|
+
export interface MedosTheme {
|
|
86
|
+
name: string;
|
|
87
|
+
colors: ThemeColors;
|
|
88
|
+
typography: ThemeTypography;
|
|
89
|
+
spacing: ThemeSpacing;
|
|
90
|
+
shadows: ThemeShadows;
|
|
91
|
+
radii: ThemeRadii;
|
|
92
|
+
transitions: ThemeTransitions;
|
|
93
|
+
}
|
|
94
|
+
export type PartialTheme = {
|
|
95
|
+
name?: string;
|
|
96
|
+
colors?: Partial<ThemeColors>;
|
|
97
|
+
typography?: Partial<ThemeTypography>;
|
|
98
|
+
spacing?: Partial<ThemeSpacing>;
|
|
99
|
+
shadows?: Partial<ThemeShadows>;
|
|
100
|
+
radii?: Partial<ThemeRadii>;
|
|
101
|
+
transitions?: Partial<ThemeTransitions>;
|
|
102
|
+
};
|
|
103
|
+
export interface ThemeConfig {
|
|
104
|
+
theme?: MedosTheme | PartialTheme;
|
|
105
|
+
cssVariablePrefix?: string;
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MedosTheme, PartialTheme } from "./types";
|
|
2
|
+
export declare function mergeTheme(partialTheme?: PartialTheme): MedosTheme;
|
|
3
|
+
export declare function generateCssVariables(theme: MedosTheme, prefix?: string): string;
|
|
4
|
+
export declare function generateCssVariablesObject(theme: MedosTheme, prefix?: string): Record<string, string>;
|
|
5
|
+
export declare function getCssVar(prefix: string, category: string, key: string, fallback?: string): string;
|
|
6
|
+
export declare function injectCssVariables(theme: MedosTheme, containerId: string, prefix?: string): void;
|
|
7
|
+
export declare function createThemeStyleTag(theme: MedosTheme, prefix?: string, selector?: string): HTMLStyleElement | null;
|
|
8
|
+
export declare function validateTheme(theme: any): string[];
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { defaultTheme } from "./themes";
|
|
2
|
+
function deepMerge(target, source) {
|
|
3
|
+
const result = { ...target };
|
|
4
|
+
for (const key in source) {
|
|
5
|
+
if (source.hasOwnProperty(key)) {
|
|
6
|
+
const sourceValue = source[key];
|
|
7
|
+
const targetValue = result[key];
|
|
8
|
+
if (sourceValue &&
|
|
9
|
+
typeof sourceValue === "object" &&
|
|
10
|
+
!Array.isArray(sourceValue) &&
|
|
11
|
+
targetValue &&
|
|
12
|
+
typeof targetValue === "object" &&
|
|
13
|
+
!Array.isArray(targetValue)) {
|
|
14
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
15
|
+
}
|
|
16
|
+
else if (sourceValue !== undefined) {
|
|
17
|
+
result[key] = sourceValue;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
export function mergeTheme(partialTheme) {
|
|
24
|
+
if (!partialTheme) {
|
|
25
|
+
return defaultTheme;
|
|
26
|
+
}
|
|
27
|
+
return deepMerge(defaultTheme, partialTheme);
|
|
28
|
+
}
|
|
29
|
+
function getCssVarName(prefix, category, key) {
|
|
30
|
+
return `--${prefix}-${category}-${key
|
|
31
|
+
.replace(/([A-Z])/g, "-$1")
|
|
32
|
+
.toLowerCase()}`;
|
|
33
|
+
}
|
|
34
|
+
export function generateCssVariables(theme, prefix = "medos") {
|
|
35
|
+
const vars = [];
|
|
36
|
+
Object.entries(theme.colors).forEach(([key, value]) => {
|
|
37
|
+
vars.push(`${getCssVarName(prefix, "color", key)}: ${value};`);
|
|
38
|
+
});
|
|
39
|
+
Object.entries(theme.typography).forEach(([key, value]) => {
|
|
40
|
+
vars.push(`${getCssVarName(prefix, "typography", key)}: ${value};`);
|
|
41
|
+
});
|
|
42
|
+
Object.entries(theme.spacing).forEach(([key, value]) => {
|
|
43
|
+
vars.push(`${getCssVarName(prefix, "spacing", key)}: ${value};`);
|
|
44
|
+
});
|
|
45
|
+
Object.entries(theme.shadows).forEach(([key, value]) => {
|
|
46
|
+
vars.push(`${getCssVarName(prefix, "shadow", key)}: ${value};`);
|
|
47
|
+
});
|
|
48
|
+
Object.entries(theme.radii).forEach(([key, value]) => {
|
|
49
|
+
vars.push(`${getCssVarName(prefix, "radius", key)}: ${value};`);
|
|
50
|
+
});
|
|
51
|
+
Object.entries(theme.transitions).forEach(([key, value]) => {
|
|
52
|
+
vars.push(`${getCssVarName(prefix, "transition", key)}: ${value};`);
|
|
53
|
+
});
|
|
54
|
+
return vars.join("\n ");
|
|
55
|
+
}
|
|
56
|
+
export function generateCssVariablesObject(theme, prefix = "medos") {
|
|
57
|
+
const vars = {};
|
|
58
|
+
Object.entries(theme.colors).forEach(([key, value]) => {
|
|
59
|
+
vars[getCssVarName(prefix, "color", key)] = value;
|
|
60
|
+
});
|
|
61
|
+
Object.entries(theme.typography).forEach(([key, value]) => {
|
|
62
|
+
vars[getCssVarName(prefix, "typography", key)] = value;
|
|
63
|
+
});
|
|
64
|
+
Object.entries(theme.spacing).forEach(([key, value]) => {
|
|
65
|
+
vars[getCssVarName(prefix, "spacing", key)] = value;
|
|
66
|
+
});
|
|
67
|
+
Object.entries(theme.shadows).forEach(([key, value]) => {
|
|
68
|
+
vars[getCssVarName(prefix, "shadow", key)] = value;
|
|
69
|
+
});
|
|
70
|
+
Object.entries(theme.radii).forEach(([key, value]) => {
|
|
71
|
+
vars[getCssVarName(prefix, "radius", key)] = value;
|
|
72
|
+
});
|
|
73
|
+
Object.entries(theme.transitions).forEach(([key, value]) => {
|
|
74
|
+
vars[getCssVarName(prefix, "transition", key)] = value;
|
|
75
|
+
});
|
|
76
|
+
return vars;
|
|
77
|
+
}
|
|
78
|
+
export function getCssVar(prefix, category, key, fallback) {
|
|
79
|
+
const varName = getCssVarName(prefix, category, key);
|
|
80
|
+
return fallback ? `var(${varName}, ${fallback})` : `var(${varName})`;
|
|
81
|
+
}
|
|
82
|
+
export function injectCssVariables(theme, containerId, prefix = "medos") {
|
|
83
|
+
if (typeof document === "undefined") {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const container = document.getElementById(containerId);
|
|
87
|
+
if (!container) {
|
|
88
|
+
console.warn(`Container with id "${containerId}" not found`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const cssVars = generateCssVariablesObject(theme, prefix);
|
|
92
|
+
Object.entries(cssVars).forEach(([key, value]) => {
|
|
93
|
+
container.style.setProperty(key, value);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export function createThemeStyleTag(theme, prefix = "medos", selector = ":root") {
|
|
97
|
+
if (typeof document === "undefined") {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const styleId = `${prefix}-theme-vars`;
|
|
101
|
+
const existingStyle = document.getElementById(styleId);
|
|
102
|
+
if (existingStyle) {
|
|
103
|
+
existingStyle.remove();
|
|
104
|
+
}
|
|
105
|
+
const styleElement = document.createElement("style");
|
|
106
|
+
styleElement.id = styleId;
|
|
107
|
+
styleElement.innerHTML = `
|
|
108
|
+
${selector} {
|
|
109
|
+
${generateCssVariables(theme, prefix)}
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
document.head.appendChild(styleElement);
|
|
113
|
+
return styleElement;
|
|
114
|
+
}
|
|
115
|
+
export function validateTheme(theme) {
|
|
116
|
+
const errors = [];
|
|
117
|
+
if (!theme || typeof theme !== "object") {
|
|
118
|
+
errors.push("Theme must be an object");
|
|
119
|
+
return errors;
|
|
120
|
+
}
|
|
121
|
+
const requiredProps = [
|
|
122
|
+
"colors",
|
|
123
|
+
"typography",
|
|
124
|
+
"spacing",
|
|
125
|
+
"shadows",
|
|
126
|
+
"radii",
|
|
127
|
+
"transitions",
|
|
128
|
+
];
|
|
129
|
+
requiredProps.forEach((prop) => {
|
|
130
|
+
if (!theme[prop] || typeof theme[prop] !== "object") {
|
|
131
|
+
errors.push(`Theme.${prop} is required and must be an object`);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
return errors;
|
|
135
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MedosClient } from "../client/MedosClient";
|
|
2
|
+
export const submitEnquiry = async (payload) => {
|
|
3
|
+
const response = await MedosClient.client.post("/enquiries", payload);
|
|
4
|
+
return response.data;
|
|
5
|
+
};
|
|
6
|
+
export const getEnquiry = async (enquiryId) => {
|
|
7
|
+
const response = await MedosClient.client.get(`/enquiries/${enquiryId}`);
|
|
8
|
+
return response.data;
|
|
9
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const serializeEnquiry = (enquiry) => {
|
|
2
|
+
if (!enquiry) {
|
|
3
|
+
throw new Error("Cannot serialize null or undefined enquiry");
|
|
4
|
+
}
|
|
5
|
+
try {
|
|
6
|
+
return JSON.stringify(enquiry);
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
throw new Error(`Failed to serialize enquiry: ${error instanceof Error ? error.message : String(error)}`);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const deserializeEnquiry = (jsonString) => {
|
|
13
|
+
if (!jsonString || typeof jsonString !== "string") {
|
|
14
|
+
throw new Error("Cannot deserialize null, undefined, or non-string value");
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(jsonString);
|
|
18
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
19
|
+
throw new Error("Deserialized value is not an object");
|
|
20
|
+
}
|
|
21
|
+
const requiredFields = [
|
|
22
|
+
"patientName",
|
|
23
|
+
"patientEmail",
|
|
24
|
+
"countryCode",
|
|
25
|
+
"patientPhone",
|
|
26
|
+
"inquirySubject",
|
|
27
|
+
"inquiryMessage",
|
|
28
|
+
"preferredContactMethod",
|
|
29
|
+
];
|
|
30
|
+
for (const field of requiredFields) {
|
|
31
|
+
if (!(field in parsed)) {
|
|
32
|
+
throw new Error(`Missing required field: ${field}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const validContactMethods = ["PHONE", "EMAIL", "BOTH"];
|
|
36
|
+
if (!validContactMethods.includes(parsed.preferredContactMethod)) {
|
|
37
|
+
throw new Error(`Invalid preferredContactMethod: ${parsed.preferredContactMethod}`);
|
|
38
|
+
}
|
|
39
|
+
if (parsed.status !== undefined && parsed.status !== null) {
|
|
40
|
+
const validStatuses = ["PENDING", "RESPONDED", "CLOSED"];
|
|
41
|
+
if (!validStatuses.includes(parsed.status)) {
|
|
42
|
+
throw new Error(`Invalid status: ${parsed.status}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return parsed;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (error instanceof SyntaxError) {
|
|
49
|
+
throw new Error(`Invalid JSON: ${error.message}`);
|
|
50
|
+
}
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
export const roundTripEnquiry = (enquiry) => {
|
|
55
|
+
const serialized = serializeEnquiry(enquiry);
|
|
56
|
+
return deserializeEnquiry(serialized);
|
|
57
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface Enquiry {
|
|
2
|
+
id?: string;
|
|
3
|
+
patientName: string;
|
|
4
|
+
patientEmail: string;
|
|
5
|
+
countryCode: string;
|
|
6
|
+
patientPhone: string;
|
|
7
|
+
inquirySubject: string;
|
|
8
|
+
inquiryMessage: string;
|
|
9
|
+
preferredContactMethod: "PHONE" | "EMAIL" | "BOTH";
|
|
10
|
+
createdAt?: string;
|
|
11
|
+
status?: "PENDING" | "RESPONDED" | "CLOSED";
|
|
12
|
+
}
|
|
13
|
+
export interface EnquiryFormState {
|
|
14
|
+
step: number;
|
|
15
|
+
loading: boolean;
|
|
16
|
+
error: string | null;
|
|
17
|
+
patientName: string;
|
|
18
|
+
patientEmail: string;
|
|
19
|
+
countryCode: string;
|
|
20
|
+
patientPhone: string;
|
|
21
|
+
inquirySubject: string;
|
|
22
|
+
inquiryMessage: string;
|
|
23
|
+
preferredContactMethod: "PHONE" | "EMAIL" | "BOTH";
|
|
24
|
+
submitted: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface EnquirySubmission {
|
|
27
|
+
patientName: string;
|
|
28
|
+
patientEmail: string;
|
|
29
|
+
countryCode: string;
|
|
30
|
+
patientPhone: string;
|
|
31
|
+
inquirySubject: string;
|
|
32
|
+
inquiryMessage: string;
|
|
33
|
+
preferredContactMethod: "PHONE" | "EMAIL" | "BOTH";
|
|
34
|
+
}
|
|
35
|
+
export interface ValidationResult {
|
|
36
|
+
isValid: boolean;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const validateName: (name: string) => boolean;
|
|
2
|
+
export declare const validateEmail: (email: string) => boolean;
|
|
3
|
+
export declare const validatePhoneNumber: (phone: string) => boolean;
|
|
4
|
+
export declare const validateSubject: (subject: string) => boolean;
|
|
5
|
+
export declare const validateMessage: (message: string) => boolean;
|
|
6
|
+
export declare const validateCountryCode: (code: string) => boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const validateName = (name) => {
|
|
2
|
+
return name.trim().length > 0;
|
|
3
|
+
};
|
|
4
|
+
export const validateEmail = (email) => {
|
|
5
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
6
|
+
return emailRegex.test(email);
|
|
7
|
+
};
|
|
8
|
+
export const validatePhoneNumber = (phone) => {
|
|
9
|
+
const cleaned = phone.replace(/\D/g, "");
|
|
10
|
+
return cleaned.length >= 7 && cleaned.length <= 15;
|
|
11
|
+
};
|
|
12
|
+
export const validateSubject = (subject) => {
|
|
13
|
+
return subject.trim().length > 0;
|
|
14
|
+
};
|
|
15
|
+
export const validateMessage = (message) => {
|
|
16
|
+
const trimmed = message.trim();
|
|
17
|
+
return trimmed.length > 0 && trimmed.length <= 1000;
|
|
18
|
+
};
|
|
19
|
+
export const validateCountryCode = (code) => {
|
|
20
|
+
return /^\+[1-9]\d{0,3}$/.test(code);
|
|
21
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
export { MedosClient } from "./client/MedosClient";
|
|
2
|
+
export * from "./core/theme";
|
|
3
|
+
export { MedosThemeProvider } from "./react/ThemeProvider";
|
|
4
|
+
export type { MedosThemeProviderProps } from "./react/ThemeProvider";
|
|
5
|
+
export { defaultTheme, modernTheme } from "./core/theme/themes";
|
|
6
|
+
export { useTheme, useThemeContext, useCssVar } from "./react/hooks/useTheme";
|
|
2
7
|
export { AppointmentCalender } from "./components/AppointmentCalender";
|
|
8
|
+
export { EnquiryForm } from "./components/EnquiryForm";
|
|
9
|
+
export type { EnquiryFormProps } from "./components/EnquiryForm";
|
|
3
10
|
export * from "./appointments/provider";
|
|
4
11
|
export * from "./appointments/types";
|
|
5
12
|
export * from "./appointment-calendar/provider";
|
|
6
13
|
export * from "./appointment-calendar/types";
|
|
14
|
+
export * from "./enquiry-form/provider";
|
|
15
|
+
export * from "./enquiry-form/types";
|
|
7
16
|
export { PatientService, SendPhoneVerificationOtpPayload, VerifyPhoneVerificationOtpPayload, } from "./services/PatientService";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export { MedosClient } from "./client/MedosClient";
|
|
2
|
+
export * from "./core/theme";
|
|
3
|
+
export { MedosThemeProvider } from "./react/ThemeProvider";
|
|
4
|
+
export { defaultTheme, modernTheme } from "./core/theme/themes";
|
|
5
|
+
export { useTheme, useThemeContext, useCssVar } from "./react/hooks/useTheme";
|
|
2
6
|
export { AppointmentCalender } from "./components/AppointmentCalender";
|
|
7
|
+
export { EnquiryForm } from "./components/EnquiryForm";
|
|
3
8
|
export * from "./appointments/provider";
|
|
4
9
|
export * from "./appointments/types";
|
|
5
10
|
export * from "./appointment-calendar/provider";
|
|
6
11
|
export * from "./appointment-calendar/types";
|
|
12
|
+
export * from "./enquiry-form/provider";
|
|
13
|
+
export * from "./enquiry-form/types";
|
|
7
14
|
export { PatientService, } from "./services/PatientService";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { templateRegistry } from "../core";
|
|
2
|
+
export function injectTemplateStyles(templateId) {
|
|
3
|
+
const existing = document.getElementById("medos-template-styles");
|
|
4
|
+
if (existing)
|
|
5
|
+
existing.remove();
|
|
6
|
+
const template = templateRegistry.getTemplate(templateId);
|
|
7
|
+
const style = document.createElement("style");
|
|
8
|
+
style.id = "medos-template-styles";
|
|
9
|
+
style.textContent = `
|
|
10
|
+
.medos-appointment-container {
|
|
11
|
+
--medos-primary-color: ${template.primaryColor} !important;
|
|
12
|
+
--medos-secondary-color: ${template.secondaryColor} !important;
|
|
13
|
+
--medos-accent-color: ${template.accentColor} !important;
|
|
14
|
+
--medos-background-color: ${template.backgroundColor} !important;
|
|
15
|
+
--medos-text-color: ${template.textColor} !important;
|
|
16
|
+
--medos-border-color: ${template.borderColor} !important;
|
|
17
|
+
--medos-muted-text: ${template.mutedText} !important;
|
|
18
|
+
--medos-success-color: ${template.successColor} !important;
|
|
19
|
+
--medos-error-color: ${template.errorColor} !important;
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
document.head.appendChild(style);
|
|
23
|
+
}
|
|
24
|
+
export function removeTemplateStyles() {
|
|
25
|
+
const existing = document.getElementById("medos-template-styles");
|
|
26
|
+
if (existing)
|
|
27
|
+
existing.remove();
|
|
28
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { MedosTheme, PartialTheme } from "../core/theme/types";
|
|
3
|
+
import { ThemeName } from "../core/theme/themes";
|
|
4
|
+
interface ThemeContextValue {
|
|
5
|
+
theme: MedosTheme;
|
|
6
|
+
cssVars: Record<string, string>;
|
|
7
|
+
prefix: string;
|
|
8
|
+
}
|
|
9
|
+
export interface MedosThemeProviderProps {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
theme?: ThemeName | MedosTheme | PartialTheme;
|
|
12
|
+
cssVariablePrefix?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function MedosThemeProvider({ children, theme, cssVariablePrefix, }: MedosThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare function useThemeContext(): ThemeContextValue;
|
|
16
|
+
export declare function useTheme(): MedosTheme;
|
|
17
|
+
export declare function useCssVar(category: string, key: string, fallback?: string): string;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { createContext, useMemo } from "react";
|
|
3
|
+
import { defaultTheme, themes } from "../core/theme/themes";
|
|
4
|
+
import { mergeTheme, generateCssVariablesObject } from "../core/theme/utils";
|
|
5
|
+
const ThemeContext = createContext(undefined);
|
|
6
|
+
export function MedosThemeProvider({ children, theme, cssVariablePrefix = "medos", }) {
|
|
7
|
+
const resolvedTheme = useMemo(() => {
|
|
8
|
+
if (!theme) {
|
|
9
|
+
return defaultTheme;
|
|
10
|
+
}
|
|
11
|
+
if (typeof theme === "string") {
|
|
12
|
+
return themes[theme] || defaultTheme;
|
|
13
|
+
}
|
|
14
|
+
if ("name" in theme && "colors" in theme && "typography" in theme) {
|
|
15
|
+
return theme;
|
|
16
|
+
}
|
|
17
|
+
return mergeTheme(theme);
|
|
18
|
+
}, [theme]);
|
|
19
|
+
const cssVars = useMemo(() => generateCssVariablesObject(resolvedTheme, cssVariablePrefix), [resolvedTheme, cssVariablePrefix]);
|
|
20
|
+
const contextValue = useMemo(() => ({
|
|
21
|
+
theme: resolvedTheme,
|
|
22
|
+
cssVars,
|
|
23
|
+
prefix: cssVariablePrefix,
|
|
24
|
+
}), [resolvedTheme, cssVars, cssVariablePrefix]);
|
|
25
|
+
return (_jsx(ThemeContext.Provider, { value: contextValue, children: _jsx("div", { style: cssVars, children: children }) }));
|
|
26
|
+
}
|
|
27
|
+
export function useThemeContext() {
|
|
28
|
+
const context = React.useContext(ThemeContext);
|
|
29
|
+
if (!context) {
|
|
30
|
+
throw new Error("useThemeContext must be used within a MedosThemeProvider");
|
|
31
|
+
}
|
|
32
|
+
return context;
|
|
33
|
+
}
|
|
34
|
+
export function useTheme() {
|
|
35
|
+
const context = React.useContext(ThemeContext);
|
|
36
|
+
return context?.theme || defaultTheme;
|
|
37
|
+
}
|
|
38
|
+
export function useCssVar(category, key, fallback) {
|
|
39
|
+
const context = React.useContext(ThemeContext);
|
|
40
|
+
const prefix = context?.prefix || "medos";
|
|
41
|
+
const varName = `--${prefix}-${category}-${key
|
|
42
|
+
.replace(/([A-Z])/g, "-$1")
|
|
43
|
+
.toLowerCase()}`;
|
|
44
|
+
return fallback ? `var(${varName}, ${fallback})` : `var(${varName})`;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTheme, useThemeContext, useCssVar } from "../ThemeProvider";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTheme, useThemeContext, useCssVar } from "../ThemeProvider";
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export * from "../core";
|
|
2
|
+
export { MedosThemeProvider } from "./ThemeProvider";
|
|
3
|
+
export type { MedosThemeProviderProps } from "./ThemeProvider";
|
|
4
|
+
export { useTheme, useThemeContext, useCssVar } from "./hooks/useTheme";
|
|
2
5
|
export { AppointmentCalender } from "../components/AppointmentCalender";
|
|
6
|
+
export { EnquiryForm } from "../components/EnquiryForm";
|
|
7
|
+
export type { EnquiryFormProps } from "../components/EnquiryForm";
|
package/dist/react/index.js
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export * from "../core";
|
|
2
|
+
export { MedosThemeProvider } from "./ThemeProvider";
|
|
3
|
+
export { useTheme, useThemeContext, useCssVar } from "./hooks/useTheme";
|
|
2
4
|
export { AppointmentCalender } from "../components/AppointmentCalender";
|
|
5
|
+
export { EnquiryForm } from "../components/EnquiryForm";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type Doctor = {
|
|
2
|
-
id:
|
|
2
|
+
id: number;
|
|
3
3
|
name: string;
|
|
4
4
|
specialty?: string;
|
|
5
5
|
[key: string]: any;
|
|
@@ -58,7 +58,7 @@ type AppointmentPayload = {
|
|
|
58
58
|
attachments?: File[];
|
|
59
59
|
};
|
|
60
60
|
type AddressItem = {
|
|
61
|
-
id: number
|
|
61
|
+
id: number;
|
|
62
62
|
completeAddress?: string;
|
|
63
63
|
label?: string;
|
|
64
64
|
address?: string;
|
|
@@ -67,7 +67,6 @@ type AddressItem = {
|
|
|
67
67
|
doctorsCount?: number;
|
|
68
68
|
totalConfiguredAppointments?: number;
|
|
69
69
|
doctors?: Doctor[];
|
|
70
|
-
[key: string]: any;
|
|
71
70
|
};
|
|
72
71
|
type AddressesResponse = {
|
|
73
72
|
totalAddresses?: number;
|
|
@@ -75,12 +74,12 @@ type AddressesResponse = {
|
|
|
75
74
|
totalConfiguredAppointments?: number;
|
|
76
75
|
totalPartialConfiguredAppointments?: number;
|
|
77
76
|
totalNotConfiguredAppointments?: number;
|
|
78
|
-
workspaceId?: number
|
|
77
|
+
workspaceId?: number;
|
|
79
78
|
addresses: AddressItem[];
|
|
80
79
|
};
|
|
81
80
|
declare const AppointmentService: {
|
|
82
81
|
getAddresses(): Promise<AddressesResponse>;
|
|
83
|
-
fetchSlots(workspaceId:
|
|
82
|
+
fetchSlots(workspaceId: number, addressId: number, doctorId: number, appointmentDate: string): Promise<Slot[]>;
|
|
84
83
|
createAppointment(payload: BookAppointmentPayload): Promise<any>;
|
|
85
84
|
};
|
|
86
85
|
export { AppointmentService, AppointmentPayload, BookAppointmentPayload, PatientPayload, PatientAddressPayload, AddressesResponse, AddressItem, };
|
|
@@ -10,18 +10,19 @@ const AppointmentService = {
|
|
|
10
10
|
.map((ad) => {
|
|
11
11
|
const addr = ad.address;
|
|
12
12
|
const doctors = (ad.doctors || []).map((d) => ({
|
|
13
|
-
id:
|
|
14
|
-
name: `${d.firstName || ""} ${d.lastName || ""}`.trim() ||
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
id: Number(d.user.id),
|
|
14
|
+
name: `${d.user.firstName || ""} ${d.user.lastName || ""}`.trim() ||
|
|
15
|
+
"Doctor",
|
|
16
|
+
email: d.user.email,
|
|
17
|
+
gender: d.user.gender,
|
|
18
|
+
countryCode: d.user.countryCode,
|
|
19
|
+
phoneNumber: d.user.phoneNumber,
|
|
20
|
+
dob: d.user.dob,
|
|
21
|
+
platform: d.user.platform,
|
|
22
|
+
isKycCompleted: d.user.isKycCompleted,
|
|
22
23
|
}));
|
|
23
24
|
return {
|
|
24
|
-
id:
|
|
25
|
+
id: Number(addr.id),
|
|
25
26
|
completeAddress: addr.completeAddress,
|
|
26
27
|
addressLine1: addr.addressLine1,
|
|
27
28
|
addressLine2: addr.addressLine2,
|
|
@@ -47,6 +48,7 @@ const AppointmentService = {
|
|
|
47
48
|
},
|
|
48
49
|
async fetchSlots(workspaceId, addressId, doctorId, appointmentDate) {
|
|
49
50
|
const client = await MedosClient.ensureInitialized();
|
|
51
|
+
console.log("fetching slots", workspaceId, addressId, doctorId, appointmentDate);
|
|
50
52
|
const res = await client.get(`/appointments/available-slots`, {
|
|
51
53
|
params: {
|
|
52
54
|
workspaceId,
|