1
+ <!-- eslint-disable vue/no-v-html -->
1
2
<script setup lang="ts">
2
3
import { storeToRefs } from ' pinia' ;
3
- import { isProxy , onMounted , ref , watch } from ' vue' ;
4
+ import { computed , isProxy , onMounted , ref , watch } from ' vue' ;
4
5
5
- import { Button , Dropdown , RadioButton } from ' @/lib/primevue' ;
6
- import { useConfigStore , useUserStore } from ' @/store' ;
6
+ import { Button , OverlayPanel , Dropdown , RadioButton } from ' @/lib/primevue' ;
7
+ import { useUserStore , useAuthStore } from ' @/store' ;
7
8
import { Regex } from ' @/utils/constants' ;
8
9
9
10
import type { Ref } from ' vue' ;
10
11
import type { IInputEvent } from ' @/interfaces' ;
11
12
import type { DropdownChangeEvent } from ' @/lib/primevue' ;
12
- import type { IdentityProvider , User , UserPermissions } from ' @/types' ;
13
+ import type { User , UserPermissions } from ' @/types' ;
13
14
14
15
// Props
15
16
type Props = {
@@ -23,20 +24,26 @@ const emit = defineEmits(['add-user', 'cancel-search-users']);
23
24
24
25
// Store
25
26
const userStore = useUserStore ();
26
- const { getConfig } = storeToRefs (useConfigStore ());
27
- const { userSearch } = storeToRefs (useUserStore ());
27
+ const { getExternalUsers, userSearch } = storeToRefs (useUserStore ());
28
+ const { getUserId } = storeToRefs (useAuthStore ());
28
29
29
30
// State
30
31
const invalidSelectedUser: Ref <boolean > = ref (false );
31
- const selectedIDP : Ref <IdentityProvider | null > = ref (null );
32
+ const selectedIdpType : Ref <string | undefined > = ref (' internal ' );
32
33
const selectedUser: Ref <User | null > = ref (null );
33
34
const userSearchInput: Ref <string | undefined > = ref (' ' );
34
- const userSearchPlaceholder: Ref <string | undefined > = ref (' ' );
35
+ const userSearchPlaceholder: Ref <string | undefined > = ref (' Name or email address' );
36
+ // search results
37
+ const userSearchResults: Ref <User []> = computed (() => {
38
+ return (selectedIdpType .value === ' internal' ? userSearch .value : getExternalUsers .value )
39
+ // filter current user
40
+ .filter ((user : User ) => user .userId !== getUserId .value );
41
+ });
35
42
36
43
// Actions
37
44
const getUserDropdownLabel = (option : User ) => {
38
- if (selectedIDP .value ?. idp ) {
39
- if (selectedIDP .value . searchable ) {
45
+ if (selectedIdpType .value ) {
46
+ if (selectedIdpType .value === ' internal ' ) {
40
47
return ` ${option .fullName } [${option .email }] ` ;
41
48
} else {
42
49
return option .email ;
@@ -73,15 +80,15 @@ const onChange = (event: DropdownChangeEvent) => {
73
80
74
81
const onInput = (event : IInputEvent ) => {
75
82
const input: string = event .target .value ;
76
- if (selectedIDP .value ?. idp ) {
83
+ if (selectedIdpType .value ) {
77
84
// Reset selection on any input change
78
85
selectedUser .value = null ;
79
86
invalidSelectedUser .value = false ;
80
-
81
- if ( selectedIDP . value . searchable && input . length >= 3 ) {
82
- userStore . fetchUsers ({ idp: selectedIDP . value . idp , search: input });
83
- } else if (input .match (Regex .EMAIL )) {
84
- userStore .fetchUsers ({ idp: selectedIDP . value . idp , email: input });
87
+ if ( selectedIdpType . value === ' internal ' && input . length >= 3 ) {
88
+ userStore . fetchUsers ({ idp: ' idir ' , search: input });
89
+ }
90
+ else if (input .match (Regex .EMAIL )) {
91
+ userStore .fetchUsers ({ email: input });
85
92
} else {
86
93
userStore .clearSearch ();
87
94
}
@@ -96,59 +103,98 @@ const onReset = () => {
96
103
userSearchInput .value = ' ' ;
97
104
};
98
105
99
- watch (selectedIDP , () => {
100
- if (selectedIDP .value ?.searchable ) {
101
- userSearchPlaceholder .value = ` Enter the full name or email address of an existing ${selectedIDP .value ?.name } ` ;
102
- } else {
103
- userSearchPlaceholder .value = ` Enter an existing user's ${selectedIDP .value ?.name } email address ` ;
104
- }
106
+ watch (selectedIdpType , () => {
107
+ // user search field placeholder
108
+ userSearchPlaceholder .value = selectedIdpType .value === ' internal' ?
109
+ ' Name or email address' : ' Complete email address' ;
105
110
});
106
111
107
- onMounted (() => {
108
- // Set default IDP
109
- selectedIDP .value = getConfig .value .idpList [0 ];
112
+ const helpText = ref (' ' );
113
+ const help1 = ref ();
114
+ const help2 = ref ();
115
+
116
+ const toggleHelp = (id : string | undefined , event : any ) => {
117
+ switch (id ) {
118
+ case ' help1' :
119
+ help1 .value .toggle (event );
120
+ helpText .value = ' Select the authentication method this person will use to sign into BCBox.' ;
121
+ break ;
122
+ case ' help2' :
123
+ help2 .value .toggle (event );
124
+ helpText .value = ' Note: If the person you are adding is new to BCBox, ' +
125
+ ' please ask them to first sign in to the website, so we can find them in the system.' ;
126
+ break ;
127
+ }
128
+ };
110
129
130
+ onMounted (() => {
111
131
onReset ();
112
132
});
113
133
</script >
114
134
115
135
<template >
116
136
<div >
117
- <ul v-if =" getConfig.idpList.length <= 3" >
118
- <li
119
- v-for =" idp of getConfig.idpList"
120
- :key =" idp.idp"
121
- class =" field-radiobutton mt-1"
137
+ <h4 class =" mb-3" >Add User(s)</h4 >
138
+ <div class =" mb-2" >
139
+ <label >How will his person sign in to BCBox?</label >
140
+ <span
141
+ class =" help-link material-icons-outlined"
142
+ @click =" toggleHelp('help1', $event)"
122
143
>
123
- <RadioButton
124
- v-model =" selectedIDP"
125
- :input-id =" idp.idp"
126
- name =" idp"
127
- :value =" idp"
128
- @click =" onReset"
129
- />
130
- <label :for =" idp.idp" >{{ idp.name }}</label >
131
- </li >
132
- </ul >
133
- <div v-else >
134
- <Dropdown
135
- v-model =" selectedIDP"
136
- :options =" getConfig.idpList"
137
- :option-label ="
138
- (option: any) => {
139
- return `${option.name} (${option.elevatedRights ? 'internal' : 'external'})`;
140
- }
141
- "
142
- class =" mt-1"
143
- @change =" onReset"
144
- />
144
+ help_outline
145
+ </span >
146
+ <OverlayPanel
147
+ ref =" help1"
148
+ class =" max-w-25rem"
149
+ >
150
+ <span >{{ helpText }}</span >
151
+ </OverlayPanel >
152
+ </div >
153
+ <div class =" card flex justify-center mb-4" >
154
+ <div class =" flex flex-wrap gap-4" >
155
+ <div class =" flex items-center align-items-center gap-2" >
156
+ <RadioButton
157
+ v-model =" selectedIdpType"
158
+ input-id =" internal"
159
+ name =" idpType"
160
+ value =" internal"
161
+ @click =" onReset"
162
+ />
163
+ <label for =" internal" >Government IDIR</label >
164
+ </div >
165
+ <div class =" flex align-items-center items-center gap-2" >
166
+ <RadioButton
167
+ v-model =" selectedIdpType"
168
+ input-id =" external"
169
+ name =" idpType"
170
+ value =" external"
171
+ @click =" onReset"
172
+ />
173
+ <label for =" external" >External (eg: BCeID or BC Services Card)</label >
174
+ </div >
175
+ </div >
145
176
</div >
146
177
178
+ <div class =" mb-2" >
179
+ <label >Search for user</label >
180
+ <span
181
+ class =" help-link material-icons-outlined"
182
+ @click =" toggleHelp('help2', $event)"
183
+ >
184
+ help_outline
185
+ </span >
186
+ <OverlayPanel
187
+ ref =" help2"
188
+ class =" max-w-25rem"
189
+ >
190
+ <span >{{ helpText }}</span >
191
+ </OverlayPanel >
192
+ </div >
147
193
<div class =" flex" >
148
194
<div class =" flex flex-auto" >
149
195
<Dropdown
150
196
v-model =" userSearchInput"
151
- :options =" userSearch "
197
+ :options =" userSearchResults "
152
198
:option-label =" (option: any) => getUserDropdownLabel(option)"
153
199
editable
154
200
:placeholder =" userSearchPlaceholder"
0 commit comments