pr360-questionnaire 2.1.11 → 2.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,6 +29,13 @@ export type ContactInfo = {
29
29
  text: string;
30
30
  }
31
31
 
32
+ export type Verification = {
33
+ id: string;
34
+ type: "Verification";
35
+ text: string;
36
+ phoneNumber: string;
37
+ }
38
+
32
39
  export type Answer = {
33
40
  id: string;
34
41
  text: string;
@@ -36,9 +43,9 @@ export type Answer = {
36
43
 
37
44
  @customElement('pr360-questionnaire')
38
45
  @liveState({
39
- properties: ['currentStep', 'visitedNodes', 'phoneNumber', 'links', 'accountActive', 'questionnaireDepth', 'providers', 'outcome'],
46
+ properties: ['currentStep', 'visitedNodes', 'phoneNumber', 'links', 'accountActive', 'questionnaireDepth', 'providers', 'outcome', 'verificationError'],
40
47
  events: {
41
- send: ['answerQuestion', 'submitContactInfo', 'goBack', 'setUtmParams']
48
+ send: ['answerQuestion', 'submitContactInfo', 'goBack', 'setUtmParams', 'submitVerification', 'resendCode']
42
49
  },
43
50
  provide: {
44
51
  scope: window,
@@ -49,7 +56,7 @@ export class QuestionnaireElement extends LitElement {
49
56
  static styles = questionnaireStyles;
50
57
 
51
58
  @state()
52
- currentStep: Question | ContactInfo | Video | undefined;
59
+ currentStep: Question | ContactInfo | Video | Verification | undefined;
53
60
 
54
61
  @state()
55
62
  accountActive: boolean = true;
@@ -70,6 +77,9 @@ export class QuestionnaireElement extends LitElement {
70
77
 
71
78
  @state() outcome: string;
72
79
 
80
+ @state()
81
+ verificationError: string | null = null;
82
+
73
83
  @property()
74
84
  @liveStateConfig('url')
75
85
  url: string | undefined;
@@ -104,6 +114,9 @@ export class QuestionnaireElement extends LitElement {
104
114
  @query('#insurance_provider')
105
115
  insuranceProviderSelect: HTMLSelectElement| undefined;
106
116
 
117
+ @query('#verification_code')
118
+ verificationCodeInput: HTMLInputElement | undefined;
119
+
107
120
  @query('form')
108
121
  contactInfoForm: HTMLFormElement | undefined;
109
122
 
@@ -205,6 +218,7 @@ export class QuestionnaireElement extends LitElement {
205
218
  case "Question": return this.renderQuestion();
206
219
  case "ContactInfo": return this.renderContactInfo();
207
220
  case "Video": return this.renderVideo();
221
+ case "Verification": return this.renderVerification();
208
222
  }
209
223
  }
210
224
 
@@ -282,6 +296,38 @@ export class QuestionnaireElement extends LitElement {
282
296
  `;
283
297
  }
284
298
 
299
+ renderVerification() {
300
+ const verification = this.currentStep as Verification;
301
+ return html`
302
+ <div class="questionnaire fade-in fade-out">
303
+ <div class="questionnaire-illustration"><img src=${this.contactInfoImageUrl()}> </div>
304
+ <div class="form__container">
305
+ <div class="header">
306
+ <h1>Verify Your Phone Number</h1>
307
+ <h2>${verification.text}</h2>
308
+ <p class="verification-phone-number">We've sent a verification code to ${verification.phoneNumber}</p>
309
+ </div>
310
+ <form @submit=${this.submitVerification}>
311
+ <div class="form verification-form">
312
+ <div class="verification-input-container">
313
+ <label for="verification_code">Verification Code</label>
314
+ <input type="text" id="verification_code" name="verification_code" required
315
+ pattern="^[a-zA-Z0-9]+$"
316
+ title="Please enter the verification code" />
317
+ ${this.verificationError ? html`<div class="error">${this.verificationError}</div>` : ''}
318
+ </div>
319
+ </div>
320
+ <div class="footer u-text-center">
321
+ <button class="button button--primary u-push-top" type="submit">Submit</button>
322
+ <button class="button--link" type="button" @click=${this.goBackToContactInfo}>Go Back</button>
323
+ <button class="button--link verification-resend-button" type="button" @click=${this.resendCode}>Resend Code</button>
324
+ </div>
325
+ </form>
326
+ </div>
327
+ </div>
328
+ `;
329
+ }
330
+
285
331
  imageSrc() {
286
332
  return this.absolutifyImageUrl((this.currentStep as Question).url);
287
333
  }
@@ -383,4 +429,29 @@ export class QuestionnaireElement extends LitElement {
383
429
  }));
384
430
  }
385
431
  }
432
+
433
+ submitVerification(event: Event) {
434
+ event.stopPropagation();
435
+ event.preventDefault();
436
+
437
+ const code = this.verificationCodeInput?.value;
438
+ if (code) {
439
+ this.verificationError = null;
440
+ // Extract node_id from verification id (format: "verification_nodeId")
441
+ const nodeId = this.currentStep?.id.replace('verification_', '');
442
+ this.dispatchEvent(new CustomEvent('submitVerification', {
443
+ detail: { verificationCode: code, nodeId: nodeId }
444
+ }));
445
+ }
446
+ }
447
+
448
+ resendCode(event: Event) {
449
+ event.stopPropagation();
450
+ this.dispatchEvent(new CustomEvent('resendCode'));
451
+ }
452
+
453
+ goBackToContactInfo(event: Event) {
454
+ event.stopPropagation();
455
+ this.dispatchEvent(new CustomEvent('goBack'));
456
+ }
386
457
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pr360-questionnaire",
3
3
  "description": "An element to render a questionnaire for PatientReach 360.",
4
- "version": "2.1.11",
4
+ "version": "2.2.11",
5
5
  "main": "dist/index.js",
6
6
  "author": {
7
7
  "email": "chris@launchscout.com",
@@ -1,6 +1,6 @@
1
1
  import '../js/questionnaire';
2
2
  import { expect } from "@esm-bundle/chai";
3
- import { ContactInfo, QuestionnaireElement} from '../js/questionnaire';
3
+ import { ContactInfo, QuestionnaireElement, Verification} from '../js/questionnaire';
4
4
  import { fixture } from '@open-wc/testing';
5
5
  import { sendKeys } from '@web/test-runner-commands';
6
6
  import LiveState from 'phx-live-state';
@@ -84,4 +84,51 @@ describe('questionnaire test', async () => {
84
84
  console.log(img);
85
85
  expect(img?.src).to.equal("https://foo.bar/images/foo");
86
86
  });
87
+
88
+ it('renders verification screen', async () => {
89
+ questionnaireElement.currentStep = {
90
+ id: "verification_123",
91
+ type: "Verification",
92
+ text: "Please enter the verification code we sent to your phone.",
93
+ phoneNumber: "555-123-4567"
94
+ } as Verification;
95
+ questionnaireElement.links = {
96
+ contact_info_image: '/images/contact.jpg'
97
+ };
98
+
99
+ const button = questionnaireElement.querySelector('button');
100
+ button?.click();
101
+ await questionnaireElement.updateComplete;
102
+
103
+ expect(questionnaireElement.shadowRoot?.textContent).to.contain("Verify Your Phone Number");
104
+ expect(questionnaireElement.shadowRoot?.textContent).to.contain("555-123-4567");
105
+ expect(questionnaireElement.shadowRoot?.querySelector('#verification_code')).to.exist;
106
+ expect(questionnaireElement.shadowRoot?.textContent).to.contain("Submit");
107
+ expect(questionnaireElement.shadowRoot?.textContent).to.contain("Resend Code");
108
+ expect(questionnaireElement.shadowRoot?.textContent).to.contain("Go Back");
109
+
110
+ // Verify Go Back button is at top left (button--link class)
111
+ const goBackButton = Array.from(questionnaireElement.shadowRoot?.querySelectorAll('.button--link') || [])
112
+ .find(btn => btn.textContent?.includes('Go Back'));
113
+ expect(goBackButton).to.exist;
114
+ });
115
+
116
+ it('displays verification error when present', async () => {
117
+ questionnaireElement.currentStep = {
118
+ id: "verification_123",
119
+ type: "Verification",
120
+ text: "Please enter the verification code we sent to your phone.",
121
+ phoneNumber: "555-123-4567"
122
+ } as Verification;
123
+ questionnaireElement.verificationError = "Invalid verification code";
124
+ questionnaireElement.links = {
125
+ contact_info_image: '/images/contact.jpg'
126
+ };
127
+
128
+ const button = questionnaireElement.querySelector('button');
129
+ button?.click();
130
+ await questionnaireElement.updateComplete;
131
+
132
+ expect(questionnaireElement.shadowRoot?.textContent).to.contain("Invalid verification code");
133
+ });
87
134
  });