medos-sdk 1.0.3 → 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 +2 -4
- package/dist/client/MedosClient.js +4 -4
- package/dist/components/AppointmentCalender.js +43 -2
- package/dist/components/AppointmentDateTimeModal.js +45 -31
- 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.js +30 -17
- package/dist/components/EnquiryForm.d.ts +7 -0
- package/dist/components/EnquiryForm.js +212 -0
- package/dist/components/Icons/ConsultationType.js +1 -1
- package/dist/components/Icons/Date&TimeIcon.js +1 -1
- package/dist/components/Icons/MapIcon.js +1 -1
- package/dist/components/Icons/PaymentMethodIcon.js +1 -1
- package/dist/components/Icons/UserIcon.js +1 -1
- package/dist/components/InquiryDetailsStep.d.ts +10 -0
- package/dist/components/InquiryDetailsStep.js +15 -0
- package/dist/components/PatientDetailsStep.js +9 -1
- package/dist/components/PhoneVerificationStep.js +22 -12
- package/dist/components/SuccessStep.d.ts +3 -1
- package/dist/components/SuccessStep.js +7 -15
- package/dist/components/custom-calendar.js +42 -24
- package/dist/components/theme-styles.d.ts +12 -0
- package/dist/components/theme-styles.js +319 -0
- package/dist/components/types.d.ts +0 -1
- 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/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/EnquiryService.d.ts +5 -0
- package/dist/services/EnquiryService.js +30 -0
- package/dist/vanilla/AppointmentCalendarWidget.js +0 -2
- package/dist/vanilla/EnquiryFormWidget.d.ts +35 -0
- package/dist/vanilla/EnquiryFormWidget.js +425 -0
- package/dist/vanilla/client/MedosClient.d.ts +2 -4
- package/dist/vanilla/components/ContactInformationStep.d.ts +13 -0
- package/dist/vanilla/components/ContactPreferenceStep.d.ts +9 -0
- package/dist/vanilla/components/EnquiryForm.d.ts +7 -0
- package/dist/vanilla/components/InquiryDetailsStep.d.ts +10 -0
- package/dist/vanilla/components/SuccessStep.d.ts +3 -1
- package/dist/vanilla/components/theme-styles.d.ts +12 -0
- package/dist/vanilla/components/types.d.ts +0 -1
- 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/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/EnquiryService.d.ts +5 -0
- package/dist/vanilla/theme-injector.d.ts +6 -0
- package/dist/vanilla/theme-injector.js +44 -0
- 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 +489 -12
- package/package.json +1 -1
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import { EnquiryService } from "../services/EnquiryService";
|
|
2
|
+
import { MedosClient } from "../client/MedosClient";
|
|
3
|
+
import { validateName, validateEmail, validatePhoneNumber, validateSubject, validateMessage, validateCountryCode, } from "../enquiry-form/validation";
|
|
4
|
+
class EnquiryFormWidget {
|
|
5
|
+
constructor(container, options) {
|
|
6
|
+
this.mounted = true;
|
|
7
|
+
if (typeof container === "string") {
|
|
8
|
+
const el = document.getElementById(container);
|
|
9
|
+
if (!el) {
|
|
10
|
+
throw new Error(`Container element with id "${container}" not found`);
|
|
11
|
+
}
|
|
12
|
+
this.container = el;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
this.container = container;
|
|
16
|
+
}
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.state = {
|
|
19
|
+
step: 0,
|
|
20
|
+
loading: false,
|
|
21
|
+
error: null,
|
|
22
|
+
patientName: "",
|
|
23
|
+
patientEmail: "",
|
|
24
|
+
countryCode: "+91",
|
|
25
|
+
patientPhone: "",
|
|
26
|
+
inquirySubject: "",
|
|
27
|
+
inquiryMessage: "",
|
|
28
|
+
preferredContactMethod: "EMAIL",
|
|
29
|
+
submitted: false,
|
|
30
|
+
};
|
|
31
|
+
this.init();
|
|
32
|
+
}
|
|
33
|
+
async init() {
|
|
34
|
+
if (this.options.apiKey) {
|
|
35
|
+
await MedosClient.init({
|
|
36
|
+
apiKey: this.options.apiKey,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else if (this.options.sessionToken) {
|
|
40
|
+
await MedosClient.initWithSession({
|
|
41
|
+
sessionToken: this.options.sessionToken,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
throw new Error("Either apiKey or sessionToken must be provided");
|
|
46
|
+
}
|
|
47
|
+
this.render();
|
|
48
|
+
}
|
|
49
|
+
validateContactStep() {
|
|
50
|
+
this.setState({ error: null });
|
|
51
|
+
if (!validateName(this.state.patientName)) {
|
|
52
|
+
this.setState({ error: "Please enter a valid name." });
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (!validateEmail(this.state.patientEmail)) {
|
|
56
|
+
this.setState({ error: "Please enter a valid email address." });
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (!validateCountryCode(this.state.countryCode)) {
|
|
60
|
+
this.setState({
|
|
61
|
+
error: "Please enter a valid country code (e.g., +91, +1).",
|
|
62
|
+
});
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (!validatePhoneNumber(this.state.patientPhone)) {
|
|
66
|
+
this.setState({
|
|
67
|
+
error: "Please enter a valid phone number (7-15 digits).",
|
|
68
|
+
});
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
validateInquiryStep() {
|
|
74
|
+
this.setState({ error: null });
|
|
75
|
+
if (!validateSubject(this.state.inquirySubject)) {
|
|
76
|
+
this.setState({ error: "Please enter a valid subject." });
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
if (!validateMessage(this.state.inquiryMessage)) {
|
|
80
|
+
this.setState({
|
|
81
|
+
error: "Please enter a valid message (max 1000 characters).",
|
|
82
|
+
});
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
goToNext() {
|
|
88
|
+
if (this.state.step === 0) {
|
|
89
|
+
if (!this.validateContactStep()) {
|
|
90
|
+
this.render();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else if (this.state.step === 1) {
|
|
95
|
+
if (!this.validateInquiryStep()) {
|
|
96
|
+
this.render();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
this.state.step = Math.min(3, this.state.step + 1);
|
|
101
|
+
this.render();
|
|
102
|
+
}
|
|
103
|
+
goBack() {
|
|
104
|
+
this.state.step = Math.max(0, this.state.step - 1);
|
|
105
|
+
this.render();
|
|
106
|
+
}
|
|
107
|
+
async submitEnquiry() {
|
|
108
|
+
this.setState({ error: null });
|
|
109
|
+
if (!this.validateContactStep() || !this.validateInquiryStep()) {
|
|
110
|
+
this.render();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.setState({ loading: true });
|
|
114
|
+
this.render();
|
|
115
|
+
try {
|
|
116
|
+
const payload = {
|
|
117
|
+
patientName: this.state.patientName,
|
|
118
|
+
patientEmail: this.state.patientEmail,
|
|
119
|
+
countryCode: this.state.countryCode,
|
|
120
|
+
patientPhone: this.state.patientPhone,
|
|
121
|
+
inquirySubject: this.state.inquirySubject,
|
|
122
|
+
inquiryMessage: this.state.inquiryMessage,
|
|
123
|
+
preferredContactMethod: this.state.preferredContactMethod,
|
|
124
|
+
};
|
|
125
|
+
await EnquiryService.submitEnquiry(payload);
|
|
126
|
+
this.state.step = 3;
|
|
127
|
+
this.options.onSuccess?.(payload);
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
const msg = e.message || "Failed to submit enquiry";
|
|
131
|
+
this.setState({ error: msg });
|
|
132
|
+
this.options.onError?.(e);
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
this.setState({ loading: false });
|
|
136
|
+
this.render();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
resetForm() {
|
|
140
|
+
this.state = {
|
|
141
|
+
step: 0,
|
|
142
|
+
loading: false,
|
|
143
|
+
error: null,
|
|
144
|
+
patientName: "",
|
|
145
|
+
patientEmail: "",
|
|
146
|
+
countryCode: "+91",
|
|
147
|
+
patientPhone: "",
|
|
148
|
+
inquirySubject: "",
|
|
149
|
+
inquiryMessage: "",
|
|
150
|
+
preferredContactMethod: "EMAIL",
|
|
151
|
+
submitted: false,
|
|
152
|
+
};
|
|
153
|
+
this.render();
|
|
154
|
+
}
|
|
155
|
+
setState(updates) {
|
|
156
|
+
this.state = { ...this.state, ...updates };
|
|
157
|
+
}
|
|
158
|
+
render() {
|
|
159
|
+
if (!this.mounted)
|
|
160
|
+
return;
|
|
161
|
+
this.container.innerHTML = `
|
|
162
|
+
<div class="medos-enquiry-container">
|
|
163
|
+
<div class="medos-enquiry-card">
|
|
164
|
+
<div class="medos-enquiry-header">
|
|
165
|
+
<h2 class="medos-enquiry-title">Submit Inquiry</h2>
|
|
166
|
+
<p class="medos-enquiry-step-indicator">Step ${this.state.step + 1} of 4</p>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
${this.state.loading
|
|
170
|
+
? '<div class="medos-enquiry-loading">Loading...</div>'
|
|
171
|
+
: ""}
|
|
172
|
+
${this.state.error
|
|
173
|
+
? `<div class="medos-enquiry-error">${this.escapeHtml(this.state.error)}</div>`
|
|
174
|
+
: ""}
|
|
175
|
+
|
|
176
|
+
${this.renderStep()}
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
`;
|
|
180
|
+
this.attachEventListeners();
|
|
181
|
+
}
|
|
182
|
+
renderStep() {
|
|
183
|
+
switch (this.state.step) {
|
|
184
|
+
case 0:
|
|
185
|
+
return this.renderStep0();
|
|
186
|
+
case 1:
|
|
187
|
+
return this.renderStep1();
|
|
188
|
+
case 2:
|
|
189
|
+
return this.renderStep2();
|
|
190
|
+
case 3:
|
|
191
|
+
return this.renderStep3();
|
|
192
|
+
default:
|
|
193
|
+
return "";
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
renderStep0() {
|
|
197
|
+
return `
|
|
198
|
+
<div class="medos-enquiry-section">
|
|
199
|
+
<label class="medos-enquiry-label">Full Name *</label>
|
|
200
|
+
<input
|
|
201
|
+
type="text"
|
|
202
|
+
class="medos-enquiry-input"
|
|
203
|
+
id="medos-enquiry-name"
|
|
204
|
+
placeholder="Enter your full name"
|
|
205
|
+
value="${this.escapeHtml(this.state.patientName)}"
|
|
206
|
+
/>
|
|
207
|
+
|
|
208
|
+
<label class="medos-enquiry-label" style="margin-top: 12px">Email Address *</label>
|
|
209
|
+
<input
|
|
210
|
+
type="email"
|
|
211
|
+
class="medos-enquiry-input"
|
|
212
|
+
id="medos-enquiry-email"
|
|
213
|
+
placeholder="your.email@example.com"
|
|
214
|
+
value="${this.escapeHtml(this.state.patientEmail)}"
|
|
215
|
+
/>
|
|
216
|
+
|
|
217
|
+
<label class="medos-enquiry-label" style="margin-top: 12px">Country Code *</label>
|
|
218
|
+
<input
|
|
219
|
+
type="text"
|
|
220
|
+
class="medos-enquiry-input"
|
|
221
|
+
id="medos-enquiry-country-code"
|
|
222
|
+
placeholder="+91"
|
|
223
|
+
value="${this.escapeHtml(this.state.countryCode)}"
|
|
224
|
+
/>
|
|
225
|
+
|
|
226
|
+
<label class="medos-enquiry-label" style="margin-top: 12px">Phone Number *</label>
|
|
227
|
+
<input
|
|
228
|
+
type="tel"
|
|
229
|
+
class="medos-enquiry-input"
|
|
230
|
+
id="medos-enquiry-phone"
|
|
231
|
+
placeholder="9876543210"
|
|
232
|
+
value="${this.escapeHtml(this.state.patientPhone)}"
|
|
233
|
+
maxlength="15"
|
|
234
|
+
/>
|
|
235
|
+
|
|
236
|
+
<div class="medos-enquiry-actions">
|
|
237
|
+
<button class="medos-enquiry-btn medos-enquiry-btn-secondary" id="medos-enquiry-btn-cancel">Cancel</button>
|
|
238
|
+
<button class="medos-enquiry-btn medos-enquiry-btn-primary" id="medos-enquiry-btn-next">Next</button>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
`;
|
|
242
|
+
}
|
|
243
|
+
renderStep1() {
|
|
244
|
+
return `
|
|
245
|
+
<div class="medos-enquiry-section">
|
|
246
|
+
<label class="medos-enquiry-label">Subject *</label>
|
|
247
|
+
<input
|
|
248
|
+
type="text"
|
|
249
|
+
class="medos-enquiry-input"
|
|
250
|
+
id="medos-enquiry-subject"
|
|
251
|
+
placeholder="What is your inquiry about?"
|
|
252
|
+
value="${this.escapeHtml(this.state.inquirySubject)}"
|
|
253
|
+
/>
|
|
254
|
+
|
|
255
|
+
<label class="medos-enquiry-label" style="margin-top: 12px">Message *</label>
|
|
256
|
+
<textarea
|
|
257
|
+
class="medos-enquiry-textarea"
|
|
258
|
+
id="medos-enquiry-message"
|
|
259
|
+
placeholder="Please describe your inquiry in detail (max 1000 characters)"
|
|
260
|
+
maxlength="1000"
|
|
261
|
+
>${this.escapeHtml(this.state.inquiryMessage)}</textarea>
|
|
262
|
+
<div class="medos-enquiry-char-count">${this.state.inquiryMessage.length}/1000</div>
|
|
263
|
+
|
|
264
|
+
<div class="medos-enquiry-actions">
|
|
265
|
+
<button class="medos-enquiry-btn medos-enquiry-btn-secondary" id="medos-enquiry-btn-back">Back</button>
|
|
266
|
+
<button class="medos-enquiry-btn medos-enquiry-btn-primary" id="medos-enquiry-btn-next">Next</button>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
`;
|
|
270
|
+
}
|
|
271
|
+
renderStep2() {
|
|
272
|
+
return `
|
|
273
|
+
<div class="medos-enquiry-section">
|
|
274
|
+
<label class="medos-enquiry-label">Preferred Contact Method *</label>
|
|
275
|
+
<div class="medos-enquiry-radio-group">
|
|
276
|
+
<label class="medos-enquiry-radio-label">
|
|
277
|
+
<input
|
|
278
|
+
type="radio"
|
|
279
|
+
name="contact-method"
|
|
280
|
+
value="PHONE"
|
|
281
|
+
${this.state.preferredContactMethod === "PHONE" ? "checked" : ""}
|
|
282
|
+
id="medos-enquiry-contact-phone"
|
|
283
|
+
/>
|
|
284
|
+
<span>Phone</span>
|
|
285
|
+
</label>
|
|
286
|
+
<label class="medos-enquiry-radio-label">
|
|
287
|
+
<input
|
|
288
|
+
type="radio"
|
|
289
|
+
name="contact-method"
|
|
290
|
+
value="EMAIL"
|
|
291
|
+
${this.state.preferredContactMethod === "EMAIL" ? "checked" : ""}
|
|
292
|
+
id="medos-enquiry-contact-email"
|
|
293
|
+
/>
|
|
294
|
+
<span>Email</span>
|
|
295
|
+
</label>
|
|
296
|
+
<label class="medos-enquiry-radio-label">
|
|
297
|
+
<input
|
|
298
|
+
type="radio"
|
|
299
|
+
name="contact-method"
|
|
300
|
+
value="BOTH"
|
|
301
|
+
${this.state.preferredContactMethod === "BOTH" ? "checked" : ""}
|
|
302
|
+
id="medos-enquiry-contact-both"
|
|
303
|
+
/>
|
|
304
|
+
<span>Both</span>
|
|
305
|
+
</label>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
<div class="medos-enquiry-actions">
|
|
309
|
+
<button class="medos-enquiry-btn medos-enquiry-btn-secondary" id="medos-enquiry-btn-back">Back</button>
|
|
310
|
+
<button class="medos-enquiry-btn medos-enquiry-btn-primary" id="medos-enquiry-btn-submit" ${this.state.loading ? "disabled" : ""} style="opacity: ${this.state.loading ? 0.6 : 1}">${this.state.loading ? "Submitting..." : "Submit Inquiry"}</button>
|
|
311
|
+
</div>
|
|
312
|
+
</div>
|
|
313
|
+
`;
|
|
314
|
+
}
|
|
315
|
+
renderStep3() {
|
|
316
|
+
return `
|
|
317
|
+
<div class="medos-enquiry-section" style="text-align: center">
|
|
318
|
+
<div class="medos-enquiry-success-card">
|
|
319
|
+
<div class="medos-enquiry-success-icon">✓</div>
|
|
320
|
+
<div class="medos-enquiry-success-title">Inquiry Submitted Successfully</div>
|
|
321
|
+
<div class="medos-enquiry-success-message">Thank you, ${this.escapeHtml(this.state.patientName || "Patient")}. We have received your inquiry and will get back to you soon.</div>
|
|
322
|
+
</div>
|
|
323
|
+
<div style="margin-top: 14px; display: flex; justify-content: center">
|
|
324
|
+
<button class="medos-enquiry-btn medos-enquiry-btn-primary" id="medos-enquiry-btn-submit-another" style="width: 160px">Submit Another</button>
|
|
325
|
+
</div>
|
|
326
|
+
</div>
|
|
327
|
+
`;
|
|
328
|
+
}
|
|
329
|
+
attachEventListeners() {
|
|
330
|
+
const nameInput = this.container.querySelector("#medos-enquiry-name");
|
|
331
|
+
if (nameInput) {
|
|
332
|
+
nameInput.addEventListener("input", (e) => {
|
|
333
|
+
const target = e.target;
|
|
334
|
+
this.state.patientName = target.value;
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
const emailInput = this.container.querySelector("#medos-enquiry-email");
|
|
338
|
+
if (emailInput) {
|
|
339
|
+
emailInput.addEventListener("input", (e) => {
|
|
340
|
+
const target = e.target;
|
|
341
|
+
this.state.patientEmail = target.value;
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
const countryCodeInput = this.container.querySelector("#medos-enquiry-country-code");
|
|
345
|
+
if (countryCodeInput) {
|
|
346
|
+
countryCodeInput.addEventListener("input", (e) => {
|
|
347
|
+
const target = e.target;
|
|
348
|
+
let value = target.value;
|
|
349
|
+
if (value && !value.startsWith("+")) {
|
|
350
|
+
value = "+" + value;
|
|
351
|
+
}
|
|
352
|
+
value = value.replace(/[^\d+]/g, "");
|
|
353
|
+
this.state.countryCode = value;
|
|
354
|
+
target.value = value;
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
const phoneInput = this.container.querySelector("#medos-enquiry-phone");
|
|
358
|
+
if (phoneInput) {
|
|
359
|
+
phoneInput.addEventListener("input", (e) => {
|
|
360
|
+
const target = e.target;
|
|
361
|
+
this.state.patientPhone = target.value.replace(/\D/g, "");
|
|
362
|
+
target.value = this.state.patientPhone;
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
const subjectInput = this.container.querySelector("#medos-enquiry-subject");
|
|
366
|
+
if (subjectInput) {
|
|
367
|
+
subjectInput.addEventListener("input", (e) => {
|
|
368
|
+
const target = e.target;
|
|
369
|
+
this.state.inquirySubject = target.value;
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
const messageInput = this.container.querySelector("#medos-enquiry-message");
|
|
373
|
+
if (messageInput) {
|
|
374
|
+
messageInput.addEventListener("input", (e) => {
|
|
375
|
+
const target = e.target;
|
|
376
|
+
this.state.inquiryMessage = target.value;
|
|
377
|
+
this.render();
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
const contactMethodRadios = this.container.querySelectorAll('input[name="contact-method"]');
|
|
381
|
+
contactMethodRadios.forEach((radio) => {
|
|
382
|
+
radio.addEventListener("change", (e) => {
|
|
383
|
+
const target = e.target;
|
|
384
|
+
this.state.preferredContactMethod = target.value;
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
const nextBtn = this.container.querySelector("#medos-enquiry-btn-next");
|
|
388
|
+
if (nextBtn) {
|
|
389
|
+
nextBtn.addEventListener("click", () => this.goToNext());
|
|
390
|
+
}
|
|
391
|
+
const backBtn = this.container.querySelector("#medos-enquiry-btn-back");
|
|
392
|
+
if (backBtn) {
|
|
393
|
+
backBtn.addEventListener("click", () => this.goBack());
|
|
394
|
+
}
|
|
395
|
+
const submitBtn = this.container.querySelector("#medos-enquiry-btn-submit");
|
|
396
|
+
if (submitBtn) {
|
|
397
|
+
submitBtn.addEventListener("click", () => this.submitEnquiry());
|
|
398
|
+
}
|
|
399
|
+
const cancelBtn = this.container.querySelector("#medos-enquiry-btn-cancel");
|
|
400
|
+
if (cancelBtn) {
|
|
401
|
+
cancelBtn.addEventListener("click", () => this.resetForm());
|
|
402
|
+
}
|
|
403
|
+
const submitAnotherBtn = this.container.querySelector("#medos-enquiry-btn-submit-another");
|
|
404
|
+
if (submitAnotherBtn) {
|
|
405
|
+
submitAnotherBtn.addEventListener("click", () => this.resetForm());
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
escapeHtml(text) {
|
|
409
|
+
const div = document.createElement("div");
|
|
410
|
+
div.textContent = text;
|
|
411
|
+
return div.innerHTML;
|
|
412
|
+
}
|
|
413
|
+
destroy() {
|
|
414
|
+
this.mounted = false;
|
|
415
|
+
this.container.innerHTML = "";
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
export function initEnquiryForm(options) {
|
|
419
|
+
const container = document.getElementById(options.containerId);
|
|
420
|
+
if (!container) {
|
|
421
|
+
throw new Error(`Container element with id "${options.containerId}" not found`);
|
|
422
|
+
}
|
|
423
|
+
return new EnquiryFormWidget(container, options);
|
|
424
|
+
}
|
|
425
|
+
export { EnquiryFormWidget };
|
|
@@ -3,11 +3,9 @@ import { AddressesResponse } from "../services/AppointmentService";
|
|
|
3
3
|
import { SendPhoneVerificationOtpPayload, VerifyPhoneVerificationOtpPayload } from "../services/PatientService";
|
|
4
4
|
interface MedosClientConfig {
|
|
5
5
|
apiKey: string;
|
|
6
|
-
baseURL?: string;
|
|
7
6
|
}
|
|
8
7
|
interface MedosClientSessionConfig {
|
|
9
8
|
sessionToken: string;
|
|
10
|
-
baseURL?: string;
|
|
11
9
|
}
|
|
12
10
|
declare class MedosClient {
|
|
13
11
|
private static instance;
|
|
@@ -16,8 +14,8 @@ declare class MedosClient {
|
|
|
16
14
|
private static isRefreshing;
|
|
17
15
|
private static pendingRequests;
|
|
18
16
|
private static initPromise;
|
|
19
|
-
static init({ apiKey
|
|
20
|
-
static initWithSession({ sessionToken
|
|
17
|
+
static init({ apiKey }: MedosClientConfig): Promise<void>;
|
|
18
|
+
static initWithSession({ sessionToken }: MedosClientSessionConfig): Promise<void>;
|
|
21
19
|
private static initializeAxiosInstance;
|
|
22
20
|
static fetchAllAddressesAndDoctors(): Promise<AddressesResponse>;
|
|
23
21
|
static fetchAppointments(workspaceId: number, addressId: number, doctorId: number, appointmentDate: string): Promise<any[]>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface ContactInformationStepProps {
|
|
3
|
+
patientName: string;
|
|
4
|
+
patientEmail: string;
|
|
5
|
+
countryCode: string;
|
|
6
|
+
patientPhone: string;
|
|
7
|
+
onNameChange: (value: string) => void;
|
|
8
|
+
onEmailChange: (value: string) => void;
|
|
9
|
+
onCountryCodeChange: (value: string) => void;
|
|
10
|
+
onPhoneChange: (value: string) => void;
|
|
11
|
+
onNext: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const ContactInformationStep: React.FC<ContactInformationStepProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface ContactPreferenceStepProps {
|
|
3
|
+
preferredContactMethod: "PHONE" | "EMAIL" | "BOTH";
|
|
4
|
+
onContactMethodChange: (method: "PHONE" | "EMAIL" | "BOTH") => void;
|
|
5
|
+
onBack: () => void;
|
|
6
|
+
onSubmit: () => void;
|
|
7
|
+
isLoading?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const ContactPreferenceStep: React.FC<ContactPreferenceStepProps>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { EnquirySubmission } from "../enquiry-form/types";
|
|
3
|
+
export interface EnquiryFormProps {
|
|
4
|
+
onSuccess?: (enquiry: EnquirySubmission) => void;
|
|
5
|
+
onError?: (error: Error) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const EnquiryForm: React.FC<EnquiryFormProps>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface InquiryDetailsStepProps {
|
|
3
|
+
inquirySubject: string;
|
|
4
|
+
inquiryMessage: string;
|
|
5
|
+
onSubjectChange: (value: string) => void;
|
|
6
|
+
onMessageChange: (value: string) => void;
|
|
7
|
+
onBack: () => void;
|
|
8
|
+
onNext: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const InquiryDetailsStep: React.FC<InquiryDetailsStepProps>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { MedosTheme } from "../core/theme/types";
|
|
3
|
+
export declare function getContainerStyles(theme: MedosTheme, prefix?: string): Record<string, React.CSSProperties>;
|
|
4
|
+
export declare function getButtonStyles(theme: MedosTheme, prefix?: string): Record<string, React.CSSProperties>;
|
|
5
|
+
export declare function getPhoneVerifyStyles(theme: MedosTheme, prefix?: string): Record<string, React.CSSProperties>;
|
|
6
|
+
export declare function getPatientDetailsStyles(theme: MedosTheme, prefix?: string): Record<string, React.CSSProperties>;
|
|
7
|
+
export declare function getSuccessStyles(theme: MedosTheme, prefix?: string): Record<string, React.CSSProperties>;
|
|
8
|
+
export declare const CONTAINER_STYLES: Record<string, React.CSSProperties>;
|
|
9
|
+
export declare const BUTTON_STYLES: Record<string, React.CSSProperties>;
|
|
10
|
+
export declare const PHONE_VERIFY_STYLES: Record<string, React.CSSProperties>;
|
|
11
|
+
export declare const PATIENT_DETAILS_STYLES: Record<string, React.CSSProperties>;
|
|
12
|
+
export declare const SUCCESS_STYLES: Record<string, React.CSSProperties>;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
export { MedosClient } from "../client/MedosClient";
|
|
2
|
+
export * from "./theme";
|
|
2
3
|
export * from "../appointments/provider";
|
|
3
4
|
export * from "../appointments/types";
|
|
4
5
|
export * from "../appointment-calendar/provider";
|
|
5
6
|
export * from "../appointment-calendar/types";
|
|
7
|
+
export * from "../enquiry-form/provider";
|
|
8
|
+
export * from "../enquiry-form/types";
|
|
6
9
|
export { PatientService, SendPhoneVerificationOtpPayload, VerifyPhoneVerificationOtpPayload, } from "../services/PatientService";
|
|
7
10
|
export { AppointmentService, type BookAppointmentPayload, type PatientPayload, type PatientAddressPayload, type AddressesResponse, type AddressItem, } from "../services/AppointmentService";
|
|
8
11
|
export { AuthService } from "../services/AuthService";
|
|
12
|
+
export { EnquiryService } from "../services/EnquiryService";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MedosTheme } from "./types";
|
|
2
|
+
export declare const defaultTheme: MedosTheme;
|
|
3
|
+
export declare const modernTheme: MedosTheme;
|
|
4
|
+
export declare const themes: {
|
|
5
|
+
readonly default: MedosTheme;
|
|
6
|
+
readonly modern: MedosTheme;
|
|
7
|
+
};
|
|
8
|
+
export type ThemeName = keyof typeof themes;
|
|
@@ -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,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[];
|