@sbc-connect/nuxt-auth 0.16.7 → 0.17.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/CHANGELOG.md +17 -0
- package/app/components/Connect/Account/Existing/List/Item.vue +65 -7
- package/app/components/Connect/Account/Existing/List/index.vue +12 -1
- package/app/interfaces/connect-account.ts +4 -0
- package/app/interfaces/connect-user-settings.ts +1 -0
- package/app/pages/auth/account/select.vue +3 -2
- package/app/plugins/auth-api.ts +1 -1
- package/app/plugins/connect-auth.client.ts +1 -1
- package/app/services/auth/query.ts +1 -1
- package/app/stores/connect-account.ts +23 -8
- package/i18n/locales/en-CA.ts +16 -0
- package/package.json +13 -13
- package/testMocks/mock-helpers.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @sbc-connect/nuxt-auth
|
|
2
2
|
|
|
3
|
+
## 0.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#201](https://github.com/bcgov/connect-nuxt/pull/201) [`0d043ed`](https://github.com/bcgov/connect-nuxt/commit/0d043ed037473ff381e0d3ca17065f11ca3b89d2) Thanks [@sumesh85](https://github.com/sumesh85)! - Account selector: existing-account rows now show the org's mailing address, a payment-method badge, and an NSF/statement-overdue status badge. NSF-suspended accounts are selectable (instead of disabled); clicking one takes the user straight to their account info page instead of into the app.
|
|
8
|
+
|
|
9
|
+
- `ConnectAccount` receives optional `address`, `paymentMethod`, `hasNsfInvoices`, and `hasOverdueInvoices` fields.
|
|
10
|
+
- `ConnectAccountExistingList`/`ConnectAccountExistingListItem` receives `showAddress`, `showPaymentMethodBadge`, and `showStatusBadge` props, all defaulting to `false` — existing consumers see no change on upgrade unless they opt in. The layer's own `/auth/account/select` page opts in to `showStatusBadge` so it keeps showing the NSF indicator.
|
|
11
|
+
|
|
12
|
+
- [#203](https://github.com/bcgov/connect-nuxt/pull/203) [`fedf109`](https://github.com/bcgov/connect-nuxt/commit/fedf109afdefa2869325afb9c7a268767c0e3d38) Thanks [@deetz99](https://github.com/deetz99)! - Update dependencies
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [[`fedf109`](https://github.com/bcgov/connect-nuxt/commit/fedf109afdefa2869325afb9c7a268767c0e3d38), [`fedf109`](https://github.com/bcgov/connect-nuxt/commit/fedf109afdefa2869325afb9c7a268767c0e3d38)]:
|
|
17
|
+
- @sbc-connect/nuxt-base@0.14.0
|
|
18
|
+
- @sbc-connect/nuxt-forms@0.8.0
|
|
19
|
+
|
|
3
20
|
## 0.16.7
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -1,11 +1,51 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
2
|
+
const {
|
|
3
|
+
account,
|
|
4
|
+
showPaymentMethodBadge = false,
|
|
5
|
+
showStatusBadge = false,
|
|
6
|
+
showAddress = false
|
|
7
|
+
} = defineProps<{
|
|
3
8
|
account: ConnectAccount
|
|
9
|
+
showPaymentMethodBadge?: boolean
|
|
10
|
+
showStatusBadge?: boolean
|
|
11
|
+
showAddress?: boolean
|
|
4
12
|
}>()
|
|
5
13
|
|
|
6
|
-
defineEmits<{
|
|
14
|
+
const emit = defineEmits<{
|
|
7
15
|
select: [id: number]
|
|
8
16
|
}>()
|
|
17
|
+
|
|
18
|
+
// ACTIVE is always selectable. Of the non-active statuses, only NSF_SUSPENDED also stays
|
|
19
|
+
// enabled (it redirects below instead of emitting select) - everything else stays disabled.
|
|
20
|
+
const isNsfSuspended = computed(() => account.accountStatus === AccountStatus.NSF_SUSPENDED)
|
|
21
|
+
const isUnusable = computed(() => account.accountStatus !== AccountStatus.ACTIVE && !isNsfSuspended.value)
|
|
22
|
+
|
|
23
|
+
function handleSelect() {
|
|
24
|
+
if (isNsfSuspended.value) {
|
|
25
|
+
useConnectAccountStore().redirectToAccountInfo(account)
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
emit('select', account.id)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const statusBadgeLabel = computed(() => {
|
|
32
|
+
if (!isNsfSuspended.value) {
|
|
33
|
+
return undefined
|
|
34
|
+
}
|
|
35
|
+
if (account.hasOverdueInvoices) {
|
|
36
|
+
return 'connect.badge.statementOverdue'
|
|
37
|
+
}
|
|
38
|
+
return 'connect.badge.nonSufficientFunds'
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const address = computed(() => account.address)
|
|
42
|
+
const addressLine = computed(() => {
|
|
43
|
+
const addr = address.value
|
|
44
|
+
if (!addr) {
|
|
45
|
+
return undefined
|
|
46
|
+
}
|
|
47
|
+
return [addr.street, addr.city, addr.region, addr.postalCode, addr.country].filter(Boolean).join(', ')
|
|
48
|
+
})
|
|
9
49
|
</script>
|
|
10
50
|
|
|
11
51
|
<template>
|
|
@@ -13,7 +53,7 @@ defineEmits<{
|
|
|
13
53
|
<div
|
|
14
54
|
class="flex flex-row items-center gap-4 sm:gap-6"
|
|
15
55
|
:class="{
|
|
16
|
-
'opacity-50':
|
|
56
|
+
'opacity-50': isUnusable,
|
|
17
57
|
}"
|
|
18
58
|
>
|
|
19
59
|
<UAvatar
|
|
@@ -27,13 +67,31 @@ defineEmits<{
|
|
|
27
67
|
<span class="text-lg font-bold text-neutral-highlighted">
|
|
28
68
|
{{ account.label }}
|
|
29
69
|
</span>
|
|
70
|
+
<span v-if="showAddress && addressLine" class="text-sm text-neutral">
|
|
71
|
+
{{ addressLine }}
|
|
72
|
+
</span>
|
|
73
|
+
<div class="mt-1 flex flex-wrap gap-2">
|
|
74
|
+
<UBadge
|
|
75
|
+
v-if="showPaymentMethodBadge && account.paymentMethod"
|
|
76
|
+
:label="$t(`connect.badge.paymentMethod.${account.paymentMethod}`)"
|
|
77
|
+
variant="subtle"
|
|
78
|
+
color="neutral"
|
|
79
|
+
class="px-3 text-center font-bold"
|
|
80
|
+
/>
|
|
81
|
+
<UBadge
|
|
82
|
+
v-if="showStatusBadge && statusBadgeLabel"
|
|
83
|
+
:label="$t(statusBadgeLabel)"
|
|
84
|
+
color="error"
|
|
85
|
+
class="px-3 text-center font-bold"
|
|
86
|
+
/>
|
|
87
|
+
</div>
|
|
30
88
|
</div>
|
|
31
89
|
</div>
|
|
32
90
|
<div class="flex w-full flex-col gap-4 sm:w-fit sm:flex-row">
|
|
33
91
|
<div class="my-auto flex gap-2">
|
|
34
92
|
<UBadge
|
|
35
|
-
v-if="
|
|
36
|
-
:label="$t('badge.inactiveAccount')"
|
|
93
|
+
v-if="isUnusable"
|
|
94
|
+
:label="$t('connect.badge.inactiveAccount')"
|
|
37
95
|
class="bg-[#fff7e3] px-3 text-center font-bold text-neutral"
|
|
38
96
|
/>
|
|
39
97
|
</div>
|
|
@@ -43,11 +101,11 @@ defineEmits<{
|
|
|
43
101
|
:aria-label="$t('connect.label.useThisAccountAria', { name: account.label })"
|
|
44
102
|
:icon="'i-mdi-chevron-right'"
|
|
45
103
|
trailing
|
|
46
|
-
:disabled="
|
|
104
|
+
:disabled="isUnusable"
|
|
47
105
|
size="xl"
|
|
48
106
|
data-testid="choose-existing-account-button"
|
|
49
107
|
class="w-full justify-center sm:w-min sm:justify-normal"
|
|
50
|
-
@click="
|
|
108
|
+
@click="handleSelect"
|
|
51
109
|
/>
|
|
52
110
|
</div>
|
|
53
111
|
</li>
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
2
|
+
const {
|
|
3
|
+
accounts,
|
|
4
|
+
showPaymentMethodBadge = false,
|
|
5
|
+
showStatusBadge = false,
|
|
6
|
+
showAddress = false
|
|
7
|
+
} = defineProps<{
|
|
3
8
|
accounts: ConnectAccount[]
|
|
9
|
+
showPaymentMethodBadge?: boolean
|
|
10
|
+
showStatusBadge?: boolean
|
|
11
|
+
showAddress?: boolean
|
|
4
12
|
}>()
|
|
5
13
|
|
|
6
14
|
defineEmits<{
|
|
@@ -23,6 +31,9 @@ defineEmits<{
|
|
|
23
31
|
v-for="account in accounts"
|
|
24
32
|
:key="account.id"
|
|
25
33
|
:account
|
|
34
|
+
:show-payment-method-badge="showPaymentMethodBadge"
|
|
35
|
+
:show-status-badge="showStatusBadge"
|
|
36
|
+
:show-address="showAddress"
|
|
26
37
|
@select="$emit('select', $event)"
|
|
27
38
|
/>
|
|
28
39
|
</ul>
|
|
@@ -7,6 +7,10 @@ export interface ConnectAccount {
|
|
|
7
7
|
type: UserSettingsType.ACCOUNT
|
|
8
8
|
urlpath: string
|
|
9
9
|
urlorigin: string
|
|
10
|
+
address?: ConnectAccountAddress
|
|
11
|
+
paymentMethod?: string
|
|
12
|
+
hasNsfInvoices?: string
|
|
13
|
+
hasOverdueInvoices?: string
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
export interface ConnectCreateAccount {
|
|
@@ -90,6 +90,7 @@ onBeforeMount(() => {
|
|
|
90
90
|
<ConnectAccountExistingList
|
|
91
91
|
v-if="showAccountList"
|
|
92
92
|
:accounts="store.userAccounts"
|
|
93
|
+
:show-status-badge="true"
|
|
93
94
|
@select="selectAndRedirect"
|
|
94
95
|
/>
|
|
95
96
|
|
|
@@ -113,7 +114,7 @@ onBeforeMount(() => {
|
|
|
113
114
|
trailing
|
|
114
115
|
size="xl"
|
|
115
116
|
class="w-full justify-center sm:w-min sm:justify-normal"
|
|
116
|
-
@click="addNew = true"
|
|
117
|
+
@click="() => { addNew = true }"
|
|
117
118
|
/>
|
|
118
119
|
<UButton
|
|
119
120
|
v-else
|
|
@@ -142,7 +143,7 @@ onBeforeMount(() => {
|
|
|
142
143
|
trailing
|
|
143
144
|
size="xl"
|
|
144
145
|
class="w-full justify-center sm:w-min sm:justify-normal"
|
|
145
|
-
@click="addNew = false"
|
|
146
|
+
@click="() => { addNew = false }"
|
|
146
147
|
/>
|
|
147
148
|
<UButton
|
|
148
149
|
:label="$t('connect.label.saveAndContinue')"
|
package/app/plugins/auth-api.ts
CHANGED
|
@@ -2,7 +2,7 @@ export default defineNuxtPlugin({
|
|
|
2
2
|
name: 'auth-api',
|
|
3
3
|
order: -20,
|
|
4
4
|
parallel: true,
|
|
5
|
-
setup(nuxtApp) {
|
|
5
|
+
setup(nuxtApp): { provide: { authApi: ReturnType<typeof $fetch.create> } } {
|
|
6
6
|
const rtc = nuxtApp.$config.public
|
|
7
7
|
const authApiUrl = rtc.authApiUrl + rtc.authApiVersion
|
|
8
8
|
const appName = rtc.appName
|
|
@@ -62,7 +62,7 @@ export const useConnectAuthQuery = () => {
|
|
|
62
62
|
function userSettingsOptions(options?: DefineOptions<ConnectUserSettings[]>) {
|
|
63
63
|
const keycloakGuid = useConnectAuth().authUser.value?.keycloakGuid
|
|
64
64
|
return defineQueryOptions({
|
|
65
|
-
query: () => $authApi<ConnectUserSettings[]>(`/users/${keycloakGuid}/settings
|
|
65
|
+
query: () => $authApi<ConnectUserSettings[]>(`/users/${keycloakGuid}/settings`, { query: { expand: 'address' } }),
|
|
66
66
|
staleTime: DEFAULT_STALE_TIME,
|
|
67
67
|
enabled: !!keycloakGuid,
|
|
68
68
|
...options,
|
|
@@ -74,12 +74,21 @@ export const useConnectAccountStore = defineStore('connect-auth-account-store',
|
|
|
74
74
|
const accounts = await service.getUserAccounts(force).catch(() => undefined)
|
|
75
75
|
if (accounts && accounts[0]) {
|
|
76
76
|
userAccounts.value = accounts
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
77
|
+
// Always resync from the fresh list so a persisted currentAccount never keeps a stale status.
|
|
78
|
+
currentAccount.value = accounts.find(account => account.id === currentAccount.value.id) ?? accounts[0]
|
|
80
79
|
}
|
|
81
80
|
}
|
|
82
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Sets `account` as current and navigates to its own info/settings page. Used both when a
|
|
84
|
+
* user clicks a visibly NSF/overdue account, and when a consumer's own backend rejects an
|
|
85
|
+
* action (e.g. payment redemption) for an account that wasn't flagged yet on the client.
|
|
86
|
+
*/
|
|
87
|
+
function redirectToAccountInfo(account: ConnectAccount) {
|
|
88
|
+
currentAccount.value = account
|
|
89
|
+
return navigateTo(`${account.urlorigin}${account.urlpath}`, { external: true })
|
|
90
|
+
}
|
|
91
|
+
|
|
83
92
|
/** Switch the current account to the given account ID if it exists in the user's account list */
|
|
84
93
|
function switchCurrentAccount(accountId: number) {
|
|
85
94
|
const account = userAccounts.value.find(account => account.id === accountId)
|
|
@@ -90,11 +99,16 @@ export const useConnectAccountStore = defineStore('connect-auth-account-store',
|
|
|
90
99
|
}
|
|
91
100
|
|
|
92
101
|
function checkAccountStatus() {
|
|
93
|
-
|
|
94
|
-
if ([AccountStatus.
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
const status = currentAccount.value?.accountStatus
|
|
103
|
+
if ([AccountStatus.SUSPENDED, AccountStatus.NSF_SUSPENDED].includes(status)) {
|
|
104
|
+
// Plain SUSPENDED has no self-serve resolution anywhere, so only the base paths are
|
|
105
|
+
// exempt. NSF_SUSPENDED additionally owns its own handling on the account selector and
|
|
106
|
+
// anywhere in a pay-link flow (dynamic /pay/{token}/... routes).
|
|
107
|
+
const path = useRoute().path
|
|
108
|
+
const endPath = path.split('/').pop() as string
|
|
109
|
+
const isNsfException = status === AccountStatus.NSF_SUSPENDED
|
|
110
|
+
&& (path.includes('/pay/') || ['select', 'create'].includes(endPath))
|
|
111
|
+
const isAllowedPath = ['return-cc-payment', 'signout'].includes(endPath) || isNsfException
|
|
98
112
|
if (!isAllowedPath) {
|
|
99
113
|
// URL not allowed so redirect
|
|
100
114
|
const redirectUrl = `${rtc.authWebUrl}account-freeze`
|
|
@@ -150,6 +164,7 @@ export const useConnectAccountStore = defineStore('connect-auth-account-store',
|
|
|
150
164
|
initAccountStore,
|
|
151
165
|
isCurrentAccount,
|
|
152
166
|
loadUserAccounts,
|
|
167
|
+
redirectToAccountInfo,
|
|
153
168
|
syncUserProfile,
|
|
154
169
|
switchCurrentAccount,
|
|
155
170
|
userAccounts,
|
package/i18n/locales/en-CA.ts
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
export default {
|
|
3
3
|
/* Ordering should be alphabetical unless otherwise specified */
|
|
4
4
|
connect: {
|
|
5
|
+
badge: {
|
|
6
|
+
inactiveAccount: 'Inactive',
|
|
7
|
+
nonSufficientFunds: 'Non-Sufficient Funds',
|
|
8
|
+
paymentMethod: {
|
|
9
|
+
CASH: 'Cash',
|
|
10
|
+
CC: 'Credit Card',
|
|
11
|
+
CHEQUE: 'Cheque',
|
|
12
|
+
DIRECT_PAY: 'Credit Card',
|
|
13
|
+
DRAWDOWN: 'BC Online',
|
|
14
|
+
EFT: 'Electronic Funds Transfer',
|
|
15
|
+
EJV: 'Electronic Journal Voucher',
|
|
16
|
+
ONLINE_BANKING: 'Online Banking',
|
|
17
|
+
PAD: 'Pre-Authorized Debit'
|
|
18
|
+
},
|
|
19
|
+
statementOverdue: 'Statement Overdue'
|
|
20
|
+
},
|
|
5
21
|
label: {
|
|
6
22
|
accept: 'Accept',
|
|
7
23
|
accountInfo: 'Account Info',
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sbc-connect/nuxt-auth",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.17.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "github:bcgov/connect-nuxt"
|
|
@@ -9,24 +9,24 @@
|
|
|
9
9
|
"license": "BSD-3-Clause",
|
|
10
10
|
"main": "./nuxt.config.ts",
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@axe-core/playwright": "4.
|
|
13
|
-
"dotenv": "
|
|
14
|
-
"nuxt": "4.
|
|
12
|
+
"@axe-core/playwright": "4.13.0",
|
|
13
|
+
"dotenv": "18.0.4",
|
|
14
|
+
"nuxt": "4.5.2",
|
|
15
15
|
"typescript": "6.0.3",
|
|
16
|
-
"vue-tsc": "3.3.
|
|
16
|
+
"vue-tsc": "3.3.11",
|
|
17
17
|
"@sbc-connect/eslint-config": "0.0.8",
|
|
18
|
-
"@sbc-connect/
|
|
19
|
-
"@sbc-connect/
|
|
18
|
+
"@sbc-connect/vitest-config": "0.2.0",
|
|
19
|
+
"@sbc-connect/playwright-config": "0.2.1"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@pinia/colada": "1.
|
|
23
|
-
"@pinia/colada-nuxt": "1.0
|
|
24
|
-
"@pinia/nuxt": "0.
|
|
22
|
+
"@pinia/colada": "1.4.6",
|
|
23
|
+
"@pinia/colada-nuxt": "1.2.0",
|
|
24
|
+
"@pinia/nuxt": "1.0.2",
|
|
25
25
|
"keycloak-js": "26.2.4",
|
|
26
|
-
"pinia": "
|
|
26
|
+
"pinia": "4.0.3",
|
|
27
27
|
"pinia-plugin-persistedstate": "4.7.1",
|
|
28
|
-
"@sbc-connect/nuxt-base": "0.
|
|
29
|
-
"@sbc-connect/nuxt-forms": "0.
|
|
28
|
+
"@sbc-connect/nuxt-base": "0.14.0",
|
|
29
|
+
"@sbc-connect/nuxt-forms": "0.8.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"preinstall": "npx only-allow pnpm",
|
|
@@ -9,7 +9,7 @@ export const mockApiCallsForSetAccount = async (
|
|
|
9
9
|
page.route('**/users/@me', async (route) => {
|
|
10
10
|
await route.fulfill({ json: getUserProfileMock() })
|
|
11
11
|
})
|
|
12
|
-
page.route('**/users/**/settings', async (route) => {
|
|
12
|
+
page.route('**/users/**/settings**', async (route) => {
|
|
13
13
|
await route.fulfill({ json: getUserSettingsMock(accountType) })
|
|
14
14
|
})
|
|
15
15
|
}
|