From e361dcab659b33a9a8caf3d6c366e81c1610c7ed Mon Sep 17 00:00:00 2001 From: Reuben Molinares Date: Thu, 29 Oct 2026 16:25:50 -0400 Subject: [PATCH 1/6] Locale updates (#2052) --- webroot/package.json | 2 +- webroot/src/locales/en.json | 2 +- webroot/src/locales/es.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/webroot/package.json b/webroot/package.json index a9491e3e5..fe6ab01c4 100644 --- a/webroot/package.json +++ b/webroot/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "scripts": { - "serve": "yarn audit:dependencies && yarn lint --no-fix && vue-cli-service serve", + "serve": "yarn lint --no-fix && vue-cli-service serve", "build": "yarn audit:dependencies && vue-cli-service build", "test:unit:all": "export NODE_OPTIONS=--openssl-legacy-provider && yarn lint --no-fix && vue-cli-service test:unit 'src/**/*.spec.ts'", "test:unit": "export NODE_OPTIONS=--openssl-legacy-provider && yarn lint --no-fix && vue-cli-service test:unit", diff --git a/webroot/src/locales/en.json b/webroot/src/locales/en.json index 661dd776f..3900c371d 100644 --- a/webroot/src/locales/en.json +++ b/webroot/src/locales/en.json @@ -707,7 +707,7 @@ "noHistory": "No history", "historyDisclaimer": "For further information regarding disciplinary action, please visit the website of the relevant licensing board in the state where the license or privilege is held.", "twoHomeStateErrorMessage": "Two states have you listed as a resident. Please update your information with those states to reflect your current residency status.", - "jurisprudenceExplanationText": "I attest I have successfully completed a jurisprudence exam for this state, if required", + "jurisprudenceExplanationText": "I attest that I have successfully completed or will successfully complete the jurisprudence requirement for that state within the timeframe required by that state.", "scopeAttestTitle": "Scope of practice attestation", "scopeAttestLabel": "Click here to read and affirm the scope of practice attestation.", "attestations": "Attestations", diff --git a/webroot/src/locales/es.json b/webroot/src/locales/es.json index 5626c5611..72bdf8bdb 100644 --- a/webroot/src/locales/es.json +++ b/webroot/src/locales/es.json @@ -687,7 +687,7 @@ "jurisdictionFee": "Tarifa Estatal", "jurisdictionFeeMilitary": "Tarifa Estatal (militar)", "disciplineStatus": "Estado de disciplina", - "jurisprudenceExplanationText": "Certifico que he completado con éxito un examen de jurisprudencia para este estado, si es necesario.", + "jurisprudenceExplanationText": "Certifico que he completado con éxito o completaré con éxito el requisito de jurisprudencia para ese estado dentro del plazo requerido por ese estado.", "scopeAttestTitle": "Alcance de la certificación de práctica", "scopeAttestLabel": "Haga clic aquí para leer y afirmar el alcance de la certificación de práctica.", "noDiscipline": "No disciplina", From e03410243e2270b7f559684b35dab0cbe815ae36 Mon Sep 17 00:00:00 2001 From: Reuben Molinares Date: Thu, 29 Oct 2026 16:35:00 -0400 Subject: [PATCH 2/6] Vulnerability patch --- webroot/package.json | 4 +-- webroot/yarn.lock | 58 ++++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/webroot/package.json b/webroot/package.json index fe6ab01c4..b2858f1a0 100644 --- a/webroot/package.json +++ b/webroot/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "scripts": { - "serve": "yarn lint --no-fix && vue-cli-service serve", + "serve": "yarn audit:dependencies && yarn lint --no-fix && vue-cli-service serve", "build": "yarn audit:dependencies && vue-cli-service build", "test:unit:all": "export NODE_OPTIONS=--openssl-legacy-provider && yarn lint --no-fix && vue-cli-service test:unit 'src/**/*.spec.ts'", "test:unit": "export NODE_OPTIONS=--openssl-legacy-provider && yarn lint --no-fix && vue-cli-service test:unit", @@ -37,7 +37,7 @@ "uuid": "^14.0.1", "vue": "^3.5.41", "vue-facing-decorator": "^3.0.4", - "vue-i18n": "^11.4.8", + "vue-i18n": "^11.4.16", "vue-responsiveness": "^0.2.5", "vue-router": "^4.5.1", "vue3-lazyload": "^0.4.2", diff --git a/webroot/yarn.lock b/webroot/yarn.lock index c9a8f3a09..7d9e8d82b 100644 --- a/webroot/yarn.lock +++ b/webroot/yarn.lock @@ -1399,35 +1399,35 @@ chardet "^2.1.1" iconv-lite "^0.7.0" -"@intlify/core-base@11.4.8": - version "11.4.8" - resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-11.4.8.tgz#1cbb60e2cad25a88a7db8896f6d5652c9792c16e" - integrity sha512-A+Q7SKm5oEcy1E/cghqd7n/St4XjTqLhiiyDuieNcMrJcrHlkY5n0jp7Q9dD3txvVHzvsmBVV5M9wD5/s1zfzw== +"@intlify/core-base@11.4.16": + version "11.4.16" + resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-11.4.16.tgz#8483379fff200d978e37cbc9ee4edf719fadcc46" + integrity sha512-xB8nMdMRLNx7b0zPvrHy0+N9uq9Vfi1aUxHqWgn2e2/TbjCKy8HfoFpnUXXxVP8I0p1ccd6LFSC3XsFjZ3vweA== dependencies: - "@intlify/devtools-types" "11.4.8" - "@intlify/message-compiler" "11.4.8" - "@intlify/shared" "11.4.8" + "@intlify/devtools-types" "11.4.16" + "@intlify/message-compiler" "11.4.16" + "@intlify/shared" "11.4.16" -"@intlify/devtools-types@11.4.8": - version "11.4.8" - resolved "https://registry.yarnpkg.com/@intlify/devtools-types/-/devtools-types-11.4.8.tgz#c71d284e218159aa11eaae4ec9166f15fc21fb37" - integrity sha512-MGpID+rlfzGUbNcnC20bm5NMSBHPrvx0atLTfv9dftn3kjXw1hGKDcIcwrO99tSrZEc2i+hczRL7ks8qXsHPkQ== +"@intlify/devtools-types@11.4.16": + version "11.4.16" + resolved "https://registry.yarnpkg.com/@intlify/devtools-types/-/devtools-types-11.4.16.tgz#21ffc193e1aa272b0a0a4432343cbae2b0a7ef34" + integrity sha512-Bl7arICsKgwcSEQuZJun3swenN4jwSpg35lCpijFznYbW9GvkfH4wLxcI5+gz7d/EHqu66UT9CZDIdnQdgMAGg== dependencies: - "@intlify/core-base" "11.4.8" - "@intlify/shared" "11.4.8" + "@intlify/core-base" "11.4.16" + "@intlify/shared" "11.4.16" -"@intlify/message-compiler@11.4.8": - version "11.4.8" - resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-11.4.8.tgz#4f8ef43a1076899102335d456f8309d3c1666510" - integrity sha512-vbzk17dYwduYiv52EK61+FDCyhfVg1uPUtPmiD/d45W99uJIcXywrweOBcHv7n9/iEqmXiMGT52bgJbZDQqK3w== +"@intlify/message-compiler@11.4.16": + version "11.4.16" + resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-11.4.16.tgz#38718635ba4997fe052009f239d8f2a8e6d971b5" + integrity sha512-p4lDWmBAsi3ja+PuEfPRavYyvqkYn/Upxz7UpnyI9LgIIy8XawcGIDzN+k99Z+99etO3HmDXGeTxnJIJGgSZ+g== dependencies: - "@intlify/shared" "11.4.8" + "@intlify/shared" "11.4.16" source-map-js "^1.0.2" -"@intlify/shared@11.4.8": - version "11.4.8" - resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-11.4.8.tgz#3c62c7882d07f4ab0f909760308accdc1465ea3d" - integrity sha512-XbRgrv+XEuvDr7UCY55oibVrh+o4u+A0VB6nSL0F5Z8LcZxE/8j573LYG6bCrOigIcHdGpSNI7Rh5UpC5/B/eg== +"@intlify/shared@11.4.16": + version "11.4.16" + resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-11.4.16.tgz#b06ea77ebf991d327d5d1f82d4af73a6235dc569" + integrity sha512-xehmkbEgbbNh/V+d8r3hFup0ViaN29YTJSAfRr28C54rxjyZEO0RNQKqW7VVajj16gLdglotNjiq+sIVNtHGzw== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -12720,14 +12720,14 @@ vue-hot-reload-api@^2.3.0: resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== -vue-i18n@^11.4.8: - version "11.4.8" - resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-11.4.8.tgz#2f2d9fa43d668dcafdc20875d5d15073bdc64ead" - integrity sha512-0ULeHP6Z9CGvAm67S77ZEp41cfGXIREGL8qfhos2BMgcQQewtQcDKuojt6jjasAD/S8GwfTp2ySPmDSpwvrCMQ== +vue-i18n@^11.4.16: + version "11.4.16" + resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-11.4.16.tgz#3b3e16d1cc3effa37afbdcf4730f3c320ba110f4" + integrity sha512-Kv9tp6iTmaAeOwop7hkAo28N1IBsbSVpnxyE26b6gqc4Q2E9Ke3ZHHA3oqqwS6/cYLT1henZU4etTaLQxrK98Q== dependencies: - "@intlify/core-base" "11.4.8" - "@intlify/devtools-types" "11.4.8" - "@intlify/shared" "11.4.8" + "@intlify/core-base" "11.4.16" + "@intlify/devtools-types" "11.4.16" + "@intlify/shared" "11.4.16" "@vue/devtools-api" "^6.5.0" vue-loader@^17.0.0: From bfa07460b0c55da81564d20b4f25c30abb6e7ba5 Mon Sep 17 00:00:00 2001 From: Reuben Molinares Date: Thu, 29 Oct 2026 18:00:06 -0400 Subject: [PATCH 3/6] Sans dieticians (#2052) --- .../PrivilegePurchaseSelect.ts | 13 ++++++++++++- webroot/src/locales/en.json | 1 + webroot/src/locales/es.json | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts b/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts index 0591ae087..7d64116e9 100644 --- a/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts +++ b/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts @@ -30,6 +30,7 @@ import { AcceptedAttestationToSend } from '@models/AcceptedAttestationToSend/Acc import { PrivilegeAttestation } from '@models/PrivilegeAttestation/PrivilegeAttestation.model'; import { PurchaseFlowStep } from '@/models/PurchaseFlowStep/PurchaseFlowStep.model'; import { State } from '@/models/State/State.model'; +import { CompactType } from '@/utils/compactConfig'; import { dataApi } from '@network/data.api'; import moment from 'moment'; import Joi from 'joi'; @@ -229,6 +230,16 @@ export default class PrivilegePurchaseSelect extends mixins(MixinForm) { return this.numPrivilegesChosen > 0; } + get jurisprudenceExplanationTextKey(): string { + let key = 'licensing.jurisprudenceExplanationText'; + + if (this.currentCompactType === CompactType.DIETITIANS) { + key = 'licensing.jurisprudenceExamExplanationText'; + } + + return key; + } + get jurisprudenceAttestation(): PrivilegeAttestation { return this.attestationRecords.find((record) => ((record as any)?.id === 'jurisprudence-confirmation')) || new PrivilegeAttestation(); } @@ -307,7 +318,7 @@ export default class PrivilegePurchaseSelect extends mixins(MixinForm) { this.formData[`jurisprudence-${stateAbbrev}`] = new FormInput({ id: `jurisprudence-${stateAbbrev}`, name: `jurisprudence-${stateAbbrev}`, - label: computed(() => this.$t('licensing.jurisprudenceExplanationText')), + label: computed(() => this.$t(this.jurisprudenceExplanationTextKey)), value: false, validation: Joi.boolean().invalid(false).required().messages(this.joiMessages.boolean), }); diff --git a/webroot/src/locales/en.json b/webroot/src/locales/en.json index 3900c371d..3e9dcbef7 100644 --- a/webroot/src/locales/en.json +++ b/webroot/src/locales/en.json @@ -708,6 +708,7 @@ "historyDisclaimer": "For further information regarding disciplinary action, please visit the website of the relevant licensing board in the state where the license or privilege is held.", "twoHomeStateErrorMessage": "Two states have you listed as a resident. Please update your information with those states to reflect your current residency status.", "jurisprudenceExplanationText": "I attest that I have successfully completed or will successfully complete the jurisprudence requirement for that state within the timeframe required by that state.", + "jurisprudenceExamExplanationText": "I attest I have successfully completed a jurisprudence exam for this state, if required", "scopeAttestTitle": "Scope of practice attestation", "scopeAttestLabel": "Click here to read and affirm the scope of practice attestation.", "attestations": "Attestations", diff --git a/webroot/src/locales/es.json b/webroot/src/locales/es.json index 72bdf8bdb..9c72bc926 100644 --- a/webroot/src/locales/es.json +++ b/webroot/src/locales/es.json @@ -688,6 +688,7 @@ "jurisdictionFeeMilitary": "Tarifa Estatal (militar)", "disciplineStatus": "Estado de disciplina", "jurisprudenceExplanationText": "Certifico que he completado con éxito o completaré con éxito el requisito de jurisprudencia para ese estado dentro del plazo requerido por ese estado.", + "jurisprudenceExamExplanationText": "Certifico que he completado con éxito un examen de jurisprudencia para este estado, si es necesario.", "scopeAttestTitle": "Alcance de la certificación de práctica", "scopeAttestLabel": "Haga clic aquí para leer y afirmar el alcance de la certificación de práctica.", "noDiscipline": "No disciplina", From d8ef1aedb0643ba29ef602f47d62747346a40e84 Mon Sep 17 00:00:00 2001 From: John Sandoval Date: Fri, 30 Oct 2026 10:16:26 -0600 Subject: [PATCH 4/6] Expand mock purchase states to be dynamic for all compacts --- webroot/docs/ADD_COMPACT.md | 1 + webroot/src/network/mocks/mock.data.api.ts | 14 +- webroot/src/network/mocks/mock.data.ts | 437 +++++++++++---------- webroot/src/store/user/user.mutations.ts | 2 + webroot/src/store/user/user.spec.ts | 5 + 5 files changed, 255 insertions(+), 204 deletions(-) diff --git a/webroot/docs/ADD_COMPACT.md b/webroot/docs/ADD_COMPACT.md index 042ac8bd8..7a7024e71 100644 --- a/webroot/docs/ADD_COMPACT.md +++ b/webroot/docs/ADD_COMPACT.md @@ -155,6 +155,7 @@ Needed when exercising the new compact under the mock API: (Cosmetology and social work are omitted there on purpose because they do not allow registration.) - [ ] Add or extend licensee / search fixtures only if you need mock flows for that compact (many fixtures stay on `octp` by default) - [ ] Add mock overlay to `mockProviderCompactOverlays()` +- [ ] If the new compact's `AppGroupMode` is `PRIVILEGE_PURCHASE`, add its privilege fees to `mockPrivilegeFeesByCompact`. Include one `licenseTypeAbbreviation` per license type the purchase-options API returns. Cosmetology, social work, and PSYPACT are omitted because they are `MULTI_STATE` and do not sell privileges. ### 8. Optional / situational UI diff --git a/webroot/src/network/mocks/mock.data.api.ts b/webroot/src/network/mocks/mock.data.api.ts index e2662e909..c4710cc35 100644 --- a/webroot/src/network/mocks/mock.data.api.ts +++ b/webroot/src/network/mocks/mock.data.api.ts @@ -25,7 +25,7 @@ import { licensees, users, pets, - privilegePurchaseOptionsResponse, + getPrivilegePurchaseOptionsResponse, getAttestation, compactStates, compactStatesForRegistration, @@ -685,9 +685,15 @@ export class DataApi { // Get Privilege Purchase Information for Licensee User public getPrivilegePurchaseInformation() { return wait(500).then(() => { - const { items } = privilegePurchaseOptionsResponse; - const privilegePurchaseOptions = items.filter((serverItem) => (serverItem.type === 'jurisdiction')).map((serverPurchaseOption) => (PrivilegePurchaseOptionSerializer.fromServer(serverPurchaseOption))); - const compactCommissionFee = items.filter((serverItem) => (serverItem.type === 'compact')).map((serverFeeObject) => (CompactFeeConfigSerializer.fromServer(serverFeeObject)))[0]; + const { items } = getPrivilegePurchaseOptionsResponse(getCurrentCompact()); + const privilegePurchaseOptions = items + .filter((serverItem) => (serverItem.type === 'jurisdiction')) + .map((serverPurchaseOption) => ( + PrivilegePurchaseOptionSerializer.fromServer(serverPurchaseOption) + )); + const compactCommissionFee = items + .filter((serverItem) => (serverItem.type === 'compact')) + .map((serverFeeObject) => CompactFeeConfigSerializer.fromServer(serverFeeObject))[0]; return { privilegePurchaseOptions, compactCommissionFee }; }); diff --git a/webroot/src/network/mocks/mock.data.ts b/webroot/src/network/mocks/mock.data.ts index e36d2c93a..60bacfb37 100644 --- a/webroot/src/network/mocks/mock.data.ts +++ b/webroot/src/network/mocks/mock.data.ts @@ -429,24 +429,47 @@ export const uploadRequestData = { }, }; +// Privilege fees for compacts in AppGroupModes.PRIVILEGE_PURCHASE. +const mockPrivilegeFeesByCompact: Partial>> = { + [CompactType.ASLP]: [ + { licenseTypeAbbreviation: 'aud', amount: 200, militaryAmount: 90 }, + { licenseTypeAbbreviation: 'slp', amount: 100, militaryAmount: 50 }, + ], + [CompactType.OT]: [ + { licenseTypeAbbreviation: 'ot', amount: 200, militaryAmount: 90 }, + { licenseTypeAbbreviation: 'ota', amount: 100, militaryAmount: 50 }, + ], + [CompactType.COUNSELING]: [ + { licenseTypeAbbreviation: 'lpc', amount: 100, militaryAmount: 50 }, + ], + [CompactType.DIETITIANS]: [ + { licenseTypeAbbreviation: 'diet', amount: 100, militaryAmount: 50 }, + ], +}; + export const createStatePrivilegePurchaseOption = (config: any = {}) => { + const compact = (config?.compact) ? config.compact as CompactType : CompactType.OT; + const compactFees = mockPrivilegeFeesByCompact[compact]; + const otFees = mockPrivilegeFeesByCompact[CompactType.OT] || []; + const feeTemplates = compactFees || otFees; const purchaseOption: any = { type: 'jurisdiction', postalAbbreviation: config?.stateAbbrev, jurisdictionName: config?.stateName, - compact: 'octp', - privilegeFees: [ - { - licenseTypeAbbreviation: 'ot', - amount: 200, - militaryRate: (config?.hasMilitaryDiscount) ? 90 : undefined, - }, - { - licenseTypeAbbreviation: 'ota', - amount: 100, - militaryRate: (config?.hasMilitaryDiscount) ? 50 : undefined, - } - ], + compact, + privilegeFees: feeTemplates.map((fee) => { + const privilegeFee = { + licenseTypeAbbreviation: fee.licenseTypeAbbreviation, + amount: fee.amount, + militaryRate: (config?.hasMilitaryDiscount) ? fee.militaryAmount : undefined, + }; + + return privilegeFee; + }), jurisprudenceRequirements: { required: Boolean(config?.hasJurisprudence), }, @@ -459,195 +482,209 @@ export const createStatePrivilegePurchaseOption = (config: any = {}) => { return purchaseOption; }; -export const privilegePurchaseOptionsResponse = { - items: [ - { - compactAbbr: 'octp', - compactCommissionFee: { - feeType: 'FLAT_RATE', - feeAmount: 3.5 - }, - transactionFeeConfiguration: { - licenseeCharges: { - active: true, - chargeType: 'FLAT_FEE_PER_PRIVILEGE', - chargeAmount: 2 - } - }, - type: 'compact', - isSandbox: true, - paymentProcessorPublicFields: { - apiLoginId: process.env.VUE_APP_MOCK_API_PAYMENT_LOGIN_ID, - publicClientKey: process.env.VUE_APP_MOCK_API_PAYMENT_CLIENT_KEY, +const privilegePurchaseStateConfigs = [ + { + stateAbbrev: 'ak', + stateName: 'alaska', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: true, + }, + { + stateAbbrev: 'al', + stateName: 'alabama', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'ar', + stateName: 'arkansas', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'co', + stateName: 'colorado', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: true, + }, + { + stateAbbrev: 'ct', + stateName: 'connecticut', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'ks', + stateName: 'kansas', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'ky', + stateName: 'kentucky', + hasMilitaryDiscount: true, + hasJurisprudence: true, + hasJurisprudenceLink: true, + }, + { + stateAbbrev: 'ma', + stateName: 'massachusetts', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'md', + stateName: 'maryland', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'me', + stateName: 'maine', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'mt', + stateName: 'montana', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'ne', + stateName: 'nebraska', + hasMilitaryDiscount: true, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'nh', + stateName: 'new hampshire', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'nm', + stateName: 'new mexico', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'nv', + stateName: 'nevada', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'oh', + stateName: 'ohio', + hasMilitaryDiscount: true, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'ok', + stateName: 'oklahoma', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'or', + stateName: 'oregon', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'ri', + stateName: 'rhode island', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'ut', + stateName: 'utah', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'va', + stateName: 'virginia', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'vt', + stateName: 'vermont', + hasMilitaryDiscount: false, + hasJurisprudence: true, + hasJurisprudenceLink: false, + }, + { + stateAbbrev: 'wa', + stateName: 'washington', + hasMilitaryDiscount: false, + hasJurisprudence: false, + hasJurisprudenceLink: false, + }, +]; + +export const getPrivilegePurchaseOptionsResponse = (compactType?: string | null) => { + const requestedCompact = compactType as CompactType; + const hasPrivilegeFees = Boolean(mockPrivilegeFeesByCompact[requestedCompact]); + const compact = (hasPrivilegeFees) ? requestedCompact : CompactType.OT; + const stateOptions = privilegePurchaseStateConfigs.map((stateConfig) => createStatePrivilegePurchaseOption({ + ...stateConfig, + compact, + })); + + return { + items: [ + { + compactAbbr: compact, + compactCommissionFee: { + feeType: 'FLAT_RATE', + feeAmount: 3.5, + }, + transactionFeeConfiguration: { + licenseeCharges: { + active: true, + chargeType: 'FLAT_FEE_PER_PRIVILEGE', + chargeAmount: 2, + }, + }, + type: 'compact', + isSandbox: true, + paymentProcessorPublicFields: { + apiLoginId: process.env.VUE_APP_MOCK_API_PAYMENT_LOGIN_ID, + publicClientKey: process.env.VUE_APP_MOCK_API_PAYMENT_CLIENT_KEY, + }, }, + ...stateOptions, + ], + pagination: { + pageSize: 100, + prevLastKey: null, + lastKey: null, }, - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ak', - stateName: 'alaska', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: true, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'al', - stateName: 'alabama', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ar', - stateName: 'arkansas', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'co', - stateName: 'colorado', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: true, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ct', - stateName: 'connecticut', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ks', - stateName: 'kansas', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ky', - stateName: 'kentucky', - hasMilitaryDiscount: true, - hasJurisprudence: true, - hasJurisprudenceLink: true, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ma', - stateName: 'massachusetts', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'md', - stateName: 'maryland', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'me', - stateName: 'maine', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'mt', - stateName: 'montana', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ne', - stateName: 'nebraska', - hasMilitaryDiscount: true, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'nh', - stateName: 'new hampshire', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'nm', - stateName: 'new mexico', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'nv', - stateName: 'nevada', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'oh', - stateName: 'ohio', - hasMilitaryDiscount: true, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ok', - stateName: 'oklahoma', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'or', - stateName: 'oregon', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ri', - stateName: 'rhode island', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'ut', - stateName: 'utah', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'va', - stateName: 'virginia', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'vt', - stateName: 'vermont', - hasMilitaryDiscount: false, - hasJurisprudence: true, - hasJurisprudenceLink: false, - }), - createStatePrivilegePurchaseOption({ - stateAbbrev: 'wa', - stateName: 'washington', - hasMilitaryDiscount: false, - hasJurisprudence: false, - hasJurisprudenceLink: false, - }), - ], - pagination: { - pageSize: 100, - prevLastKey: null, - lastKey: null - } + }; }; export const attestationResponses = [ diff --git a/webroot/src/store/user/user.mutations.ts b/webroot/src/store/user/user.mutations.ts index d3342d51b..965cac497 100644 --- a/webroot/src/store/user/user.mutations.ts +++ b/webroot/src/store/user/user.mutations.ts @@ -8,6 +8,7 @@ import { Compact } from '@models/Compact/Compact.model'; import { LicenseeUser } from '@/models/LicenseeUser/LicenseeUser.model'; import { StaffUser } from '@/models/StaffUser/StaffUser.model'; import { PurchaseFlowStep } from '@/models/PurchaseFlowStep/PurchaseFlowStep.model'; +import { PurchaseFlowState } from '@/models/PurchaseFlowState/PurchaseFlowState.model'; import { AuthTypes } from '@utils/auth'; import { getImpliedCompactForHost } from './user.state'; @@ -171,6 +172,7 @@ export default { state.isAutoLogoutWarning = false; state.userType = null; state.currentCompact = getImpliedCompactForHost(); + state.purchase = new PurchaseFlowState(); state.error = null; }, [MutationTypes.UPDATE_ACCOUNT_REQUEST]: (state: any) => { diff --git a/webroot/src/store/user/user.spec.ts b/webroot/src/store/user/user.spec.ts index ec078232d..f94a88d8d 100644 --- a/webroot/src/store/user/user.spec.ts +++ b/webroot/src/store/user/user.spec.ts @@ -219,6 +219,9 @@ describe('Use Store Mutations', () => { const state = { isLoggedInAsStaff: true, isLoggedInAsLicensee: true, + purchase: new PurchaseFlowState({ + steps: [new PurchaseFlowStep({ stepNum: 0 })], + }), }; mutations[MutationTypes.STORE_RESET_USER](state); @@ -227,6 +230,8 @@ describe('Use Store Mutations', () => { expect(state.isLoadingAccount).to.equal(false); expect(state.isLoggedInAsStaff).to.equal(false); expect(state.isLoggedInAsLicensee).to.equal(false); + expect(state.purchase).to.be.an.instanceof(PurchaseFlowState); + expect(state.purchase.steps).to.deep.equal([]); expect(state.error).to.equal(null); }); it('should successfully update account request', () => { From 14303f30ab956b85614c979b41d2808a117f111b Mon Sep 17 00:00:00 2001 From: John Sandoval Date: Fri, 30 Oct 2026 10:33:50 -0600 Subject: [PATCH 5/6] PR review feedback --- .../PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts b/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts index 7d64116e9..0e8f99782 100644 --- a/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts +++ b/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts @@ -68,6 +68,10 @@ export default class PrivilegePurchaseSelect extends mixins(MixinForm) { 'jurisprudence-confirmation', 'scope-of-practice-attestation' ], + diet: [ + 'jurisprudence-confirmation', + 'scope-of-practice-attestation' + ], } attestationRecords: Array = []; // eslint-disable-line lines-between-class-members areFormInputsSet = false; From 2f459ef5bd5a9b481568ca8596bcaaa00839678d Mon Sep 17 00:00:00 2001 From: Reuben Molinares Date: Fri, 30 Oct 2026 14:18:57 -0400 Subject: [PATCH 6/6] Explanation conditional key comment (#2052) --- .../PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts b/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts index 0e8f99782..b46c02c8c 100644 --- a/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts +++ b/webroot/src/components/PrivilegePurchaseSelect/PrivilegePurchaseSelect.ts @@ -237,6 +237,7 @@ export default class PrivilegePurchaseSelect extends mixins(MixinForm) { get jurisprudenceExplanationTextKey(): string { let key = 'licensing.jurisprudenceExplanationText'; + // Dietitians still uses the older exam wording while the other compacts use the updated sentence if (this.currentCompactType === CompactType.DIETITIANS) { key = 'licensing.jurisprudenceExamExplanationText'; }