From 2bdd6d3919ada9717424303210e5634f0867600d Mon Sep 17 00:00:00 2001 From: John Sandoval Date: Thu, 2 Jul 2026 14:49:55 -0600 Subject: [PATCH 1/4] WIP: multistate license scopes & discipline updates --- webroot/src/components/Icons/Globe/Globe.less | 6 ++ .../src/components/Icons/Globe/Globe.spec.ts | 19 +++++ webroot/src/components/Icons/Globe/Globe.ts | 18 +++++ webroot/src/components/Icons/Globe/Globe.vue | 31 +++++++ .../src/components/Icons/MapPin/MapPin.less | 6 ++ .../components/Icons/MapPin/MapPin.spec.ts | 19 +++++ webroot/src/components/Icons/MapPin/MapPin.ts | 18 +++++ .../src/components/Icons/MapPin/MapPin.vue | 31 +++++++ .../components/LicenseCard/LicenseCard.less | 47 ++++++++++- .../src/components/LicenseCard/LicenseCard.ts | 81 ++++++++++++++++--- .../components/LicenseCard/LicenseCard.vue | 15 +++- .../PrivilegeCard/PrivilegeCard.less | 14 +++- .../components/PrivilegeCard/PrivilegeCard.ts | 42 +++++++--- .../PrivilegeCard/PrivilegeCard.vue | 5 +- webroot/src/locales/en.json | 26 +++++- webroot/src/locales/es.json | 22 ++++- .../src/models/License/License.model.spec.ts | 16 ++++ webroot/src/models/License/License.model.ts | 28 ++++++- webroot/src/network/data.api.ts | 56 ++++++++----- webroot/src/network/licenseApi/data.api.ts | 40 ++++++--- webroot/src/network/mocks/mock.data.ts | 10 +++ webroot/src/store/users/users.actions.ts | 18 +++-- webroot/src/styles.common/_colors.less | 1 + 23 files changed, 500 insertions(+), 69 deletions(-) create mode 100644 webroot/src/components/Icons/Globe/Globe.less create mode 100644 webroot/src/components/Icons/Globe/Globe.spec.ts create mode 100644 webroot/src/components/Icons/Globe/Globe.ts create mode 100644 webroot/src/components/Icons/Globe/Globe.vue create mode 100644 webroot/src/components/Icons/MapPin/MapPin.less create mode 100644 webroot/src/components/Icons/MapPin/MapPin.spec.ts create mode 100644 webroot/src/components/Icons/MapPin/MapPin.ts create mode 100644 webroot/src/components/Icons/MapPin/MapPin.vue diff --git a/webroot/src/components/Icons/Globe/Globe.less b/webroot/src/components/Icons/Globe/Globe.less new file mode 100644 index 0000000000..d8f105ee62 --- /dev/null +++ b/webroot/src/components/Icons/Globe/Globe.less @@ -0,0 +1,6 @@ +// +// Globe.less +// CompactConnect +// +// Created by InspiringApps on 7/2/2026. +// diff --git a/webroot/src/components/Icons/Globe/Globe.spec.ts b/webroot/src/components/Icons/Globe/Globe.spec.ts new file mode 100644 index 0000000000..57289a8ba3 --- /dev/null +++ b/webroot/src/components/Icons/Globe/Globe.spec.ts @@ -0,0 +1,19 @@ +// +// Globe.spec.ts +// CompactConnect +// +// Created by InspiringApps on 7/2/2026. +// + +import { expect } from 'chai'; +import { mountShallow } from '@tests/helpers/setup'; +import Globe from '@components/Icons/Globe/Globe.vue'; + +describe('Globe component', async () => { + it('should mount the component', async () => { + const wrapper = await mountShallow(Globe); + + expect(wrapper.exists()).to.equal(true); + expect(wrapper.findComponent(Globe).exists()).to.equal(true); + }); +}); diff --git a/webroot/src/components/Icons/Globe/Globe.ts b/webroot/src/components/Icons/Globe/Globe.ts new file mode 100644 index 0000000000..7339749d2b --- /dev/null +++ b/webroot/src/components/Icons/Globe/Globe.ts @@ -0,0 +1,18 @@ +// +// Globe.ts +// CompactConnect +// +// Created by InspiringApps on 7/2/2026. +// + +import { Component, Vue, toNative } from 'vue-facing-decorator'; + +@Component({ + name: 'Globe', +}) +class Globe extends Vue { +} + +export default toNative(Globe); + +// export default Globe; diff --git a/webroot/src/components/Icons/Globe/Globe.vue b/webroot/src/components/Icons/Globe/Globe.vue new file mode 100644 index 0000000000..a754e3430f --- /dev/null +++ b/webroot/src/components/Icons/Globe/Globe.vue @@ -0,0 +1,31 @@ + + + + + + diff --git a/webroot/src/components/Icons/MapPin/MapPin.less b/webroot/src/components/Icons/MapPin/MapPin.less new file mode 100644 index 0000000000..ff38ecf51f --- /dev/null +++ b/webroot/src/components/Icons/MapPin/MapPin.less @@ -0,0 +1,6 @@ +// +// MapPin.less +// CompactConnect +// +// Created by InspiringApps on 7/2/2026. +// diff --git a/webroot/src/components/Icons/MapPin/MapPin.spec.ts b/webroot/src/components/Icons/MapPin/MapPin.spec.ts new file mode 100644 index 0000000000..c93709fb49 --- /dev/null +++ b/webroot/src/components/Icons/MapPin/MapPin.spec.ts @@ -0,0 +1,19 @@ +// +// MapPin.spec.ts +// CompactConnect +// +// Created by InspiringApps on 7/2/2026. +// + +import { expect } from 'chai'; +import { mountShallow } from '@tests/helpers/setup'; +import MapPin from '@components/Icons/MapPin/MapPin.vue'; + +describe('MapPin component', async () => { + it('should mount the component', async () => { + const wrapper = await mountShallow(MapPin); + + expect(wrapper.exists()).to.equal(true); + expect(wrapper.findComponent(MapPin).exists()).to.equal(true); + }); +}); diff --git a/webroot/src/components/Icons/MapPin/MapPin.ts b/webroot/src/components/Icons/MapPin/MapPin.ts new file mode 100644 index 0000000000..36d1694a7e --- /dev/null +++ b/webroot/src/components/Icons/MapPin/MapPin.ts @@ -0,0 +1,18 @@ +// +// MapPin.ts +// CompactConnect +// +// Created by InspiringApps on 7/2/2026. +// + +import { Component, Vue, toNative } from 'vue-facing-decorator'; + +@Component({ + name: 'MapPin', +}) +class MapPin extends Vue { +} + +export default toNative(MapPin); + +// export default MapPin; diff --git a/webroot/src/components/Icons/MapPin/MapPin.vue b/webroot/src/components/Icons/MapPin/MapPin.vue new file mode 100644 index 0000000000..6f22566bfc --- /dev/null +++ b/webroot/src/components/Icons/MapPin/MapPin.vue @@ -0,0 +1,31 @@ + + + + + + diff --git a/webroot/src/components/LicenseCard/LicenseCard.less b/webroot/src/components/LicenseCard/LicenseCard.less index dc84a28fa1..175c35a750 100644 --- a/webroot/src/components/LicenseCard/LicenseCard.less +++ b/webroot/src/components/LicenseCard/LicenseCard.less @@ -5,7 +5,7 @@ // Created by InspiringApps on 10/8/2024. // .license-card-container { - width: 30rem; + width: 36rem; padding: 2rem 2rem 1.6rem 2rem; border-radius: 2rem; color: @white; @@ -175,6 +175,51 @@ } } + .license-scope-container { + display: flex; + + .license-scope { + display: flex; + align-items: center; + padding: 0.3rem 0.8rem 0.3rem 0.6rem; + border-radius: @borderRadiusPillShape; + font-weight: @fontWeightBold; + font-size: @fontSizeSmaller; + + &.single-state { + color: @white; + background-color: @midBlue; + } + + &.multi-state { + color: @fontColor; + background-color: @altBlue1; + } + } + + .scope-icon { + height: 1.2rem; + margin-right: 0.2rem; + fill: none; + stroke: @white; + + &.fill-type { + &:deep(.custom-fill) { + fill: @white; + } + } + + &.stroke-fill-type, + &.stroke-type { + stroke: @white; + } + + &.globe-icon { + stroke: @fontColor; + } + } + } + .license-info-grid { display: grid; grid-template-columns: 1fr 1fr; diff --git a/webroot/src/components/LicenseCard/LicenseCard.ts b/webroot/src/components/LicenseCard/LicenseCard.ts index 8f304659c2..8f9d6e506e 100644 --- a/webroot/src/components/LicenseCard/LicenseCard.ts +++ b/webroot/src/components/LicenseCard/LicenseCard.ts @@ -26,12 +26,14 @@ import InputButton from '@components/Forms/InputButton/InputButton.vue'; import InputSubmit from '@components/Forms/InputSubmit/InputSubmit.vue'; import LicenseIcon from '@components/Icons/LicenseIcon/LicenseIcon.vue'; import LicenseHomeIcon from '@components/Icons/LicenseHome/LicenseHome.vue'; +import MapPinIcon from '@components/Icons/MapPin/MapPin.vue'; +import GlobeIcon from '@components/Icons/Globe/Globe.vue'; import CheckCircleIcon from '@components/Icons/CheckCircle/CheckCircle.vue'; import CloseXIcon from '@components/Icons/CloseX/CloseX.vue'; import MockPopulate from '@components/Forms/MockPopulate/MockPopulate.vue'; import Modal from '@components/Modal/Modal.vue'; import { dateDisplay } from '@models/_formatters/date'; -import { License, LicenseStatus } from '@/models/License/License.model'; +import { License, LicenseStatus, LicenseScope } from '@/models/License/License.model'; import { Licensee } from '@/models/Licensee/Licensee.model'; import { Compact } from '@models/Compact/Compact.model'; import { State } from '@/models/State/State.model'; @@ -55,6 +57,8 @@ import moment from 'moment'; Modal, LicenseIcon, LicenseHomeIcon, + MapPinIcon, + GlobeIcon, CheckCircleIcon, CloseXIcon, } @@ -116,6 +120,10 @@ class LicenseCard extends mixins(MixinForm) { return this.$store.getters.isAppModeSocialWork; } + get isAppGroupModeMultiState(): boolean { + return this.$store.getters.isAppGroupModeMultiState; + } + get currentUser(): StaffUser { return this.userStore.model; } @@ -169,10 +177,30 @@ class LicenseCard extends mixins(MixinForm) { return this.license?.licenseNumber || ''; } + get licenseTypeDisplay(): string { + return this.license?.licenseTypeDisplay() || ''; + } + get licenseTypeAbbrev(): string { return this.license?.licenseTypeAbbreviation() || ''; } + get licenseScope(): string { + return this.license?.licenseScope || ''; + } + + get licenseScopeDisplay(): string { + return this.license?.licenseScopeDisplay() || ''; + } + + get isLicenseScopeSingleState(): boolean { + return this.licenseScope === LicenseScope.SINGLE_STATE; + } + + get isLicenseScopeMultiState(): boolean { + return this.licenseScope === LicenseScope.MULTI_STATE; + } + get isActive(): boolean { return this.license?.status === LicenseStatus.ACTIVE; } @@ -281,24 +309,41 @@ class LicenseCard extends mixins(MixinForm) { get npdbCategoryOptions(): Array<{ value: string, name: string | ComputedRef }> { const { isAppModeJcc, isAppModeCosmetology, isAppModeSocialWork } = this; + const includeList: Array = []; + let isMultiSelect = true; let options = this.$tm('licensing.npdbTypes').map((npdbType) => ({ value: npdbType.key, name: npdbType.name, })); + // Define the included keys per compact if (isAppModeJcc) { - const excludeList = ['Consumer Harm']; + includeList.push('Non-compliance With Requirements'); + includeList.push('Criminal Conviction or Adjudication'); + includeList.push('Confidentiality, Consent or Disclosure Violations'); + includeList.push('Misconduct or Abuse'); + includeList.push('Fraud, Deception, or Misrepresentation'); + includeList.push('Unsafe Practice or Substandard Care'); + includeList.push('Improper Supervision or Allowing Unlicensed Practice'); + includeList.push('Other'); + } else if (isAppModeCosmetology) { + isMultiSelect = false; + includeList.push('fraud'); + includeList.push('consumer harm'); + includeList.push('other'); + } else if (isAppModeSocialWork) { + isMultiSelect = false; + includeList.push('fraud'); + includeList.push('consumer harm'); + includeList.push('other'); + } - options = options.filter((option) => !excludeList.includes(option.value)); - } else if (isAppModeCosmetology || isAppModeSocialWork) { - const includeList = ['Fraud, Deception, or Misrepresentation', 'Consumer Harm', 'Other']; + // Filter the compact-specific options + options = options.filter((option) => includeList.includes(option.value) || option.value === ''); - options = options.filter((option) => includeList.includes(option.value)); - - options.unshift({ - value: '', - name: computed(() => this.$t('common.selectOption')), - }); + // For a single-select, include the blank option + if (!isMultiSelect) { + options.unshift({ value: '', name: computed(() => this.$t('common.selectOption')) }); } return options; @@ -534,6 +579,7 @@ class LicenseCard extends mixins(MixinForm) { licenseeId, stateAbbrev, licenseTypeAbbrev, + licenseScope, formData } = this; @@ -547,12 +593,14 @@ class LicenseCard extends mixins(MixinForm) { licenseState: stateAbbrev, licenseType: licenseTypeAbbrev.toLowerCase(), investigationId, + licenseScope, encumbrance: { encumbranceType: formData.encumberModalDisciplineAction.value, npdbCategories: (Array.isArray(formData.encumberModalNpdbCategories.value)) ? formData.encumberModalNpdbCategories.value : [formData.encumberModalNpdbCategories.value], startDate: formData.encumberModalStartDate.value, + licenseScope, }, }).catch((err) => { this.modalErrorMessage = err?.message || this.$t('common.error'); @@ -570,6 +618,7 @@ class LicenseCard extends mixins(MixinForm) { ? formData.encumberModalNpdbCategories.value : [formData.encumberModalNpdbCategories.value], startDate: formData.encumberModalStartDate.value, + licenseScope, }).catch((err) => { this.modalErrorMessage = err?.message || this.$t('common.error'); this.isFormError = true; @@ -712,7 +761,8 @@ class LicenseCard extends mixins(MixinForm) { currentCompactType: compactType, licenseeId, stateAbbrev, - licenseTypeAbbrev + licenseTypeAbbrev, + licenseScope } = this; const errorMessages: Array = []; @@ -726,6 +776,7 @@ class LicenseCard extends mixins(MixinForm) { licenseType: licenseTypeAbbrev.toLowerCase(), encumbranceId: adverseActionId, endDate: this.formData[`adverse-action-end-date-${adverseActionId}`].value, + licenseScope, }).catch((err) => { errorMessages.push(err?.message || this.$t('common.error')); }); @@ -799,7 +850,8 @@ class LicenseCard extends mixins(MixinForm) { currentCompactType: compactType, licenseeId, stateAbbrev, - licenseTypeAbbrev + licenseTypeAbbrev, + licenseScope } = this; await this.$store.dispatch(`users/createInvestigationLicenseRequest`, { @@ -807,6 +859,7 @@ class LicenseCard extends mixins(MixinForm) { licenseeId, licenseState: stateAbbrev, licenseType: licenseTypeAbbrev.toLowerCase(), + licenseScope, }).catch((err) => { this.modalErrorMessage = err?.message || this.$t('common.error'); this.isFormError = true; @@ -955,6 +1008,7 @@ class LicenseCard extends mixins(MixinForm) { licenseeId, stateAbbrev, licenseTypeAbbrev, + licenseScope } = this; const investigationId = this.selectedInvestigation?.id; @@ -964,6 +1018,7 @@ class LicenseCard extends mixins(MixinForm) { licenseState: stateAbbrev, licenseType: licenseTypeAbbrev.toLowerCase(), investigationId, + licenseScope }).catch((err) => { this.modalErrorMessage = err?.message || this.$t('common.error'); this.isFormError = true; diff --git a/webroot/src/components/LicenseCard/LicenseCard.vue b/webroot/src/components/LicenseCard/LicenseCard.vue index 71688649e0..a69af609f0 100644 --- a/webroot/src/components/LicenseCard/LicenseCard.vue +++ b/webroot/src/components/LicenseCard/LicenseCard.vue @@ -79,7 +79,10 @@
-
{{licenseTypeAbbrev}}
+
+ + +
+
+
+ + + {{licenseScopeDisplay }} +
+
{{expiresTitle}}
diff --git a/webroot/src/components/PrivilegeCard/PrivilegeCard.less b/webroot/src/components/PrivilegeCard/PrivilegeCard.less index 1307a4b4ab..7536799dd2 100644 --- a/webroot/src/components/PrivilegeCard/PrivilegeCard.less +++ b/webroot/src/components/PrivilegeCard/PrivilegeCard.less @@ -17,7 +17,7 @@ display: flex; flex-direction: row; align-items: flex-start; - padding: 1rem 2rem 1rem 2rem; + padding: 1rem 2rem 0.6rem 2rem; border-top-left-radius: 2rem; border-top-right-radius: 2rem; color: @white; @@ -130,6 +130,18 @@ } } + .license-type { + display: flex; + width: 100%; + padding: 0 2rem 1rem 2rem; + color: @white; + background-color: darken(@darkGrey, 5%); + + &.active { + background-color: @primaryColor; + } + } + .privilege-info-grid { display: grid; grid-template-columns: 1fr 1fr; diff --git a/webroot/src/components/PrivilegeCard/PrivilegeCard.ts b/webroot/src/components/PrivilegeCard/PrivilegeCard.ts index dbdb71276b..3cae70e880 100644 --- a/webroot/src/components/PrivilegeCard/PrivilegeCard.ts +++ b/webroot/src/components/PrivilegeCard/PrivilegeCard.ts @@ -152,6 +152,10 @@ class PrivilegeCard extends mixins(MixinForm) { return this.licensee?.nameDisplay() || ''; } + get privilegeTypeDisplay(): string { + return this.privilege?.licenseTypeDisplay() || ''; + } + get privilegeTypeAbbrev(): string { return this.privilege?.licenseTypeAbbreviation() || ''; } @@ -256,24 +260,42 @@ class PrivilegeCard extends mixins(MixinForm) { get npdbCategoryOptions(): Array<{ value: string, name: string | ComputedRef }> { const { isAppModeJcc, isAppModeCosmetology, isAppModeSocialWork } = this; + const includeList: Array = []; + let isMultiSelect = true; let options = this.$tm('licensing.npdbTypes').map((npdbType) => ({ value: npdbType.key, name: npdbType.name, })); + // Define the included keys per compact if (isAppModeJcc) { - const excludeList = ['Consumer Harm']; - - options = options.filter((option) => !excludeList.includes(option.value)); - } else if (isAppModeCosmetology || isAppModeSocialWork) { - const includeList = ['Fraud, Deception, or Misrepresentation', 'Consumer Harm', 'Other']; + includeList.push('Non-compliance With Requirements'); + includeList.push('Criminal Conviction or Adjudication'); + includeList.push('Confidentiality, Consent or Disclosure Violations'); + includeList.push('Misconduct or Abuse'); + includeList.push('Fraud, Deception, or Misrepresentation'); + includeList.push('Unsafe Practice or Substandard Care'); + includeList.push('Improper Supervision or Allowing Unlicensed Practice'); + includeList.push('Other'); + } else if (isAppModeCosmetology) { + isMultiSelect = false; + includeList.push('fraud'); + includeList.push('consumer harm'); + includeList.push('other'); + } else if (isAppModeSocialWork) { + isMultiSelect = false; + includeList.push('fraud'); + includeList.push('consumer harm'); + includeList.push('other'); + } - options = options.filter((option) => includeList.includes(option.value)); + // Filter the compact-specific options + options = options.filter((option) => includeList.includes(option.value) || option.value === ''); - options.unshift({ - value: '', - name: computed(() => this.$t('common.selectOption')), - }); + // For a single-select, include the blank option + if (!isMultiSelect) { + console.log('???'); + options.unshift({ value: '', name: computed(() => this.$t('common.selectOption')) }); } return options; diff --git a/webroot/src/components/PrivilegeCard/PrivilegeCard.vue b/webroot/src/components/PrivilegeCard/PrivilegeCard.vue index 1004ec4770..0e96db9736 100644 --- a/webroot/src/components/PrivilegeCard/PrivilegeCard.vue +++ b/webroot/src/components/PrivilegeCard/PrivilegeCard.vue @@ -13,7 +13,6 @@ }">
{{stateContent}}
-
{{privilegeTypeAbbrev}}
{{statusDisplay}}
@@ -88,6 +87,10 @@
+
+ + +
{{ $t('licensing.activeFrom') }}
diff --git a/webroot/src/locales/en.json b/webroot/src/locales/en.json index 870437880b..578f92ebed 100644 --- a/webroot/src/locales/en.json +++ b/webroot/src/locales/en.json @@ -867,12 +867,24 @@ "abbrev": "lmsw" }, { - "name": "Licensed Bachelor Social Worker", - "key": "licensed bachelor social worker", + "name": "Licensed Bachelors Social Worker", + "key": "licensed bachelors social worker", "compactKey": "socw", "abbrev": "lbsw" } ], + "licenseScopes": [ + { + "name": "Single state", + "key": "single-state", + "compactKey": "socw" + }, + { + "name": "Multi state", + "key": "multi-state", + "compactKey": "socw" + } + ], "disciplineTypes": [ { "name": "Fine", @@ -968,13 +980,21 @@ "name": "Improper Supervision or Allowing Unlicensed Practice", "key": "Improper Supervision or Allowing Unlicensed Practice" }, + { + "name": "Fraud", + "key": "fraud" + }, { "name": "Consumer harm", - "key": "Consumer Harm" + "key": "consumer harm" }, { "name": "Other", "key": "Other" + }, + { + "name": "Other", + "key": "other" } ], "privilegePurchaseTitle": "Privilege purchase", diff --git a/webroot/src/locales/es.json b/webroot/src/locales/es.json index 58797f18ff..98009492ed 100644 --- a/webroot/src/locales/es.json +++ b/webroot/src/locales/es.json @@ -852,11 +852,23 @@ }, { "name": "Trabajador social titulado con licencia", - "key": "licensed bachelor social worker", + "key": "licensed bachelors social worker", "compactKey": "socw", "abbrev": "lbsw" } ], + "licenseScopes": [ + { + "name": "Estado único", + "key": "single-state", + "compactKey": "socw" + }, + { + "name": "Estado múltiple", + "key": "multi-state", + "compactKey": "socw" + } + ], "disciplineTypes": [ { "name": "Multa", @@ -952,6 +964,10 @@ "name": "Supervisión inadecuada o autorización de prácticas sin licencia", "key": "Improper Supervision or Allowing Unlicensed Practice" }, + { + "name": "Fraude", + "key": "Fraud, Deception, or Misrepresentation" + }, { "name": "Daños al consumidor", "key": "Consumer Harm" @@ -959,6 +975,10 @@ { "name": "Otro", "key": "Other" + }, + { + "name": "Otro", + "key": "other" } ], "privilegePurchaseTitle": "Compra privada", diff --git a/webroot/src/models/License/License.model.spec.ts b/webroot/src/models/License/License.model.spec.ts index 1656a7fedf..8f73554ab9 100644 --- a/webroot/src/models/License/License.model.spec.ts +++ b/webroot/src/models/License/License.model.spec.ts @@ -10,6 +10,7 @@ import { serverDateFormat, displayDateFormat, serverDatetimeFormat } from '@/app import { License, LicenseType, + LicenseScope, LicenseStatus, EligibilityStatus, LicenseSerializer @@ -61,6 +62,7 @@ describe('License model', () => { expect(license.mailingAddress).to.be.an.instanceof(Address); expect(license.email).to.equal(null); expect(license.licenseType).to.equal(null); + expect(license.licenseScope).to.equal(null); expect(license.history).to.matchPattern([]); expect(license.status).to.equal(LicenseStatus.INACTIVE); expect(license.statusDescription).to.equal(null); @@ -76,7 +78,9 @@ describe('License model', () => { expect(license.isExpired()).to.equal(false); expect(license.isAdminDeactivated()).to.equal(false); expect(license.isCompactEligible()).to.equal(false); + expect(license.licenseTypeDisplay()).to.equal(''); expect(license.licenseTypeAbbreviation()).to.equal(''); + expect(license.licenseScopeDisplay()).to.equal(''); expect(license.displayName()).to.equal('Unknown'); expect(license.isEncumbered()).to.equal(false); expect(license.isLatestLiftedEncumbranceWithinWaitPeriod()).to.equal(false); @@ -99,6 +103,7 @@ describe('License model', () => { email: 'test@example.com', npi: 'test-npi', licenseType: LicenseType.AUDIOLOGIST, + licenseScope: LicenseScope.MULTI_STATE, history: [new LicenseHistoryItem()], status: LicenseStatus.ACTIVE, statusDescription: 'test-status-desc', @@ -125,6 +130,7 @@ describe('License model', () => { expect(license.licenseNumber).to.equal(data.licenseNumber); expect(license.privilegeId).to.equal(data.privilegeId); expect(license.licenseType).to.equal(data.licenseType); + expect(license.licenseScope).to.equal(data.licenseScope); expect(license.history[0]).to.be.an.instanceof(LicenseHistoryItem); expect(license.status).to.equal(data.status); expect(license.statusDescription).to.equal(data.statusDescription); @@ -140,7 +146,9 @@ describe('License model', () => { expect(license.isExpired()).to.equal(false); expect(license.isAdminDeactivated()).to.equal(false); expect(license.isCompactEligible()).to.equal(true); + expect(license.licenseTypeDisplay()).to.equal('Audiologist'); expect(license.licenseTypeAbbreviation()).to.equal('AUD'); + expect(license.licenseScopeDisplay()).to.equal('Multi state'); expect(license.displayName()).to.equal('Unknown - audiologist'); expect(license.displayName(', ', true)).to.equal('Unknown, AUD'); expect(license.isEncumbered()).to.equal(false); @@ -180,6 +188,7 @@ describe('License model', () => { homeAddressPostalCode: 'test-zip', emailAddress: 'test@example.com', licenseType: LicenseType.AUDIOLOGIST, + licenseScope: LicenseScope.SINGLE_STATE, history: [], licenseStatus: LicenseStatus.ACTIVE, licenseStatusName: 'test-status-desc', @@ -220,6 +229,7 @@ describe('License model', () => { expect(license.expireDate).to.equal(data.dateOfExpiration); expect(license.activeFromDate).to.equal(data.activeSince); expect(license.licenseType).to.equal(data.licenseType); + expect(license.licenseScope).to.equal(data.licenseScope); expect(license.status).to.equal(data.licenseStatus); expect(license.statusDescription).to.equal(data.licenseStatusName); expect(license.eligibility).to.equal(data.compactEligibility); @@ -243,7 +253,9 @@ describe('License model', () => { expect(license.isCompactEligible()).to.equal(true); expect(license.displayName()).to.equal('Alabama - audiologist'); expect(license.displayName(', ', true)).to.equal('Alabama, AUD'); + expect(license.licenseTypeDisplay()).to.equal('Audiologist'); expect(license.licenseTypeAbbreviation()).to.equal('AUD'); + expect(license.licenseScopeDisplay()).to.equal('Single state'); expect(license.isEncumbered()).to.equal(true); expect(license.isLatestLiftedEncumbranceWithinWaitPeriod()).to.equal(false); expect(license.isUnderInvestigation()).to.equal(true); @@ -257,6 +269,7 @@ describe('License model', () => { jurisdiction: 'ne', licenseJurisdiction: 'ky', licenseType: 'occupational therapy assistant', + licenseScope: 'multi-state', dateOfIssuance: '2022-03-19T21:51:26+00:00', dateOfRenewal: '2025-03-26T16:19:09+00:00', dateOfExpiration: '2025-02-12', @@ -579,6 +592,7 @@ describe('License model', () => { expect(license.expireDate).to.equal(data.dateOfExpiration); expect(license.activeFromDate).to.equal(data.activeSince); expect(license.licenseType).to.equal(data.licenseType); + expect(license.licenseScope).to.equal(data.licenseScope); expect(license.privilegeId).to.equal(data.privilegeId); expect(license.status).to.equal(data.status); expect(license.statusDescription).to.equal(null); @@ -607,7 +621,9 @@ describe('License model', () => { expect(license.isCompactEligible()).to.equal(false); expect(license.displayName()).to.equal('Nebraska - occupational therapy assistant'); expect(license.displayName(', ', true)).to.equal('Nebraska, OTA'); + expect(license.licenseTypeDisplay()).to.equal('Occupational Therapy Assistant'); expect(license.licenseTypeAbbreviation()).to.equal('OTA'); + expect(license.licenseScopeDisplay()).to.equal('Multi state'); expect(license.history.length).to.equal(0); expect(license.isEncumbered()).to.equal(false); expect(license.isLatestLiftedEncumbranceWithinWaitPeriod()).to.equal(true); diff --git a/webroot/src/models/License/License.model.ts b/webroot/src/models/License/License.model.ts index fa757fbacd..0a75281a95 100644 --- a/webroot/src/models/License/License.model.ts +++ b/webroot/src/models/License/License.model.ts @@ -20,7 +20,7 @@ import { StatsigClient } from '@statsig/js-client'; // ======================================================== // = Interface = // ======================================================== -export enum LicenseType { // Temp server definition until server returns via endpoint +export enum LicenseType { AUDIOLOGIST = 'audiologist', SPEECH_LANGUAGE_PATHOLOGIST = 'speech-language pathologist', SPEECH_AND_LANGUAGE_PATHOLOGIST = 'speech and language pathologist', @@ -34,7 +34,12 @@ export enum LicenseType { // Temp server definition until server returns via end ESTHETICIAN = 'esthetician', } -export enum LicenseStatus { // Temp server definition until server returns via endpoint +export enum LicenseScope { + SINGLE_STATE = 'single-state', + MULTI_STATE = 'multi-state', +} + +export enum LicenseStatus { ACTIVE = 'active', INACTIVE = 'inactive', } @@ -62,6 +67,7 @@ export interface InterfaceLicense { licenseNumber?: string | null; privilegeId?: string | null; licenseType?: LicenseType | null, + licenseScope?: LicenseScope | null, history?: Array, status?: LicenseStatus, statusDescription?: string | null, @@ -92,6 +98,7 @@ export class License implements InterfaceLicense { public privilegeId? = null; public expireDate? = null; public licenseType? = null; + public licenseScope? = null; public history? = []; public status? = LicenseStatus.INACTIVE; public statusDescription? = null; @@ -148,6 +155,14 @@ export class License implements InterfaceLicense { return this.eligibility === EligibilityStatus.ELIGIBLE; } + public licenseTypeDisplay(): string { + const licenseTypes = this.$tm('licensing.licenseTypes') || []; + const licenseType = licenseTypes.find((translate) => translate.key === this.licenseType); + const typeDisplay = licenseType?.name || ''; + + return typeDisplay; + } + public licenseTypeAbbreviation(): string { const licenseTypes = this.$tm('licensing.licenseTypes') || []; const licenseType = licenseTypes.find((translate) => translate.key === this.licenseType); @@ -157,6 +172,14 @@ export class License implements InterfaceLicense { return upperCaseAbbrev; } + public licenseScopeDisplay(): string { + const licenseScopes = this.$tm('licensing.licenseScopes') || []; + const licenseScope = licenseScopes.find((translate) => translate.key === this.licenseScope); + const scopeDisplay = licenseScope?.name || ''; + + return scopeDisplay; + } + public displayName(delimiter = ' - ', displayAbbrev = false): string { const stateName = this.issueState?.name() || ''; const licenseTypeToShow = (displayAbbrev) ? this.licenseTypeAbbreviation() : this.licenseType; @@ -223,6 +246,7 @@ export class LicenseSerializer { renewalDate: json.dateOfRenewal, expireDate: json.dateOfExpiration, licenseType: json.licenseType, + licenseScope: json.licenseScope, status: json.licenseStatus || json.status, statusDescription: json.licenseStatusName, eligibility: (json.type === 'license' || json.type === 'license-home') diff --git a/webroot/src/network/data.api.ts b/webroot/src/network/data.api.ts index 1adcd6137f..fedbddc4bf 100644 --- a/webroot/src/network/data.api.ts +++ b/webroot/src/network/data.api.ts @@ -181,6 +181,7 @@ export class DataApi { * @param {string} npdbCategory The NPDB category name. * @param {Array} npdbCategories The NPDB category list. * @param {string} startDate The encumber start date. + * @param {string} [licenseScope] The license scope. * @return {Promise} The server response. */ public encumberLicense( @@ -191,7 +192,8 @@ export class DataApi { encumbranceType, npdbCategory, npdbCategories, - startDate + startDate, + licenseScope ) { return licenseDataApi.encumberLicense( compact, @@ -201,50 +203,56 @@ export class DataApi { encumbranceType, npdbCategory, npdbCategories, - startDate + startDate, + licenseScope ); } /** * PATCH Un-encumber License for a licensee. - * @param {string} compact The compact string ID (aslp, octp, coun). - * @param {string} licenseeId The Licensee ID. - * @param {string} licenseState The 2-character state abbreviation for the License. - * @param {string} licenseType The license type. - * @param {string} encumbranceId The Encumbrance ID. - * @param {string} endDate The encumber end date. - * @return {Promise} The server response. + * @param {string} compact The compact string ID (aslp, octp, coun). + * @param {string} licenseeId The Licensee ID. + * @param {string} licenseState The 2-character state abbreviation for the License. + * @param {string} licenseType The license type. + * @param {string} encumbranceId The Encumbrance ID. + * @param {string} endDate The encumber end date. + * @param {string} [licenseScope] The license scope. + * @return {Promise} The server response. */ - public unencumberLicense(compact, licenseeId, licenseState, licenseType, encumbranceId, endDate) { + public unencumberLicense(compact, licenseeId, licenseState, licenseType, encumbranceId, endDate, licenseScope) { return licenseDataApi.unencumberLicense( compact, licenseeId, licenseState, licenseType, encumbranceId, - endDate + endDate, + licenseScope ); } /** * POST Create License Investigation for a licensee. - * @param {string} compact The compact string ID (aslp, octp, coun). - * @param {string} licenseeId The Licensee ID. - * @param {string} licenseState The 2-character state abbreviation for the License. - * @param {string} licenseType The license type. - * @return {Promise} The server response. + * @param {string} compact The compact string ID (aslp, octp, coun). + * @param {string} licenseeId The Licensee ID. + * @param {string} licenseState The 2-character state abbreviation for the License. + * @param {string} licenseType The license type. + * @param {string} [licenseScope] The license scope. + * @return {Promise} The server response. */ public createLicenseInvestigation( compact, licenseeId, licenseState, - licenseType + licenseType, + licenseScope ) { return licenseDataApi.createLicenseInvestigation( compact, licenseeId, licenseState, - licenseType + licenseType, + licenseScope ); } @@ -255,16 +263,26 @@ export class DataApi { * @param {string} licenseState The 2-character state abbreviation for the License. * @param {string} licenseType The license type. * @param {string} investigationId The Investigation ID. + * @param {string} [licenseScope] The license scope. * @param {object} [encumbrance] Optional encumbrance config to add to the privilege. * @return {Promise} The server response. */ - public updateLicenseInvestigation(compact, licenseeId, licenseState, licenseType, investigationId, encumbrance) { + public updateLicenseInvestigation( + compact, + licenseeId, + licenseState, + licenseType, + investigationId, + licenseScope, + encumbrance + ) { return licenseDataApi.updateLicenseInvestigation( compact, licenseeId, licenseState, licenseType, investigationId, + licenseScope, encumbrance ); } diff --git a/webroot/src/network/licenseApi/data.api.ts b/webroot/src/network/licenseApi/data.api.ts index f49aa10a5e..4ab6d7127f 100644 --- a/webroot/src/network/licenseApi/data.api.ts +++ b/webroot/src/network/licenseApi/data.api.ts @@ -282,6 +282,7 @@ export class LicenseDataApi implements DataApiInterface { * @param {string} npdbCategory The NPDB category name. * @param {Array} npdbCategories The NPDB category list. * @param {string} startDate The encumber start date. + * @param {string} [licenseScope] The license scope. * @return {Promise} The server response. */ public async encumberLicense( @@ -292,12 +293,14 @@ export class LicenseDataApi implements DataApiInterface { encumbranceType: string, npdbCategory: string, npdbCategories: Array, - startDate: string + startDate: string, + licenseScope?: string ) { const serverResponse: any = await this.api.post(`/v1/compacts/${compact}/providers/${licenseeId}/licenses/jurisdiction/${licenseState}/licenseType/${licenseType}/encumbrance`, { encumbranceType, clinicalPrivilegeActionCategories: npdbCategories, encumbranceEffectiveDate: startDate, + ...(licenseScope && { licenseScope }), }); return serverResponse; @@ -305,13 +308,14 @@ export class LicenseDataApi implements DataApiInterface { /** * PATCH Un-encumber License for a licensee. - * @param {string} compact The compact string ID (aslp, octp, coun). - * @param {string} licenseeId The Licensee ID. - * @param {string} licenseState The 2-character state abbreviation for the License. - * @param {string} licenseType The license type. - * @param {string} encumbranceId The Encumbrance ID. - * @param {string} endDate The encumber end date. - * @return {Promise} The server response. + * @param {string} compact The compact string ID (aslp, octp, coun). + * @param {string} licenseeId The Licensee ID. + * @param {string} licenseState The 2-character state abbreviation for the License. + * @param {string} licenseType The license type. + * @param {string} encumbranceId The Encumbrance ID. + * @param {string} endDate The encumber end date. + * @param {string} [licenseScope] The license scope. + * @return {Promise} The server response. */ public async unencumberLicense( compact: string, @@ -319,10 +323,12 @@ export class LicenseDataApi implements DataApiInterface { licenseState: string, licenseType: string, encumbranceId: string, - endDate: string + endDate: string, + licenseScope?: string ) { const serverResponse: any = await this.api.patch(`/v1/compacts/${compact}/providers/${licenseeId}/licenses/jurisdiction/${licenseState}/licenseType/${licenseType}/encumbrance/${encumbranceId}`, { effectiveLiftDate: endDate, + ...(licenseScope && { licenseScope }), }); return serverResponse; @@ -334,15 +340,19 @@ export class LicenseDataApi implements DataApiInterface { * @param {string} licenseeId The Licensee ID. * @param {string} licenseState The 2-character state abbreviation for the License. * @param {string} licenseType The license type. + * @param {string} [licenseScope] The license scope. * @return {Promise} The server response. */ public async createLicenseInvestigation( compact: string, licenseeId: string, licenseState: string, - licenseType: string + licenseType: string, + licenseScope?: string ) { - const serverResponse: any = await this.api.post(`/v1/compacts/${compact}/providers/${licenseeId}/licenses/jurisdiction/${licenseState}/licenseType/${licenseType}/investigation`, {}); + const serverResponse: any = await this.api.post(`/v1/compacts/${compact}/providers/${licenseeId}/licenses/jurisdiction/${licenseState}/licenseType/${licenseType}/investigation`, { + ...(licenseScope && { licenseScope }), + }); return serverResponse; } @@ -354,11 +364,13 @@ export class LicenseDataApi implements DataApiInterface { * @param {string} licenseState The 2-character state abbreviation for the License. * @param {string} licenseType The license type. * @param {string} investigationId The Investigation ID. + * @param {string} [licenseScope] The license scope. * @param {object} [encumbrance] Optional encumbrance config to add to the license. * @param {string} encumbranceType The discipline action type. * @param {string} npdbCategory The NPDB category name. * @param {Array} npdbCategories The NPDB category list. * @param {string} startDate The encumber start date. + * @param {string} [licenseScope] The license scope. * @return {Promise} The server response. */ public async updateLicenseInvestigation( @@ -367,21 +379,25 @@ export class LicenseDataApi implements DataApiInterface { licenseState: string, licenseType: string, investigationId: string, + licenseScope?: string, encumbrance?: { encumbranceType: string, npdbCategory: string, npdbCategories: Array, - startDate: string + startDate: string, + licenseScope?: string, } ) { const serverResponse: any = await this.api.patch(`/v1/compacts/${compact}/providers/${licenseeId}/licenses/jurisdiction/${licenseState}/licenseType/${licenseType}/investigation/${investigationId}`, { action: 'close', + ...(licenseScope && { licenseScope }), ...(encumbrance ? { encumbrance: { encumbranceType: encumbrance.encumbranceType, clinicalPrivilegeActionCategories: encumbrance.npdbCategories, encumbranceEffectiveDate: encumbrance.startDate, + ...(licenseScope && { licenseScope }), }, } : {} diff --git a/webroot/src/network/mocks/mock.data.ts b/webroot/src/network/mocks/mock.data.ts index 73ef181c76..044f63fd6b 100644 --- a/webroot/src/network/mocks/mock.data.ts +++ b/webroot/src/network/mocks/mock.data.ts @@ -641,6 +641,7 @@ export const licensees = { licenseNumber: 'A-987654321', type: 'license-home', licenseType: 'occupational therapy assistant', + licenseScope: 'single-state', jurisdiction: 'co', dateOfIssuance: moment().subtract(10, 'months').format(serverDateFormat), dateOfUpdate: moment().subtract(10, 'months').format(serverDateFormat), @@ -668,6 +669,7 @@ export const licensees = { licenseNumber: 'A-555666777', type: 'license-home', licenseType: 'occupational therapist', + licenseScope: 'multi-state', jurisdiction: 'ca', dateOfIssuance: moment().subtract(2, 'years').subtract(7, 'days').subtract(10, 'months') .format(serverDateFormat), @@ -782,6 +784,7 @@ export const licensees = { licenseNumber: 'A-441445289', type: 'license-home', licenseType: 'occupational therapy assistant', + licenseScope: 'single-state', jurisdiction: 'co', dateOfIssuance: moment().subtract(10, 'months').format(serverDateFormat), dateOfUpdate: moment().subtract(10, 'months').format(serverDateFormat), @@ -808,6 +811,7 @@ export const licensees = { licenseNumber: 'A-921445289', type: 'license-home', licenseType: 'occupational therapist', + licenseScope: 'multi-state', jurisdiction: 'co', dateOfIssuance: moment().subtract(1, 'years').subtract(11, 'months').format(serverDateFormat), dateOfUpdate: moment().subtract(1, 'months').format(serverDateFormat), @@ -834,6 +838,7 @@ export const licensees = { licenseNumber: 'A-944945289', type: 'license-home', licenseType: 'occupational therapist', + licenseScope: 'single-state', jurisdiction: 'ma', dateOfIssuance: moment().subtract(2, 'years').subtract(7, 'days').subtract(10, 'months') .format(serverDateFormat), @@ -861,6 +866,7 @@ export const licensees = { npi: '6441445289', type: 'license-home', licenseType: 'occupational therapy assistant', + licenseScope: 'multi-state', jurisdiction: 'ca', dateOfIssuance: '2024-08-29', dateOfUpdate: '2024-08-29', @@ -887,6 +893,7 @@ export const licensees = { npi: '6441445289', type: 'license-home', licenseType: 'occupational therapy assistant', + licenseScope: 'single-state', jurisdiction: 'nv', dateOfIssuance: '2023-08-29', dateOfUpdate: '2024-08-29', @@ -1294,6 +1301,7 @@ export const licensees = { licenseNumber: 'A-312445289', type: 'license-home', licenseType: 'occupational therapy assistant', + licenseScope: 'multi-state', jurisdiction: 'co', dateOfIssuance: '2023-08-29', dateOfUpdate: '2023-08-29', @@ -1371,6 +1379,7 @@ export const licensees = { licenseNumber: 'A-1234567890', type: 'license-home', licenseType: 'occupational therapy assistant', + licenseScope: 'single-state', jurisdiction: 'co', dateOfIssuance: moment().add(1, 'day').subtract(11, 'months').subtract(2, 'years') .format(serverDateFormat), @@ -1448,6 +1457,7 @@ export const licensees = { licenseNumber: null, type: 'license-home', licenseType: 'occupational therapy assistant', + licenseScope: 'single-state', jurisdiction: 'co', dateOfIssuance: '2024-08-29', dateOfUpdate: '2024-08-29', diff --git a/webroot/src/store/users/users.actions.ts b/webroot/src/store/users/users.actions.ts index 7137334413..0cabcc4344 100644 --- a/webroot/src/store/users/users.actions.ts +++ b/webroot/src/store/users/users.actions.ts @@ -151,7 +151,8 @@ export default { encumbranceType, npdbCategory, npdbCategories, - startDate + startDate, + licenseScope }: any) => { commit(MutationTypes.ENCUMBER_LICENSE_REQUEST); return dataApi.encumberLicense( @@ -162,7 +163,8 @@ export default { encumbranceType, npdbCategory, npdbCategories, - startDate + startDate, + licenseScope ).then(async (response) => { dispatch('encumberLicenseSuccess'); @@ -185,7 +187,8 @@ export default { licenseState, licenseType, encumbranceId, - endDate + endDate, + licenseScope }: any) => { commit(MutationTypes.UNENCUMBER_LICENSE_REQUEST); return dataApi.unencumberLicense( @@ -194,7 +197,8 @@ export default { licenseState, licenseType, encumbranceId, - endDate + endDate, + licenseScope ).then(async (response) => { dispatch('unencumberLicenseSuccess'); @@ -216,13 +220,15 @@ export default { licenseeId, licenseState, licenseType, + licenseScope, }: any) => { commit(MutationTypes.CREATE_INVESTIGATION_LICENSE_REQUEST); return dataApi.createLicenseInvestigation( compact, licenseeId, licenseState, - licenseType + licenseType, + licenseScope ).then(async (response) => { dispatch('createInvestigationLicenseSuccess'); @@ -245,6 +251,7 @@ export default { licenseState, licenseType, investigationId, + licenseScope, encumbrance }: any) => { commit(MutationTypes.UPDATE_INVESTIGATION_LICENSE_REQUEST); @@ -254,6 +261,7 @@ export default { licenseState, licenseType, investigationId, + licenseScope, encumbrance ).then(async (response) => { dispatch('updateInvestigationLicenseSuccess'); diff --git a/webroot/src/styles.common/_colors.less b/webroot/src/styles.common/_colors.less index 4503fcc23d..4b7944060a 100644 --- a/webroot/src/styles.common/_colors.less +++ b/webroot/src/styles.common/_colors.less @@ -27,6 +27,7 @@ @darkBlue: #1e2f5e; @lightBlue: #d1ecf8; @veryLightBlue: #f6f9ff; +@altBlue1: #9ddcf9; // Greens @__green: #288737; From e6ba13c3e165014c73710b61685bbcc23831caa0 Mon Sep 17 00:00:00 2001 From: John Sandoval Date: Mon, 6 Jul 2026 09:58:18 -0600 Subject: [PATCH 2/4] WIP: multistate license scopes & discipline updates --- webroot/src/locales/es.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webroot/src/locales/es.json b/webroot/src/locales/es.json index 98009492ed..c8ddf62d07 100644 --- a/webroot/src/locales/es.json +++ b/webroot/src/locales/es.json @@ -966,11 +966,11 @@ }, { "name": "Fraude", - "key": "Fraud, Deception, or Misrepresentation" + "key": "fraud" }, { "name": "Daños al consumidor", - "key": "Consumer Harm" + "key": "consumer harm" }, { "name": "Otro", From cbd203f1a509e35e8ab4990718b39dc08b4b0a90 Mon Sep 17 00:00:00 2001 From: John Sandoval Date: Mon, 6 Jul 2026 12:24:30 -0600 Subject: [PATCH 3/4] WIP: multistate license scopes & discipline updates --- webroot/src/components/PrivilegeCard/PrivilegeCard.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/webroot/src/components/PrivilegeCard/PrivilegeCard.ts b/webroot/src/components/PrivilegeCard/PrivilegeCard.ts index 3cae70e880..8c0513fee8 100644 --- a/webroot/src/components/PrivilegeCard/PrivilegeCard.ts +++ b/webroot/src/components/PrivilegeCard/PrivilegeCard.ts @@ -294,7 +294,6 @@ class PrivilegeCard extends mixins(MixinForm) { // For a single-select, include the blank option if (!isMultiSelect) { - console.log('???'); options.unshift({ value: '', name: computed(() => this.$t('common.selectOption')) }); } From 271d98125d7a1e3a12b6106531757ada56f700b0 Mon Sep 17 00:00:00 2001 From: John Sandoval Date: Wed, 8 Jul 2026 10:49:14 -0600 Subject: [PATCH 4/4] PR review feedback --- webroot/src/components/Icons/Globe/Globe.vue | 9 ++------- webroot/src/components/Icons/MapPin/MapPin.vue | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/webroot/src/components/Icons/Globe/Globe.vue b/webroot/src/components/Icons/Globe/Globe.vue index a754e3430f..6422c4b5c7 100644 --- a/webroot/src/components/Icons/Globe/Globe.vue +++ b/webroot/src/components/Icons/Globe/Globe.vue @@ -6,8 +6,8 @@ --> diff --git a/webroot/src/components/Icons/MapPin/MapPin.vue b/webroot/src/components/Icons/MapPin/MapPin.vue index 6f22566bfc..658fa6e03c 100644 --- a/webroot/src/components/Icons/MapPin/MapPin.vue +++ b/webroot/src/components/Icons/MapPin/MapPin.vue @@ -6,8 +6,8 @@ -->