@7365admin1/layer-common 1.11.42 → 1.11.44
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
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-row no-gutters>
|
|
3
|
-
<v-col cols="12" class="mb-
|
|
3
|
+
<v-col cols="12" class="mb-3">
|
|
4
4
|
<v-row no-gutters align="center" justify="space-between">
|
|
5
|
-
<div>
|
|
5
|
+
<div class="d-flex flex-wrap align-center">
|
|
6
6
|
<v-btn
|
|
7
|
+
v-if="showAddButton && canAddServiceProvider"
|
|
7
8
|
class="text-none mr-2"
|
|
8
9
|
rounded="pill"
|
|
9
10
|
variant="tonal"
|
|
10
|
-
@click="(createDialog = true), setServiceProvider({ mode: 'add' })"
|
|
11
11
|
size="large"
|
|
12
|
+
@click="(createDialog = true), setServiceProvider({ mode: 'add' })"
|
|
12
13
|
>
|
|
13
14
|
Add
|
|
14
15
|
</v-btn>
|
|
15
16
|
<v-btn
|
|
17
|
+
v-if="canInviteServiceProvider"
|
|
16
18
|
class="text-none mr-2"
|
|
17
19
|
rounded="pill"
|
|
18
20
|
variant="tonal"
|
|
@@ -25,6 +27,7 @@
|
|
|
25
27
|
Invite
|
|
26
28
|
</v-btn>
|
|
27
29
|
<v-btn
|
|
30
|
+
v-if="showBillingButton"
|
|
28
31
|
class="text-none mr-2"
|
|
29
32
|
rounded="pill"
|
|
30
33
|
variant="tonal"
|
|
@@ -41,16 +44,18 @@
|
|
|
41
44
|
|
|
42
45
|
<v-text-field
|
|
43
46
|
v-model="searchText"
|
|
44
|
-
placeholder="Search
|
|
47
|
+
placeholder="Search"
|
|
45
48
|
variant="outlined"
|
|
46
49
|
density="comfortable"
|
|
47
50
|
clearable
|
|
48
51
|
hide-details
|
|
52
|
+
prepend-inner-icon="mdi-magnify"
|
|
49
53
|
class="ml-2"
|
|
50
|
-
style="max-width:
|
|
54
|
+
style="max-width: 280px"
|
|
51
55
|
/>
|
|
52
56
|
</v-row>
|
|
53
57
|
</v-col>
|
|
58
|
+
|
|
54
59
|
<v-col cols="12">
|
|
55
60
|
<v-card
|
|
56
61
|
width="100%"
|
|
@@ -59,50 +64,227 @@
|
|
|
59
64
|
rounded="lg"
|
|
60
65
|
:loading="loading"
|
|
61
66
|
>
|
|
62
|
-
<
|
|
63
|
-
<
|
|
67
|
+
<div class="sp-table-header">
|
|
68
|
+
<v-toolbar
|
|
69
|
+
density="compact"
|
|
70
|
+
color="grey-lighten-4"
|
|
71
|
+
flat
|
|
72
|
+
class="sp-toolbar-top px-2"
|
|
73
|
+
>
|
|
64
74
|
<v-btn
|
|
65
|
-
fab
|
|
66
75
|
icon
|
|
76
|
+
variant="text"
|
|
67
77
|
density="comfortable"
|
|
68
|
-
@click="
|
|
78
|
+
@click="loadList()"
|
|
69
79
|
>
|
|
70
80
|
<v-icon>mdi-refresh</v-icon>
|
|
71
81
|
</v-btn>
|
|
72
|
-
</template>
|
|
73
82
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
<v-spacer />
|
|
84
|
+
|
|
85
|
+
<template v-if="canViewServiceProviders">
|
|
86
|
+
<span class="mr-2 text-caption text-medium-emphasis">{{
|
|
87
|
+
pageRange
|
|
88
|
+
}}</span>
|
|
79
89
|
<local-pagination
|
|
80
90
|
v-model="page"
|
|
81
91
|
:length="pages"
|
|
82
|
-
@update:value="
|
|
92
|
+
@update:value="loadList()"
|
|
83
93
|
/>
|
|
84
|
-
</
|
|
85
|
-
</
|
|
86
|
-
|
|
94
|
+
</template>
|
|
95
|
+
</v-toolbar>
|
|
96
|
+
|
|
97
|
+
<v-tabs
|
|
98
|
+
v-model="listTab"
|
|
99
|
+
color="primary"
|
|
100
|
+
density="comfortable"
|
|
101
|
+
class="sp-tabs"
|
|
102
|
+
align-tabs="start"
|
|
103
|
+
>
|
|
104
|
+
<v-tab value="active" class="text-none">Service Providers</v-tab>
|
|
105
|
+
<v-tab value="pending" class="text-none">Pending</v-tab>
|
|
106
|
+
<v-tab value="inactive" class="text-none">In-Active</v-tab>
|
|
107
|
+
</v-tabs>
|
|
108
|
+
</div>
|
|
87
109
|
|
|
88
110
|
<v-data-table
|
|
111
|
+
v-if="canViewServiceProviders"
|
|
89
112
|
:headers="headers"
|
|
90
113
|
:items="items"
|
|
91
114
|
item-value="_id"
|
|
92
|
-
items-per-page="
|
|
115
|
+
:items-per-page="pageSize"
|
|
93
116
|
fixed-header
|
|
94
117
|
hide-default-footer
|
|
95
|
-
|
|
96
|
-
style="max-height: calc(100vh -
|
|
118
|
+
class="sp-table"
|
|
119
|
+
style="max-height: calc(100vh - 280px)"
|
|
97
120
|
>
|
|
98
|
-
<template #item.
|
|
99
|
-
<span class="text-
|
|
121
|
+
<template #item.companyName="{ item }">
|
|
122
|
+
<span class="text-body-2 d-block text-truncate sp-col-company">{{
|
|
123
|
+
item.companyName
|
|
124
|
+
}}</span>
|
|
125
|
+
</template>
|
|
126
|
+
<template #item.email="{ item }">
|
|
127
|
+
<span class="text-body-2 d-block text-truncate sp-col-email">{{
|
|
128
|
+
item.email
|
|
129
|
+
}}</span>
|
|
130
|
+
</template>
|
|
131
|
+
<template #item.type="{ item }">
|
|
132
|
+
<span class="text-body-2 d-block text-truncate sp-col-type">{{
|
|
133
|
+
item.type
|
|
134
|
+
}}</span>
|
|
135
|
+
</template>
|
|
136
|
+
<template #item.members="{ item }">
|
|
137
|
+
<span class="text-body-2">{{ item.members }}</span>
|
|
138
|
+
</template>
|
|
139
|
+
<template #item.status="{ item }">
|
|
140
|
+
<v-chip
|
|
141
|
+
:color="statusChipColor(item.status)"
|
|
142
|
+
size="small"
|
|
143
|
+
variant="tonal"
|
|
144
|
+
class="text-none"
|
|
145
|
+
>
|
|
146
|
+
{{ item.status }}
|
|
147
|
+
</v-chip>
|
|
148
|
+
</template>
|
|
149
|
+
<template #item.actions="{ item }">
|
|
150
|
+
<v-menu v-if="item.source === 'provider'" location="bottom end">
|
|
151
|
+
<template #activator="{ props: menuProps }">
|
|
152
|
+
<v-btn
|
|
153
|
+
v-bind="menuProps"
|
|
154
|
+
icon
|
|
155
|
+
variant="text"
|
|
156
|
+
density="comfortable"
|
|
157
|
+
aria-label="Row actions"
|
|
158
|
+
>
|
|
159
|
+
<v-icon>mdi-dots-vertical</v-icon>
|
|
160
|
+
</v-btn>
|
|
161
|
+
</template>
|
|
162
|
+
<v-list density="compact" min-width="140">
|
|
163
|
+
<v-list-item
|
|
164
|
+
v-if="canViewMembers(item)"
|
|
165
|
+
title="View Members"
|
|
166
|
+
@click="openView(item)"
|
|
167
|
+
/>
|
|
168
|
+
<v-list-item
|
|
169
|
+
:title="rowActionLabel(item)"
|
|
170
|
+
:base-color="
|
|
171
|
+
item.source === 'provider' && listTab === 'inactive'
|
|
172
|
+
? undefined
|
|
173
|
+
: 'error'
|
|
174
|
+
"
|
|
175
|
+
@click="onDeleteRow(item)"
|
|
176
|
+
/>
|
|
177
|
+
</v-list>
|
|
178
|
+
</v-menu>
|
|
100
179
|
</template>
|
|
101
180
|
</v-data-table>
|
|
181
|
+
<v-card-text v-else class="text-body-2 text-medium-emphasis">
|
|
182
|
+
You do not have permission to view service providers.
|
|
183
|
+
</v-card-text>
|
|
184
|
+
|
|
102
185
|
</v-card>
|
|
103
186
|
</v-col>
|
|
104
187
|
</v-row>
|
|
105
188
|
|
|
189
|
+
<v-dialog v-model="viewDialog" max-width="514">
|
|
190
|
+
<v-card rounded="lg" class="sp-members-card">
|
|
191
|
+
<v-card-title class="sp-members-title">
|
|
192
|
+
Members ({{ memberDialogCount }})
|
|
193
|
+
</v-card-title>
|
|
194
|
+
|
|
195
|
+
<v-divider />
|
|
196
|
+
|
|
197
|
+
<v-table class="sp-members-table">
|
|
198
|
+
<thead>
|
|
199
|
+
<tr>
|
|
200
|
+
<th>Name</th>
|
|
201
|
+
<th class="text-right">Role</th>
|
|
202
|
+
</tr>
|
|
203
|
+
</thead>
|
|
204
|
+
<tbody>
|
|
205
|
+
<tr v-if="loadingMembers">
|
|
206
|
+
<td colspan="2" class="text-center text-medium-emphasis">
|
|
207
|
+
Loading...
|
|
208
|
+
</td>
|
|
209
|
+
</tr>
|
|
210
|
+
<tr v-else-if="!serviceProviderMembers.length">
|
|
211
|
+
<td colspan="2" class="text-center text-medium-emphasis">
|
|
212
|
+
No members found.
|
|
213
|
+
</td>
|
|
214
|
+
</tr>
|
|
215
|
+
<template v-else>
|
|
216
|
+
<tr v-for="member in serviceProviderMembers" :key="member._id">
|
|
217
|
+
<td>{{ member.name }}</td>
|
|
218
|
+
<td class="text-right">{{ member.role }}</td>
|
|
219
|
+
</tr>
|
|
220
|
+
</template>
|
|
221
|
+
</tbody>
|
|
222
|
+
</v-table>
|
|
223
|
+
|
|
224
|
+
<v-divider />
|
|
225
|
+
|
|
226
|
+
<v-card-actions class="pa-0">
|
|
227
|
+
<v-btn
|
|
228
|
+
block
|
|
229
|
+
variant="text"
|
|
230
|
+
height="56"
|
|
231
|
+
class="text-none font-weight-bold"
|
|
232
|
+
@click="viewDialog = false"
|
|
233
|
+
>
|
|
234
|
+
Close
|
|
235
|
+
</v-btn>
|
|
236
|
+
</v-card-actions>
|
|
237
|
+
</v-card>
|
|
238
|
+
</v-dialog>
|
|
239
|
+
|
|
240
|
+
<v-dialog v-model="statusDialog" max-width="728" persistent>
|
|
241
|
+
<v-card rounded="lg" class="sp-status-card">
|
|
242
|
+
<v-card-title class="sp-status-title">
|
|
243
|
+
{{ statusDialogTitle }}
|
|
244
|
+
</v-card-title>
|
|
245
|
+
|
|
246
|
+
<v-card-text class="sp-status-body">
|
|
247
|
+
<div class="sp-status-question">
|
|
248
|
+
{{ statusDialogQuestion }}
|
|
249
|
+
</div>
|
|
250
|
+
<div class="sp-status-copy">
|
|
251
|
+
{{ statusDialogCopy }}
|
|
252
|
+
</div>
|
|
253
|
+
</v-card-text>
|
|
254
|
+
|
|
255
|
+
<v-divider />
|
|
256
|
+
|
|
257
|
+
<v-card-actions class="pa-0">
|
|
258
|
+
<v-row no-gutters class="fill-height">
|
|
259
|
+
<v-col cols="6">
|
|
260
|
+
<v-btn
|
|
261
|
+
block
|
|
262
|
+
variant="flat"
|
|
263
|
+
height="82"
|
|
264
|
+
class="text-none sp-status-cancel"
|
|
265
|
+
:disabled="statusUpdating"
|
|
266
|
+
@click="closeStatusDialog"
|
|
267
|
+
>
|
|
268
|
+
Cancel
|
|
269
|
+
</v-btn>
|
|
270
|
+
</v-col>
|
|
271
|
+
<v-col cols="6">
|
|
272
|
+
<v-btn
|
|
273
|
+
block
|
|
274
|
+
variant="flat"
|
|
275
|
+
height="82"
|
|
276
|
+
class="text-none sp-status-confirm"
|
|
277
|
+
:loading="statusUpdating"
|
|
278
|
+
@click="confirmStatusChange"
|
|
279
|
+
>
|
|
280
|
+
{{ statusConfirmLabel }}
|
|
281
|
+
</v-btn>
|
|
282
|
+
</v-col>
|
|
283
|
+
</v-row>
|
|
284
|
+
</v-card-actions>
|
|
285
|
+
</v-card>
|
|
286
|
+
</v-dialog>
|
|
287
|
+
|
|
106
288
|
<v-dialog v-model="createDialog" width="500" persistent>
|
|
107
289
|
<v-card width="100%">
|
|
108
290
|
<v-toolbar>
|
|
@@ -233,27 +415,28 @@
|
|
|
233
415
|
</v-card>
|
|
234
416
|
</v-dialog>
|
|
235
417
|
|
|
236
|
-
<v-dialog v-model="createInviteDialog" width="
|
|
237
|
-
<v-card width="100%">
|
|
238
|
-
<v-toolbar>
|
|
418
|
+
<v-dialog v-model="createInviteDialog" width="680" persistent>
|
|
419
|
+
<v-card width="100%" rounded="lg" class="sp-invite-card">
|
|
420
|
+
<v-toolbar flat color="grey-lighten-4" height="76">
|
|
239
421
|
<v-row no-gutters class="fill-height px-6" align="center">
|
|
240
422
|
<span class="font-weight-bold text-h5">
|
|
241
423
|
Invite Service Provider
|
|
242
424
|
</span>
|
|
243
425
|
</v-row>
|
|
244
426
|
</v-toolbar>
|
|
245
|
-
<v-card-text
|
|
427
|
+
<v-card-text class="sp-invite-body">
|
|
246
428
|
<v-form
|
|
247
429
|
v-model="validServiceProvider"
|
|
248
430
|
:disabled="disableServiceProvider"
|
|
249
431
|
>
|
|
250
|
-
<v-row no-gutters
|
|
251
|
-
<v-col cols="12"
|
|
432
|
+
<v-row no-gutters>
|
|
433
|
+
<v-col cols="12">
|
|
252
434
|
<v-row no-gutters>
|
|
253
435
|
<InputLabel class="text-capitalize" title="Email" required />
|
|
254
436
|
<v-col cols="12">
|
|
255
437
|
<v-text-field
|
|
256
|
-
v-model="
|
|
438
|
+
v-model="serviceProviderInvite.email"
|
|
439
|
+
variant="outlined"
|
|
257
440
|
density="comfortable"
|
|
258
441
|
:rules="[requiredRule, emailRule]"
|
|
259
442
|
></v-text-field>
|
|
@@ -262,17 +445,61 @@
|
|
|
262
445
|
</v-col>
|
|
263
446
|
|
|
264
447
|
<v-col cols="12">
|
|
265
|
-
<v-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
>
|
|
270
|
-
<
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
448
|
+
<v-divider class="mb-6" />
|
|
449
|
+
</v-col>
|
|
450
|
+
|
|
451
|
+
<v-col cols="12">
|
|
452
|
+
<v-row no-gutters>
|
|
453
|
+
<InputLabel class="text-capitalize" title="App" required />
|
|
454
|
+
<v-col cols="12">
|
|
455
|
+
<v-select
|
|
456
|
+
v-model="serviceProviderInvite.app"
|
|
457
|
+
:items="serviceProviderInviteApps"
|
|
458
|
+
item-title="title"
|
|
459
|
+
item-value="value"
|
|
460
|
+
variant="outlined"
|
|
461
|
+
density="comfortable"
|
|
462
|
+
:rules="[requiredRule]"
|
|
463
|
+
@update:model-value="loadInviteRoles"
|
|
464
|
+
></v-select>
|
|
465
|
+
</v-col>
|
|
466
|
+
</v-row>
|
|
467
|
+
</v-col>
|
|
468
|
+
|
|
469
|
+
<v-col cols="12">
|
|
470
|
+
<v-row no-gutters>
|
|
471
|
+
<InputLabel class="text-capitalize" title="Site" required />
|
|
472
|
+
<v-col cols="12">
|
|
473
|
+
<v-select
|
|
474
|
+
v-model="serviceProviderInvite.siteId"
|
|
475
|
+
:items="serviceProviderInviteSites"
|
|
476
|
+
item-title="title"
|
|
477
|
+
item-value="value"
|
|
478
|
+
variant="outlined"
|
|
479
|
+
density="comfortable"
|
|
480
|
+
:rules="[requiredRule]"
|
|
481
|
+
@update:model-value="setInviteSiteName"
|
|
482
|
+
></v-select>
|
|
483
|
+
</v-col>
|
|
484
|
+
</v-row>
|
|
485
|
+
</v-col>
|
|
486
|
+
|
|
487
|
+
<v-col cols="12">
|
|
488
|
+
<v-row no-gutters>
|
|
489
|
+
<InputLabel class="text-capitalize" title="Role" required />
|
|
490
|
+
<v-col cols="12">
|
|
491
|
+
<v-select
|
|
492
|
+
v-model="serviceProviderInvite.role"
|
|
493
|
+
:items="serviceProviderInviteRoles"
|
|
494
|
+
item-title="name"
|
|
495
|
+
item-value="_id"
|
|
496
|
+
variant="outlined"
|
|
497
|
+
density="comfortable"
|
|
498
|
+
:loading="loadingInviteRoles"
|
|
499
|
+
:rules="[requiredRule]"
|
|
500
|
+
></v-select>
|
|
501
|
+
</v-col>
|
|
502
|
+
</v-row>
|
|
276
503
|
</v-col>
|
|
277
504
|
|
|
278
505
|
<v-col cols="12" class="my-2">
|
|
@@ -290,27 +517,26 @@
|
|
|
290
517
|
</v-form>
|
|
291
518
|
</v-card-text>
|
|
292
519
|
|
|
293
|
-
<v-toolbar>
|
|
294
|
-
<v-row class="
|
|
295
|
-
<v-col cols="6">
|
|
520
|
+
<v-toolbar flat height="76" class="sp-invite-footer">
|
|
521
|
+
<v-row no-gutters class="fill-height">
|
|
522
|
+
<v-col cols="6" class="fill-height">
|
|
296
523
|
<v-btn
|
|
297
524
|
block
|
|
298
|
-
variant="
|
|
299
|
-
class="text-none"
|
|
300
|
-
|
|
525
|
+
variant="flat"
|
|
526
|
+
class="text-none sp-invite-footer-btn"
|
|
527
|
+
height="76"
|
|
301
528
|
@click="setServiceProvider({ mode: 'invite', dialog: false })"
|
|
302
529
|
>
|
|
303
530
|
Cancel
|
|
304
531
|
</v-btn>
|
|
305
532
|
</v-col>
|
|
306
533
|
|
|
307
|
-
<v-col cols="6">
|
|
534
|
+
<v-col cols="6" class="fill-height">
|
|
308
535
|
<v-btn
|
|
309
536
|
block
|
|
310
537
|
variant="flat"
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
size="large"
|
|
538
|
+
class="text-none sp-invite-submit-btn"
|
|
539
|
+
height="76"
|
|
314
540
|
:disabled="!validServiceProvider"
|
|
315
541
|
:loading="disableServiceProvider"
|
|
316
542
|
@click="submitServiceProviderInvite()"
|
|
@@ -328,8 +554,29 @@
|
|
|
328
554
|
|
|
329
555
|
<script lang="ts" setup>
|
|
330
556
|
import useServiceProvider from "../composables/useServiceProvider";
|
|
557
|
+
import useVerification from "../composables/useVerification";
|
|
558
|
+
import useRole from "../composables/useRole";
|
|
331
559
|
import { errorConverter } from "../utils/data";
|
|
332
560
|
|
|
561
|
+
type ListTab = "active" | "pending" | "inactive";
|
|
562
|
+
|
|
563
|
+
type TableRow = {
|
|
564
|
+
_id: string;
|
|
565
|
+
serviceProviderOrgId: string;
|
|
566
|
+
companyName: string;
|
|
567
|
+
email: string;
|
|
568
|
+
type: string;
|
|
569
|
+
members: string;
|
|
570
|
+
status: string;
|
|
571
|
+
source: "provider" | "invite";
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
type ServiceProviderMemberRow = {
|
|
575
|
+
_id: string;
|
|
576
|
+
name: string;
|
|
577
|
+
role: string;
|
|
578
|
+
};
|
|
579
|
+
|
|
333
580
|
const props = defineProps({
|
|
334
581
|
orgId: {
|
|
335
582
|
type: String,
|
|
@@ -362,45 +609,86 @@ const props = defineProps({
|
|
|
362
609
|
},
|
|
363
610
|
canAddServiceProvider: {
|
|
364
611
|
type: Boolean,
|
|
365
|
-
default:
|
|
612
|
+
default: true,
|
|
366
613
|
},
|
|
367
614
|
canInviteServiceProvider: {
|
|
368
615
|
type: Boolean,
|
|
369
|
-
default:
|
|
616
|
+
default: true,
|
|
370
617
|
},
|
|
371
618
|
canViewServiceProviders: {
|
|
372
619
|
type: Boolean,
|
|
373
|
-
default:
|
|
620
|
+
default: true,
|
|
621
|
+
},
|
|
622
|
+
showAddButton: {
|
|
623
|
+
type: Boolean,
|
|
624
|
+
default: true,
|
|
625
|
+
},
|
|
626
|
+
showBillingButton: {
|
|
627
|
+
type: Boolean,
|
|
628
|
+
default: true,
|
|
374
629
|
},
|
|
375
630
|
});
|
|
376
631
|
|
|
377
632
|
const headers = [
|
|
378
633
|
{
|
|
379
|
-
title: "
|
|
380
|
-
value: "
|
|
634
|
+
title: "Company name",
|
|
635
|
+
value: "companyName",
|
|
636
|
+
sortable: true,
|
|
637
|
+
minWidth: "140px",
|
|
638
|
+
maxWidth: "220px",
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
title: "Email",
|
|
642
|
+
value: "email",
|
|
643
|
+
sortable: true,
|
|
644
|
+
minWidth: "180px",
|
|
645
|
+
maxWidth: "260px",
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
title: "Type",
|
|
649
|
+
value: "type",
|
|
650
|
+
sortable: true,
|
|
651
|
+
minWidth: "120px",
|
|
652
|
+
maxWidth: "180px",
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
title: "Members",
|
|
656
|
+
value: "members",
|
|
657
|
+
sortable: false,
|
|
658
|
+
width: "88px",
|
|
659
|
+
align: "start" as const,
|
|
381
660
|
},
|
|
382
661
|
{
|
|
383
662
|
title: "Status",
|
|
384
663
|
value: "status",
|
|
664
|
+
sortable: true,
|
|
665
|
+
width: "120px",
|
|
385
666
|
},
|
|
386
667
|
{
|
|
387
|
-
title: "
|
|
388
|
-
value: "
|
|
668
|
+
title: "",
|
|
669
|
+
value: "actions",
|
|
670
|
+
sortable: false,
|
|
671
|
+
align: "end" as const,
|
|
672
|
+
width: "56px",
|
|
673
|
+
minWidth: "56px",
|
|
389
674
|
},
|
|
390
675
|
];
|
|
391
676
|
|
|
392
677
|
const { natureOfBusiness } = useLocal();
|
|
393
|
-
const { requiredRule, emailRule } = useUtils();
|
|
678
|
+
const { requiredRule, emailRule, debounce } = useUtils();
|
|
394
679
|
|
|
680
|
+
const listTab = ref<ListTab>("active");
|
|
395
681
|
const page = ref(1);
|
|
396
682
|
const pages = ref(0);
|
|
397
683
|
const pageRange = ref("-- - -- of --");
|
|
684
|
+
const pageSize = 20;
|
|
398
685
|
|
|
399
686
|
const message = ref("");
|
|
400
687
|
const messageSnackbar = ref(false);
|
|
401
688
|
const messageColor = ref("");
|
|
402
689
|
|
|
403
|
-
const items = ref<
|
|
690
|
+
const items = ref<TableRow[]>([]);
|
|
691
|
+
const loading = ref(false);
|
|
404
692
|
|
|
405
693
|
const validServiceProvider = ref(false);
|
|
406
694
|
const disableServiceProvider = ref(false);
|
|
@@ -417,56 +705,348 @@ const serviceProvider = ref({
|
|
|
417
705
|
orgName: "",
|
|
418
706
|
category: "",
|
|
419
707
|
});
|
|
708
|
+
const defaultInviteApp = "property_management_agency";
|
|
709
|
+
const serviceProviderInvite = ref({
|
|
710
|
+
email: "",
|
|
711
|
+
app: defaultInviteApp,
|
|
712
|
+
siteId: props.siteId,
|
|
713
|
+
siteName: props.siteName,
|
|
714
|
+
role: "",
|
|
715
|
+
});
|
|
420
716
|
|
|
421
717
|
const {
|
|
422
718
|
getAll: getAllServiceProvider,
|
|
423
719
|
add: addServiceProvider,
|
|
424
720
|
createServiceProviderInvite,
|
|
721
|
+
updateStatus: updateServiceProviderStatus,
|
|
425
722
|
} = useServiceProvider();
|
|
723
|
+
const { getAll: getAllMembers } = useMember();
|
|
426
724
|
|
|
427
|
-
const {
|
|
725
|
+
const { getVerifications, cancelUserInvitation } = useVerification();
|
|
726
|
+
const { getRoles } = useRole();
|
|
428
727
|
|
|
429
|
-
const {
|
|
728
|
+
const { getSiteById } = useSite();
|
|
430
729
|
|
|
431
730
|
const { data: site } = await useLazyAsyncData(
|
|
432
731
|
"get-site-by-id-" + props.siteId,
|
|
433
732
|
() => getSiteById(props.siteId)
|
|
434
733
|
);
|
|
435
734
|
|
|
436
|
-
const
|
|
735
|
+
const searchText = ref("");
|
|
437
736
|
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
737
|
+
const createDialog = ref(false);
|
|
738
|
+
const createInviteDialog = ref(false);
|
|
739
|
+
const loadingInviteRoles = ref(false);
|
|
740
|
+
const serviceProviderInviteRoles = ref<Array<Record<string, any>>>([]);
|
|
741
|
+
|
|
742
|
+
const serviceProviderInviteApps = computed(() =>
|
|
743
|
+
natureOfBusiness.map((item) => ({
|
|
744
|
+
...item,
|
|
745
|
+
title:
|
|
746
|
+
item.value === "cleaning_services"
|
|
747
|
+
? "Cleaning"
|
|
748
|
+
: item.title.replace(" Services", ""),
|
|
749
|
+
}))
|
|
448
750
|
);
|
|
449
751
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
752
|
+
const serviceProviderInviteSites = computed(() => [
|
|
753
|
+
{
|
|
754
|
+
title: site.value?.name || props.siteName || props.siteId,
|
|
755
|
+
value: props.siteId,
|
|
756
|
+
},
|
|
757
|
+
]);
|
|
758
|
+
|
|
759
|
+
const viewDialog = ref(false);
|
|
760
|
+
const viewRow = ref<TableRow | null>(null);
|
|
761
|
+
const loadingMembers = ref(false);
|
|
762
|
+
const serviceProviderMembers = ref<ServiceProviderMemberRow[]>([]);
|
|
763
|
+
const memberDialogCount = computed(() =>
|
|
764
|
+
loadingMembers.value
|
|
765
|
+
? viewRow.value?.members ?? 0
|
|
766
|
+
: serviceProviderMembers.value.length
|
|
767
|
+
);
|
|
768
|
+
|
|
769
|
+
function canViewMembers(row: TableRow) {
|
|
770
|
+
return row.source === "provider";
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
const statusDialog = ref(false);
|
|
774
|
+
const statusUpdating = ref(false);
|
|
775
|
+
const statusActionRow = ref<TableRow | null>(null);
|
|
776
|
+
const statusAction = ref<"delete" | "reactivate">("delete");
|
|
777
|
+
const statusDialogTitle = computed(() =>
|
|
778
|
+
statusAction.value === "reactivate"
|
|
779
|
+
? "Reactivate Service Provider"
|
|
780
|
+
: "Delete Service Provider"
|
|
781
|
+
);
|
|
782
|
+
const statusDialogQuestion = computed(() =>
|
|
783
|
+
statusAction.value === "reactivate"
|
|
784
|
+
? "Are you sure you want to reactivate this service provider?"
|
|
785
|
+
: "Are you sure you want to delete this service provider?"
|
|
786
|
+
);
|
|
787
|
+
const statusDialogCopy = computed(() =>
|
|
788
|
+
statusAction.value === "reactivate"
|
|
789
|
+
? "This action will restore the record. The service provider will be moved to the Active tab."
|
|
790
|
+
: "This action will not permanently remove the record. The service provider will be moved to the Inactive tab."
|
|
791
|
+
);
|
|
792
|
+
const statusConfirmLabel = computed(() =>
|
|
793
|
+
statusAction.value === "reactivate" ? "Reactivate" : "Confirm"
|
|
794
|
+
);
|
|
795
|
+
|
|
796
|
+
function rowActionLabel(row: TableRow) {
|
|
797
|
+
return row.source === "provider" && listTab.value === "inactive"
|
|
798
|
+
? "Reactivate"
|
|
799
|
+
: "Delete";
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function typeDisplay(type: string, nature?: string) {
|
|
803
|
+
if (nature && String(nature).trim()) return String(nature);
|
|
804
|
+
const list = natureOfBusiness.value as Array<{ title?: string; value?: string }>;
|
|
805
|
+
const hit = list?.find((x) => x.value === type);
|
|
806
|
+
return hit?.title ?? type ?? "-";
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
function statusDisplay(raw: string, source: TableRow["source"]) {
|
|
810
|
+
if (source === "invite") return "Pending";
|
|
811
|
+
const s = (raw || "").toLowerCase();
|
|
812
|
+
if (s === "inactive") return "In-Active";
|
|
813
|
+
if (!raw) return "-";
|
|
814
|
+
return raw.charAt(0).toUpperCase() + raw.slice(1).toLowerCase();
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
function statusChipColor(statusLabel: string) {
|
|
818
|
+
const s = statusLabel.toLowerCase();
|
|
819
|
+
if (s === "active") return "success";
|
|
820
|
+
if (s === "pending") return "warning";
|
|
821
|
+
if (s === "in-active" || s === "inactive") return "default";
|
|
822
|
+
return "primary";
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
async function loadInviteRoles() {
|
|
826
|
+
loadingInviteRoles.value = true;
|
|
827
|
+
serviceProviderInvite.value.role = "";
|
|
828
|
+
try {
|
|
829
|
+
const response = await getRoles({
|
|
830
|
+
org: props.orgId,
|
|
831
|
+
type: serviceProviderInvite.value.app,
|
|
832
|
+
limit: 50,
|
|
833
|
+
});
|
|
834
|
+
serviceProviderInviteRoles.value = response?.items ?? [];
|
|
835
|
+
serviceProviderInvite.value.role =
|
|
836
|
+
serviceProviderInviteRoles.value[0]?._id ?? "";
|
|
837
|
+
} catch (error: any) {
|
|
838
|
+
serviceProviderInviteRoles.value = [];
|
|
839
|
+
showMessage(errorConverter(error), "error");
|
|
840
|
+
} finally {
|
|
841
|
+
loadingInviteRoles.value = false;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
function setInviteSiteName(siteId: string) {
|
|
846
|
+
const selectedSite = serviceProviderInviteSites.value.find(
|
|
847
|
+
(item) => item.value === siteId
|
|
848
|
+
);
|
|
849
|
+
serviceProviderInvite.value.siteName = selectedSite?.title ?? "";
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
function formatMembersCell(value: unknown): string {
|
|
853
|
+
if (value == null || value === "") return "0";
|
|
854
|
+
const n = Number(value);
|
|
855
|
+
if (!Number.isFinite(n)) return "0";
|
|
856
|
+
return String(n);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
function formatEmailCell(value: unknown): string {
|
|
860
|
+
if (value == null) return "-";
|
|
861
|
+
const s = String(value).trim();
|
|
862
|
+
return s.length ? s : "-";
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function mapProviderRows(raw: Record<string, any>[]): TableRow[] {
|
|
866
|
+
return raw.map((row) => ({
|
|
867
|
+
_id: String(row._id ?? ""),
|
|
868
|
+
serviceProviderOrgId: String(row.serviceProviderOrgId ?? ""),
|
|
869
|
+
companyName: row.name ?? "-",
|
|
870
|
+
email: formatEmailCell(row.email),
|
|
871
|
+
type: typeDisplay(row.type ?? "", row.nature),
|
|
872
|
+
members: formatMembersCell(row.members),
|
|
873
|
+
status: statusDisplay(row.status ?? "active", "provider"),
|
|
874
|
+
source: "provider",
|
|
875
|
+
}));
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
function inviteTypeLabel(t: string) {
|
|
879
|
+
const key = (t || "").toLowerCase();
|
|
880
|
+
const map: Record<string, string> = {
|
|
881
|
+
"service-provider-invite": "Service provider invite",
|
|
882
|
+
"service-provider-create-org": "Service provider (new org)",
|
|
883
|
+
};
|
|
884
|
+
return map[key] ?? (t ? t.replace(/-/g, " ") : "-");
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
function mapInviteRows(raw: Record<string, any>[]): TableRow[] {
|
|
888
|
+
return raw.map((row) => ({
|
|
889
|
+
_id: String(row._id ?? ""),
|
|
890
|
+
serviceProviderOrgId: String(row.metadata?.serviceProviderOrgId ?? ""),
|
|
891
|
+
companyName: row.metadata?.name || "-",
|
|
892
|
+
email: formatEmailCell(row.email),
|
|
893
|
+
type: row.metadata?.app
|
|
894
|
+
? typeDisplay(row.metadata.app)
|
|
895
|
+
: inviteTypeLabel(row.type ?? ""),
|
|
896
|
+
members: "-",
|
|
897
|
+
status: "Pending",
|
|
898
|
+
source: "invite",
|
|
899
|
+
}));
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
async function loadList() {
|
|
903
|
+
if (!props.siteId || !props.canViewServiceProviders) {
|
|
904
|
+
items.value = [];
|
|
905
|
+
pages.value = 0;
|
|
906
|
+
pageRange.value = "-- - -- of --";
|
|
907
|
+
return;
|
|
456
908
|
}
|
|
457
|
-
|
|
909
|
+
|
|
910
|
+
loading.value = true;
|
|
911
|
+
try {
|
|
912
|
+
if (listTab.value === "pending") {
|
|
913
|
+
const data = await getVerifications({
|
|
914
|
+
status: "pending",
|
|
915
|
+
type: "service-provider-invite,service-provider-create-org",
|
|
916
|
+
page: page.value,
|
|
917
|
+
search: searchText.value?.trim() || "",
|
|
918
|
+
siteId: props.siteId,
|
|
919
|
+
orgId: props.orgId,
|
|
920
|
+
limit: pageSize,
|
|
921
|
+
});
|
|
922
|
+
items.value = mapInviteRows(data.items ?? []);
|
|
923
|
+
pages.value = data.pages ?? 0;
|
|
924
|
+
pageRange.value = data.pageRange ?? "-- - -- of --";
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
const statusParam = listTab.value === "active" ? "active" : "inactive";
|
|
929
|
+
const data = await getAllServiceProvider({
|
|
930
|
+
page: page.value,
|
|
931
|
+
siteId: props.siteId,
|
|
932
|
+
search: searchText.value?.trim() || "",
|
|
933
|
+
limit: pageSize,
|
|
934
|
+
status: statusParam,
|
|
935
|
+
});
|
|
936
|
+
items.value = mapProviderRows(data.items ?? []);
|
|
937
|
+
pages.value = data.pages ?? 0;
|
|
938
|
+
pageRange.value = data.pageRange ?? "-- - -- of --";
|
|
939
|
+
} catch (error: any) {
|
|
940
|
+
showMessage(errorConverter(error), "error");
|
|
941
|
+
items.value = [];
|
|
942
|
+
pages.value = 0;
|
|
943
|
+
pageRange.value = "-- - -- of --";
|
|
944
|
+
} finally {
|
|
945
|
+
loading.value = false;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
async function openView(row: TableRow) {
|
|
950
|
+
viewRow.value = row;
|
|
951
|
+
serviceProviderMembers.value = [];
|
|
952
|
+
viewDialog.value = true;
|
|
953
|
+
|
|
954
|
+
if (!row.serviceProviderOrgId) return;
|
|
955
|
+
|
|
956
|
+
loadingMembers.value = true;
|
|
957
|
+
try {
|
|
958
|
+
const data = await getAllMembers({
|
|
959
|
+
page: 1,
|
|
960
|
+
limit: 1000,
|
|
961
|
+
org: row.serviceProviderOrgId,
|
|
962
|
+
status: "active",
|
|
963
|
+
});
|
|
964
|
+
serviceProviderMembers.value = (data.items ?? []).map((member: any) => ({
|
|
965
|
+
_id: String(member._id ?? ""),
|
|
966
|
+
name: member.name || member.fullName || member.email || "-",
|
|
967
|
+
role: member.roleName || member.role?.name || "-",
|
|
968
|
+
}));
|
|
969
|
+
} catch (error: any) {
|
|
970
|
+
showMessage(errorConverter(error), "error");
|
|
971
|
+
} finally {
|
|
972
|
+
loadingMembers.value = false;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
async function onDeleteRow(row: TableRow) {
|
|
977
|
+
if (row.source === "invite") {
|
|
978
|
+
const ok = confirm("Cancel this invitation?");
|
|
979
|
+
if (!ok) return;
|
|
980
|
+
try {
|
|
981
|
+
await cancelUserInvitation(row._id);
|
|
982
|
+
showMessage("Invitation cancelled.", "success");
|
|
983
|
+
await loadList();
|
|
984
|
+
} catch (error: any) {
|
|
985
|
+
showMessage(errorConverter(error), "error");
|
|
986
|
+
}
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
statusActionRow.value = row;
|
|
991
|
+
statusAction.value = listTab.value === "inactive" ? "reactivate" : "delete";
|
|
992
|
+
statusDialog.value = true;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
function closeStatusDialog() {
|
|
996
|
+
if (statusUpdating.value) return;
|
|
997
|
+
statusDialog.value = false;
|
|
998
|
+
statusActionRow.value = null;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
async function confirmStatusChange() {
|
|
1002
|
+
if (!statusActionRow.value) return;
|
|
1003
|
+
|
|
1004
|
+
statusUpdating.value = true;
|
|
1005
|
+
const nextStatus = statusAction.value === "reactivate" ? "active" : "inactive";
|
|
1006
|
+
try {
|
|
1007
|
+
await updateServiceProviderStatus(statusActionRow.value._id, nextStatus);
|
|
1008
|
+
showMessage(
|
|
1009
|
+
statusAction.value === "reactivate"
|
|
1010
|
+
? "Service provider reactivated."
|
|
1011
|
+
: "Service provider moved to In-Active.",
|
|
1012
|
+
"success"
|
|
1013
|
+
);
|
|
1014
|
+
statusDialog.value = false;
|
|
1015
|
+
statusActionRow.value = null;
|
|
1016
|
+
listTab.value = nextStatus === "active" ? "active" : "inactive";
|
|
1017
|
+
page.value = 1;
|
|
1018
|
+
await loadList();
|
|
1019
|
+
} catch (error: any) {
|
|
1020
|
+
showMessage(errorConverter(error), "error");
|
|
1021
|
+
} finally {
|
|
1022
|
+
statusUpdating.value = false;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
watch(listTab, () => {
|
|
1027
|
+
page.value = 1;
|
|
1028
|
+
loadList();
|
|
458
1029
|
});
|
|
459
1030
|
|
|
460
|
-
|
|
461
|
-
|
|
1031
|
+
watch(page, () => {
|
|
1032
|
+
loadList();
|
|
1033
|
+
});
|
|
462
1034
|
|
|
463
|
-
const
|
|
1035
|
+
const debouncedSearch = debounce(() => {
|
|
1036
|
+
page.value = 1;
|
|
1037
|
+
loadList();
|
|
1038
|
+
}, 500);
|
|
464
1039
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
1040
|
+
watch(
|
|
1041
|
+
() => searchText.value,
|
|
1042
|
+
() => {
|
|
1043
|
+
debouncedSearch();
|
|
1044
|
+
}
|
|
1045
|
+
);
|
|
1046
|
+
|
|
1047
|
+
onMounted(() => {
|
|
1048
|
+
loadList();
|
|
1049
|
+
});
|
|
470
1050
|
|
|
471
1051
|
function showMessage(msg: string, color: string) {
|
|
472
1052
|
message.value = msg;
|
|
@@ -474,25 +1054,16 @@ function showMessage(msg: string, color: string) {
|
|
|
474
1054
|
messageSnackbar.value = true;
|
|
475
1055
|
}
|
|
476
1056
|
|
|
477
|
-
function onNotify(payload: { message: string; color: string }) {
|
|
478
|
-
showMessage(payload.message, payload.color);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
const dialogServiceProviderInvite = ref(false);
|
|
482
|
-
const dialogServiceProviderAdd = ref(false);
|
|
483
|
-
|
|
484
1057
|
function setServiceProvider({
|
|
485
1058
|
mode = "invite",
|
|
486
1059
|
dialog = true,
|
|
487
1060
|
data = {} as Record<string, any>,
|
|
488
1061
|
} = {}) {
|
|
489
1062
|
if (mode === "invite") {
|
|
490
|
-
// dialogServiceProviderInvite.value = dialog;
|
|
491
1063
|
createInviteDialog.value = dialog;
|
|
492
1064
|
}
|
|
493
1065
|
|
|
494
1066
|
if (mode === "add") {
|
|
495
|
-
// dialogServiceProviderAdd.value = dialog;
|
|
496
1067
|
createDialog.value = dialog;
|
|
497
1068
|
}
|
|
498
1069
|
|
|
@@ -508,6 +1079,18 @@ function setServiceProvider({
|
|
|
508
1079
|
orgName: "Org Name",
|
|
509
1080
|
category: mode === "add" ? "internal" : "external",
|
|
510
1081
|
};
|
|
1082
|
+
|
|
1083
|
+
if (mode === "invite") {
|
|
1084
|
+
serviceProviderInvite.value = {
|
|
1085
|
+
email: "",
|
|
1086
|
+
app: defaultInviteApp,
|
|
1087
|
+
siteId: props.siteId,
|
|
1088
|
+
siteName: site.value?.name || props.siteName,
|
|
1089
|
+
role: "",
|
|
1090
|
+
};
|
|
1091
|
+
createMoreServiceProvider.value = false;
|
|
1092
|
+
void loadInviteRoles();
|
|
1093
|
+
}
|
|
511
1094
|
return;
|
|
512
1095
|
}
|
|
513
1096
|
|
|
@@ -522,11 +1105,9 @@ async function submitServiceProviderAdd() {
|
|
|
522
1105
|
messageServiceProvider.value = "";
|
|
523
1106
|
|
|
524
1107
|
try {
|
|
525
|
-
console.log("serviceProvider.value");
|
|
526
|
-
console.log(serviceProvider.value);
|
|
527
1108
|
const result = await addServiceProvider(serviceProvider.value);
|
|
528
1109
|
await setServiceProvider({ mode: "add", dialog: false });
|
|
529
|
-
await
|
|
1110
|
+
await loadList();
|
|
530
1111
|
|
|
531
1112
|
if (result?.id) {
|
|
532
1113
|
showMessage(result?.message, "success");
|
|
@@ -546,33 +1127,195 @@ async function submitServiceProviderInvite() {
|
|
|
546
1127
|
messageServiceProvider.value = "";
|
|
547
1128
|
try {
|
|
548
1129
|
const payload = {
|
|
549
|
-
email:
|
|
1130
|
+
email: serviceProviderInvite.value.email.trim(),
|
|
1131
|
+
name: "",
|
|
1132
|
+
app: serviceProviderInvite.value.app,
|
|
1133
|
+
role: serviceProviderInvite.value.role,
|
|
550
1134
|
orgId: props.orgId,
|
|
551
|
-
siteId:
|
|
552
|
-
siteName:
|
|
1135
|
+
siteId: serviceProviderInvite.value.siteId,
|
|
1136
|
+
siteName:
|
|
1137
|
+
serviceProviderInvite.value.siteName || site.value?.name || props.siteName,
|
|
553
1138
|
};
|
|
554
1139
|
|
|
555
1140
|
await createServiceProviderInvite(payload);
|
|
1141
|
+
showMessage("Invitation sent.", "success");
|
|
556
1142
|
if (createMoreServiceProvider.value) {
|
|
557
|
-
|
|
1143
|
+
serviceProviderInvite.value.email = "";
|
|
558
1144
|
} else {
|
|
559
1145
|
await setServiceProvider({ mode: "invite", dialog: false });
|
|
560
1146
|
}
|
|
1147
|
+
await loadList();
|
|
561
1148
|
} catch (error: any) {
|
|
562
1149
|
messageServiceProvider.value =
|
|
563
1150
|
error?.response?._data?.message ??
|
|
564
1151
|
"An error occurred while inviting the service provider.";
|
|
1152
|
+
showMessage(errorConverter(error), "error");
|
|
565
1153
|
} finally {
|
|
566
1154
|
disableServiceProvider.value = false;
|
|
567
1155
|
}
|
|
568
1156
|
}
|
|
1157
|
+
</script>
|
|
569
1158
|
|
|
570
|
-
|
|
1159
|
+
<style scoped>
|
|
1160
|
+
.sp-toolbar-top {
|
|
1161
|
+
display: flex;
|
|
1162
|
+
align-items: center;
|
|
1163
|
+
flex-wrap: nowrap;
|
|
1164
|
+
gap: 4px;
|
|
1165
|
+
}
|
|
571
1166
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
(
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
1167
|
+
.sp-table-header {
|
|
1168
|
+
background: #f5f5f5;
|
|
1169
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
.sp-tabs {
|
|
1173
|
+
width: 100%;
|
|
1174
|
+
min-height: 40px;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
.sp-tabs :deep(.v-tab) {
|
|
1178
|
+
min-width: 120px;
|
|
1179
|
+
justify-content: flex-start;
|
|
1180
|
+
text-transform: none;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
.sp-col-company {
|
|
1184
|
+
max-width: 220px;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
.sp-col-email {
|
|
1188
|
+
max-width: 260px;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
.sp-col-type {
|
|
1192
|
+
max-width: 180px;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
.sp-table :deep(thead th) {
|
|
1196
|
+
font-weight: 600;
|
|
1197
|
+
font-size: 0.8125rem;
|
|
1198
|
+
color: rgba(0, 0, 0, 0.7);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
.sp-table :deep(tbody td) {
|
|
1202
|
+
vertical-align: middle;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
.sp-invite-card {
|
|
1206
|
+
overflow: hidden;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
.sp-invite-body {
|
|
1210
|
+
max-height: 100vh;
|
|
1211
|
+
overflow-y: auto;
|
|
1212
|
+
padding: 48px 44px 34px;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
.sp-invite-body :deep(.v-field) {
|
|
1216
|
+
border-radius: 6px;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
.sp-invite-body :deep(.v-field__input) {
|
|
1220
|
+
min-height: 64px;
|
|
1221
|
+
font-size: 1.25rem;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
.sp-invite-footer {
|
|
1225
|
+
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
.sp-invite-footer-btn {
|
|
1229
|
+
border-radius: 0;
|
|
1230
|
+
background: #ffffff !important;
|
|
1231
|
+
color: #111827 !important;
|
|
1232
|
+
font-size: 1.25rem;
|
|
1233
|
+
font-weight: 700;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
.sp-invite-submit-btn {
|
|
1237
|
+
border-radius: 0;
|
|
1238
|
+
background: #0b253b !important;
|
|
1239
|
+
color: #ffffff !important;
|
|
1240
|
+
font-size: 1.25rem;
|
|
1241
|
+
font-weight: 700;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
.sp-members-card {
|
|
1245
|
+
overflow: hidden;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
.sp-members-title {
|
|
1249
|
+
min-height: 56px;
|
|
1250
|
+
display: flex;
|
|
1251
|
+
align-items: center;
|
|
1252
|
+
padding: 0 16px;
|
|
1253
|
+
font-size: 1.25rem;
|
|
1254
|
+
font-weight: 700;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
.sp-members-table {
|
|
1258
|
+
max-height: 444px;
|
|
1259
|
+
overflow-y: auto;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
.sp-members-table :deep(th) {
|
|
1263
|
+
height: 64px;
|
|
1264
|
+
color: #667085;
|
|
1265
|
+
font-size: 1rem;
|
|
1266
|
+
font-weight: 500;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
.sp-members-table :deep(td) {
|
|
1270
|
+
height: 64px;
|
|
1271
|
+
color: #667085;
|
|
1272
|
+
font-size: 1rem;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
.sp-status-card {
|
|
1276
|
+
overflow: hidden;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
.sp-status-title {
|
|
1280
|
+
min-height: 82px;
|
|
1281
|
+
display: flex;
|
|
1282
|
+
align-items: center;
|
|
1283
|
+
padding: 0 24px;
|
|
1284
|
+
background: #f5f5f5;
|
|
1285
|
+
color: #101828;
|
|
1286
|
+
font-size: 1.75rem;
|
|
1287
|
+
font-weight: 700;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
.sp-status-body {
|
|
1291
|
+
padding: 44px 46px 42px;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
.sp-status-question {
|
|
1295
|
+
color: #101828;
|
|
1296
|
+
font-size: 1.5rem;
|
|
1297
|
+
font-weight: 700;
|
|
1298
|
+
line-height: 1.35;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
.sp-status-copy {
|
|
1302
|
+
margin-top: 28px;
|
|
1303
|
+
color: #667085;
|
|
1304
|
+
font-size: 1.5rem;
|
|
1305
|
+
line-height: 1.2;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
.sp-status-cancel {
|
|
1309
|
+
color: #101828;
|
|
1310
|
+
background: #ffffff;
|
|
1311
|
+
font-size: 1.5rem;
|
|
1312
|
+
font-weight: 700;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
.sp-status-confirm {
|
|
1316
|
+
color: #ffffff;
|
|
1317
|
+
background: #00263a;
|
|
1318
|
+
font-size: 1.5rem;
|
|
1319
|
+
font-weight: 700;
|
|
1320
|
+
}
|
|
1321
|
+
</style>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
:class="['ma-1', isSelected && 'selected']"
|
|
15
15
|
width="150"
|
|
16
16
|
height="100"
|
|
17
|
-
@click="clickable && emit('onClickCarousel', data
|
|
17
|
+
@click="clickable && emit('onClickCarousel', data)"
|
|
18
18
|
class="rounded-lg border-thin"
|
|
19
19
|
border=" opacity-50 thin "
|
|
20
20
|
>
|
|
@@ -57,10 +57,19 @@ export default function useServiceProvider() {
|
|
|
57
57
|
serviceProviderOrgId = "",
|
|
58
58
|
orgId = "",
|
|
59
59
|
siteId = "",
|
|
60
|
+
status = "",
|
|
60
61
|
} = {}) {
|
|
61
62
|
return useNuxtApp().$api<Record<string, any>>("/api/service-providers", {
|
|
62
63
|
method: "GET",
|
|
63
|
-
query: {
|
|
64
|
+
query: {
|
|
65
|
+
page,
|
|
66
|
+
search,
|
|
67
|
+
limit,
|
|
68
|
+
serviceProviderOrgId,
|
|
69
|
+
orgId,
|
|
70
|
+
siteId,
|
|
71
|
+
...(status ? { status } : {}),
|
|
72
|
+
},
|
|
64
73
|
});
|
|
65
74
|
}
|
|
66
75
|
|
|
@@ -128,32 +137,36 @@ export default function useServiceProvider() {
|
|
|
128
137
|
|
|
129
138
|
async function createServiceProviderInvite({
|
|
130
139
|
email,
|
|
140
|
+
name = "",
|
|
141
|
+
app = "",
|
|
142
|
+
role = "",
|
|
131
143
|
orgId,
|
|
132
144
|
siteId,
|
|
133
145
|
siteName,
|
|
134
146
|
}: {
|
|
135
147
|
email: string;
|
|
148
|
+
name?: string;
|
|
149
|
+
app?: string;
|
|
150
|
+
role?: string;
|
|
136
151
|
orgId: string;
|
|
137
152
|
siteId: string;
|
|
138
153
|
siteName: string;
|
|
139
154
|
}) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
console.error("Error creating service provider invite:", err);
|
|
156
|
-
}
|
|
155
|
+
return useNuxtApp().$api<Record<string, any>>(
|
|
156
|
+
"/api/auth/invite/service-provider/with-org",
|
|
157
|
+
{
|
|
158
|
+
method: "POST",
|
|
159
|
+
body: {
|
|
160
|
+
email,
|
|
161
|
+
name,
|
|
162
|
+
app,
|
|
163
|
+
role,
|
|
164
|
+
orgId,
|
|
165
|
+
siteId,
|
|
166
|
+
siteName,
|
|
167
|
+
},
|
|
168
|
+
}
|
|
169
|
+
);
|
|
157
170
|
}
|
|
158
171
|
|
|
159
172
|
async function invite({
|
|
@@ -211,6 +224,16 @@ export default function useServiceProvider() {
|
|
|
211
224
|
);
|
|
212
225
|
}
|
|
213
226
|
|
|
227
|
+
async function updateStatus(id: string, status: "active" | "inactive") {
|
|
228
|
+
return useNuxtApp().$api<Record<string, any>>(
|
|
229
|
+
`/api/service-providers/${id}/status`,
|
|
230
|
+
{
|
|
231
|
+
method: "PATCH",
|
|
232
|
+
body: { status },
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
214
237
|
return {
|
|
215
238
|
serviceProviders,
|
|
216
239
|
serviceProvider,
|
|
@@ -228,5 +251,6 @@ export default function useServiceProvider() {
|
|
|
228
251
|
invite,
|
|
229
252
|
add,
|
|
230
253
|
addViaInvite,
|
|
254
|
+
updateStatus,
|
|
231
255
|
};
|
|
232
256
|
}
|
|
@@ -5,7 +5,10 @@ export default function useVerification() {
|
|
|
5
5
|
search = "",
|
|
6
6
|
page = 1,
|
|
7
7
|
email = "",
|
|
8
|
-
app = ""
|
|
8
|
+
app = "",
|
|
9
|
+
siteId = "",
|
|
10
|
+
orgId = "",
|
|
11
|
+
limit = 20,
|
|
9
12
|
} = {}): Promise<{
|
|
10
13
|
items: TMiniVerification[];
|
|
11
14
|
pages: number;
|
|
@@ -13,7 +16,7 @@ export default function useVerification() {
|
|
|
13
16
|
}> {
|
|
14
17
|
return useNuxtApp().$api("/api/verifications", {
|
|
15
18
|
method: "GET",
|
|
16
|
-
query: { status, search, page, type, email, app },
|
|
19
|
+
query: { status, search, page, type, email, app, siteId, orgId, limit },
|
|
17
20
|
});
|
|
18
21
|
}
|
|
19
22
|
|