@iservice365/layer-common 0.0.6 → 0.2.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.
Files changed (91) hide show
  1. package/.playground/app.vue +7 -2
  2. package/.playground/pages/feedback.vue +30 -0
  3. package/CHANGELOG.md +12 -0
  4. package/components/Chat/Bubbles.vue +53 -0
  5. package/components/Chat/Information.vue +187 -0
  6. package/components/Chat/ListCard.vue +62 -0
  7. package/components/Chat/Message.vue +149 -0
  8. package/components/Chat/Navigation.vue +150 -0
  9. package/components/ConfirmDialog.vue +66 -0
  10. package/components/Container/Standard.vue +33 -0
  11. package/components/Feedback/Form.vue +136 -0
  12. package/components/FeedbackDetail.vue +465 -0
  13. package/components/FeedbackMain.vue +454 -0
  14. package/components/FormDialog.vue +65 -0
  15. package/components/Input/File.vue +203 -0
  16. package/components/Input/ListGroupSelection.vue +96 -0
  17. package/components/Input/NewDate.vue +123 -0
  18. package/components/Input/Number.vue +124 -0
  19. package/components/InvitationMain.vue +284 -0
  20. package/components/Layout/Header.vue +28 -4
  21. package/components/ListView.vue +87 -0
  22. package/components/MemberMain.vue +459 -0
  23. package/components/RolePermissionFormCreate.vue +161 -0
  24. package/components/RolePermissionFormPreviewUpdate.vue +183 -0
  25. package/components/RolePermissionMain.vue +361 -0
  26. package/components/ServiceProviderFormCreate.vue +154 -0
  27. package/components/ServiceProviderMain.vue +195 -0
  28. package/components/SignaturePad.vue +73 -0
  29. package/components/SpecificAttr.vue +53 -0
  30. package/components/SwitchContext.vue +26 -5
  31. package/components/TableList.vue +150 -0
  32. package/components/TableListSecondary.vue +164 -0
  33. package/components/WorkOrder/Create.vue +197 -0
  34. package/components/WorkOrder/ListView.vue +96 -0
  35. package/components/WorkOrder/Main.vue +308 -0
  36. package/components/Workorder.vue +1 -0
  37. package/composables/useAddress.ts +107 -0
  38. package/composables/useCommonPermission.ts +130 -0
  39. package/composables/useCustomer.ts +113 -0
  40. package/composables/useFeedback.ts +117 -0
  41. package/composables/useFile.ts +40 -0
  42. package/composables/useInvoice.ts +18 -0
  43. package/composables/useLocal.ts +24 -4
  44. package/composables/useLocalAuth.ts +58 -14
  45. package/composables/useLocalSetup.ts +52 -0
  46. package/composables/useMember.ts +104 -0
  47. package/composables/useOrg.ts +76 -92
  48. package/composables/usePaymentMethod.ts +101 -0
  49. package/composables/usePrice.ts +15 -0
  50. package/composables/usePromoCode.ts +36 -0
  51. package/composables/useRole.ts +38 -7
  52. package/composables/useServiceProvider.ts +218 -0
  53. package/composables/useSite.ts +108 -0
  54. package/composables/useSubscription.ts +149 -0
  55. package/composables/useUser.ts +38 -14
  56. package/composables/useUtils.ts +218 -6
  57. package/composables/useVerification.ts +33 -0
  58. package/composables/useWorkOrder.ts +68 -0
  59. package/middleware/01.auth.ts +11 -0
  60. package/middleware/02.org.ts +18 -0
  61. package/middleware/03.customer.ts +13 -0
  62. package/nuxt.config.ts +2 -1
  63. package/package.json +7 -3
  64. package/pages/index.vue +3 -0
  65. package/pages/payment-method-linked.vue +31 -0
  66. package/pages/require-customer.vue +56 -0
  67. package/pages/require-organization-membership.vue +47 -0
  68. package/pages/unauthorized.vue +29 -0
  69. package/plugins/API.ts +1 -3
  70. package/plugins/iconify.client.ts +5 -0
  71. package/plugins/vuetify.ts +2 -0
  72. package/public/bg-camera.jpg +0 -0
  73. package/public/bg-city.jpg +0 -0
  74. package/public/bg-condo.jpg +0 -0
  75. package/public/images/icons/delete-icon.png +0 -0
  76. package/public/sprite.svg +1 -0
  77. package/types/address.d.ts +13 -0
  78. package/types/customer.d.ts +15 -0
  79. package/types/feedback.d.ts +63 -0
  80. package/types/local.d.ts +46 -38
  81. package/types/member.d.ts +21 -0
  82. package/types/org.d.ts +13 -0
  83. package/types/permission.d.ts +1 -0
  84. package/types/price.d.ts +17 -0
  85. package/types/promo-code.d.ts +19 -0
  86. package/types/service-provider.d.ts +15 -0
  87. package/types/site.d.ts +13 -0
  88. package/types/subscription.d.ts +23 -0
  89. package/types/user.d.ts +19 -0
  90. package/types/verification.d.ts +20 -0
  91. package/types/work-order.d.ts +40 -0
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <TableListSecondary
3
+ :headers="headers"
4
+ :items="items"
5
+ :pages="pages"
6
+ :page-range="pageRange"
7
+ :loading="loading"
8
+ :height="height"
9
+ :page="page"
10
+ v-model="selected"
11
+ @update:pagination="_getItems"
12
+ @click:row="onRowClick"
13
+ :length="pages"
14
+ :clickable-rows="clickableRows"
15
+ @update:page="onPageChange"
16
+ >
17
+ <template #title>
18
+ <slot name="title" />
19
+ </template>
20
+
21
+ <template #action-button>
22
+ <slot name="action-button" />
23
+ </template>
24
+
25
+ <template
26
+ v-for="header in headers"
27
+ :key="header.value"
28
+ #[header.value]="slotProps"
29
+ >
30
+ <slot :name="header.value" v-bind="slotProps" />
31
+ </template>
32
+
33
+ <template #action-table="{ item }">
34
+ <slot name="action-table" :item="item" />
35
+ </template>
36
+ </TableListSecondary>
37
+ </template>
38
+
39
+ <script lang="ts" setup>
40
+ import { getCurrentInstance } from "vue";
41
+ import { useRoute, useRouter } from "vue-router";
42
+
43
+ const emit = defineEmits(["click:create", "update:pagination", "row-click"]);
44
+ const page = defineModel("page", { type: Number, default: 1 });
45
+
46
+ const props = defineProps({
47
+ headers: Array as PropType<any[]>,
48
+ items: Array as PropType<any[]>,
49
+ pages: Number,
50
+ pageRange: String,
51
+ page: Number,
52
+ loading: Boolean,
53
+ height: {
54
+ type: String,
55
+ default: "calc(100vh - 175px)",
56
+ },
57
+ viewPage: Object as PropType<{ name: string }>,
58
+ org: String,
59
+ site: String,
60
+ id: String,
61
+ getItems: Function as PropType<() => Promise<void>>,
62
+ deleteItem: Function as PropType<(id: string) => Promise<void>>,
63
+ clickableRows: {
64
+ type: Boolean,
65
+ default: false,
66
+ },
67
+ });
68
+
69
+ const selected = ref<string[]>([]);
70
+
71
+ async function _getItems() {
72
+ if (props.getItems) {
73
+ await props.getItems();
74
+ emit("update:pagination");
75
+ }
76
+ }
77
+
78
+ function onPageChange(newPage: number) {
79
+ page.value = newPage;
80
+ _getItems();
81
+ emit("update:pagination", newPage);
82
+ }
83
+
84
+ function onRowClick(item: any) {
85
+ emit("row-click", item);
86
+ }
87
+ </script>
@@ -0,0 +1,459 @@
1
+ <template>
2
+ <v-row no-gutters>
3
+ <v-col cols="12" class="mb-2">
4
+ <v-row no-gutters>
5
+ <v-btn
6
+ v-if="props.seatManagement !== 'index'"
7
+ class="text-none"
8
+ rounded="pill"
9
+ variant="tonal"
10
+ :to="{
11
+ name: props.seatManagement,
12
+ params: { organization: props.orgId },
13
+ }"
14
+ size="large"
15
+ >
16
+ Manage seats
17
+ </v-btn>
18
+ </v-row>
19
+ </v-col>
20
+
21
+ <v-col cols="12">
22
+ <v-card width="100%" variant="outlined" border="thin" rounded="lg">
23
+ <v-toolbar density="compact" color="grey-lighten-4">
24
+ <template #prepend>
25
+ <v-btn fab icon density="comfortable" @click="getAll()">
26
+ <v-icon>mdi-refresh</v-icon>
27
+ </v-btn>
28
+ </template>
29
+
30
+ <template #append>
31
+ <v-row no-gutters justify="end" align="center">
32
+ <span class="mr-2 text-caption text-font gray">
33
+ {{ pageRange }}
34
+ </span>
35
+ <local-pagination
36
+ v-model="page"
37
+ :length="pages"
38
+ @update:value="getAll()"
39
+ />
40
+ </v-row>
41
+ </template>
42
+
43
+ <template #extension>
44
+ <v-tabs>
45
+ <v-tab
46
+ v-for="tab in [
47
+ { name: 'Active', status: 'active' },
48
+ { name: 'Suspended', status: 'suspended' },
49
+ ]"
50
+ :key="tab.status"
51
+ :to="{
52
+ name: props.route,
53
+ params: setRouteParams({
54
+ status: tab.status,
55
+ orgId: props.orgId,
56
+ }),
57
+ }"
58
+ >
59
+ {{ tab.name }}
60
+ </v-tab>
61
+ </v-tabs>
62
+ </template>
63
+ </v-toolbar>
64
+
65
+ <v-data-table
66
+ :headers="props.headers"
67
+ :items="items"
68
+ item-value="_id"
69
+ items-per-page="20"
70
+ fixed-header
71
+ hide-default-footer
72
+ style="max-height: calc(100vh - (126px))"
73
+ :loading="loading"
74
+ >
75
+ <template #item.nature="{ item }">
76
+ {{ replaceMatch(item.nature, "_", " ") }}
77
+ </template>
78
+ <template #item.action-table="{ item }">
79
+ <v-menu
80
+ v-if="
81
+ (status === 'active' &&
82
+ (canSuspendMembers || canDeleteMembers)) ||
83
+ (status === 'suspended' &&
84
+ (canActivateMembers || canDeleteMembers))
85
+ "
86
+ v-model="item.menuOpen"
87
+ :close-on-content-click="false"
88
+ offset-y
89
+ width="150"
90
+ >
91
+ <template v-slot:activator="{ props }">
92
+ <v-icon v-bind="props">mdi-dots-horizontal</v-icon>
93
+ </template>
94
+ <v-list>
95
+ <v-list-item
96
+ v-if="props.assignRole"
97
+ @click="
98
+ setMember({
99
+ dialog: true,
100
+ mode: 'assign-role',
101
+ role: item,
102
+ })
103
+ "
104
+ >
105
+ Assign Role
106
+ </v-list-item>
107
+
108
+ <v-list-item
109
+ v-if="status === 'active' && canSuspendMembers"
110
+ @click="openUpdateDialog(item._id, 'suspended')"
111
+ >
112
+ Suspend
113
+ </v-list-item>
114
+ <v-list-item
115
+ v-if="status === 'suspended' && canActivateMembers"
116
+ @click="openUpdateDialog(item._id, 'active')"
117
+ >
118
+ Activate
119
+ </v-list-item>
120
+ <v-list-item
121
+ v-if="canDeleteMembers"
122
+ @click="openUpdateDialog(item._id, 'deleted')"
123
+ >
124
+ Delete
125
+ </v-list-item>
126
+ </v-list>
127
+ </v-menu>
128
+ </template>
129
+ </v-data-table>
130
+ </v-card>
131
+ </v-col>
132
+ <ConfirmDialog
133
+ v-model="confirmDialog"
134
+ :loading="updateLoading"
135
+ @submit="handleUpdateMemberStatus"
136
+ >
137
+ <template #title>
138
+ <span class="font-weight-medium text-h5">
139
+ {{ updateActionText }} Member</span
140
+ >
141
+ </template>
142
+
143
+ <template #description>
144
+ <p class="text-subtitle-2">
145
+ Are you sure you want to {{ updateActionText }} this Member? This
146
+ action cannot be undone.
147
+ </p>
148
+ </template>
149
+
150
+ <template #footer>
151
+ <v-btn
152
+ variant="text"
153
+ @click="confirmDialog = false"
154
+ :disabled="updateLoading"
155
+ >
156
+ Close
157
+ </v-btn>
158
+ <v-btn
159
+ color="primary"
160
+ variant="flat"
161
+ @click="handleUpdateMemberStatus"
162
+ :loading="updateLoading"
163
+ >
164
+ {{ updateActionText }} Member
165
+ </v-btn>
166
+ </template>
167
+ </ConfirmDialog>
168
+
169
+ <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
170
+
171
+ <v-dialog v-model="assignRoleDialog" max-width="400px">
172
+ <v-card>
173
+ <v-card-title class="text-h5">Assign Role</v-card-title>
174
+ <v-card-text>
175
+ <v-form v-model="memberRoleForm" @submit.prevent="updateMemberRole()">
176
+ <v-row no-gutters>
177
+ <v-col cols="12" class="mb-2">
178
+ <v-row no-gutters>
179
+ <InputLabel class="text-capitalize" title="Name" required />
180
+ <v-col cols="12">
181
+ <v-select
182
+ v-model="selectedRole"
183
+ :items="roles"
184
+ item-value="_id"
185
+ item-title="name"
186
+ density="comfortable"
187
+ :rules="[requiredRule]"
188
+ :error-messages="
189
+ selectedRole === selectedMemberRole
190
+ ? 'Role already assigned'
191
+ : ''
192
+ "
193
+ persistent-hint
194
+ ></v-select>
195
+ </v-col>
196
+
197
+ <v-col cols="12" class="text-error text-center">
198
+ {{ message }}
199
+ </v-col>
200
+ </v-row>
201
+ </v-col>
202
+
203
+ <v-col cols="12">
204
+ <v-row>
205
+ <v-col cols="6">
206
+ <v-btn
207
+ block
208
+ variant="text"
209
+ @click="setMember({ mode: 'assign-role' })"
210
+ >
211
+ Cancel
212
+ </v-btn>
213
+ </v-col>
214
+ <v-col cols="6">
215
+ <v-btn
216
+ block
217
+ variant="flat"
218
+ color="black"
219
+ :disabled="!memberRoleForm"
220
+ type="submit"
221
+ >
222
+ Submit
223
+ </v-btn>
224
+ </v-col>
225
+ </v-row>
226
+ </v-col>
227
+ </v-row>
228
+ </v-form>
229
+ </v-card-text>
230
+ </v-card>
231
+ </v-dialog>
232
+ </v-row>
233
+ </template>
234
+
235
+ <script setup lang="ts">
236
+ const props = defineProps({
237
+ orgId: {
238
+ type: String,
239
+ default: "",
240
+ },
241
+ customerId: {
242
+ type: String,
243
+ default: "",
244
+ },
245
+ siteId: {
246
+ type: String,
247
+ default: "",
248
+ },
249
+ status: {
250
+ type: String,
251
+ default: "active",
252
+ },
253
+ type: {
254
+ type: String,
255
+ default: "organization",
256
+ },
257
+ seatManagement: {
258
+ type: String,
259
+ default: "index",
260
+ },
261
+ inviteMember: {
262
+ type: String,
263
+ default: "index",
264
+ },
265
+ route: {
266
+ type: String,
267
+ default: "index",
268
+ },
269
+ canActivateMembers: {
270
+ type: Boolean,
271
+ default: false,
272
+ },
273
+ canSuspendMembers: {
274
+ type: Boolean,
275
+ default: false,
276
+ },
277
+ canDeleteMembers: {
278
+ type: Boolean,
279
+ default: false,
280
+ },
281
+ assignRole: {
282
+ type: Boolean,
283
+ default: false,
284
+ },
285
+ headers: {
286
+ type: Array as PropType<Array<Record<string, string>>>,
287
+ default: () => [
288
+ {
289
+ title: "Name",
290
+
291
+ value: "name",
292
+ },
293
+ {
294
+ title: "Role",
295
+
296
+ value: "roleName",
297
+ },
298
+ {
299
+ title: "Organization",
300
+
301
+ value: "orgName",
302
+ },
303
+ {
304
+ title: "Status",
305
+
306
+ value: "status",
307
+ },
308
+ {
309
+ title: "Action",
310
+ value: "action-table",
311
+ },
312
+ ],
313
+ },
314
+ });
315
+
316
+ const items = ref<Array<Record<string, any>>>([]);
317
+ const page = ref(1);
318
+ const pages = ref(10);
319
+ const pageRange = ref("-- - -- of --");
320
+
321
+ const message = ref("");
322
+ const messageSnackbar = ref(false);
323
+ const messageColor = ref("");
324
+
325
+ const {
326
+ getAll: _getAll,
327
+ updateMemberStatus: _updateMemberStatus,
328
+ updateMemberRole: _updateMemberRole,
329
+ } = useMember();
330
+
331
+ const { headerSearch } = useLocal();
332
+ const { replaceMatch, setRouteParams, requiredRule } = useUtils();
333
+
334
+ const {
335
+ data: getAllReq,
336
+ refresh: getAll,
337
+ status: getAllReqStatus,
338
+ } = useLazyAsyncData("get-all-members", () =>
339
+ _getAll({
340
+ status: props.status,
341
+ org: props.orgId,
342
+ search: headerSearch.value,
343
+ page: page.value,
344
+ type: props.type,
345
+ })
346
+ );
347
+
348
+ const loading = computed(() => getAllReqStatus.value === "pending");
349
+
350
+ watchEffect(() => {
351
+ if (getAllReq.value) {
352
+ items.value = getAllReq.value.items;
353
+ pages.value = getAllReq.value.pages;
354
+ pageRange.value = getAllReq.value.pageRange;
355
+ }
356
+ });
357
+
358
+ watch(headerSearch, () => {
359
+ getAll();
360
+ });
361
+
362
+ const confirmDialog = ref(false);
363
+ const selectedMemberId = ref<string | null>(null);
364
+ const updateLoading = ref(false);
365
+ const updateAction = ref("");
366
+
367
+ const memberRoleForm = ref(false);
368
+ const assignRoleDialog = ref(false);
369
+ const selectedRole = ref<string | null>(null);
370
+ const selectedMemberRole = ref("");
371
+
372
+ function setMember({
373
+ dialog = false,
374
+ mode = "",
375
+ role = {} as Record<string, any>,
376
+ } = {}) {
377
+ if (mode === "assign-role") {
378
+ assignRoleDialog.value = dialog;
379
+ }
380
+
381
+ selectedMemberId.value = role._id;
382
+ selectedRole.value = role.role;
383
+ selectedMemberRole.value = role.role;
384
+ }
385
+
386
+ const roles = ref<Array<Record<string, any>>>([]);
387
+ const { getRoles } = useRole();
388
+ const { data: getAllRoleReq } = useLazyAsyncData("get-roles", () =>
389
+ getRoles({ org: props.orgId, type: props.type, limit: 20 })
390
+ );
391
+
392
+ watchEffect(() => {
393
+ if (getAllRoleReq.value) {
394
+ roles.value = getAllRoleReq.value.items;
395
+ }
396
+ });
397
+
398
+ watchEffect(() => {
399
+ if (selectedRole.value) {
400
+ message.value = "";
401
+ }
402
+ });
403
+
404
+ async function updateMemberRole() {
405
+ try {
406
+ await _updateMemberRole(
407
+ selectedMemberId.value ?? "",
408
+ selectedRole.value ?? "",
409
+ props.type,
410
+ props.orgId
411
+ );
412
+ await setMember({ mode: "assign-role" });
413
+ await getAll();
414
+ } catch (error: any) {
415
+ message.value = error?.response?._data?.message || "Failed to update role";
416
+ }
417
+ }
418
+
419
+ function openUpdateDialog(id: string, action: string) {
420
+ updateAction.value = action;
421
+ selectedMemberId.value = id;
422
+ confirmDialog.value = true;
423
+ }
424
+
425
+ function showMessage(msg: string, color: string) {
426
+ message.value = msg;
427
+ messageColor.value = color;
428
+ messageSnackbar.value = true;
429
+ }
430
+
431
+ async function handleUpdateMemberStatus() {
432
+ if (!selectedMemberId.value) return;
433
+ updateLoading.value = true;
434
+ try {
435
+ const res = await _updateMemberStatus(
436
+ selectedMemberId.value,
437
+ updateAction.value
438
+ );
439
+
440
+ confirmDialog.value = false;
441
+ showMessage(res.message, "success");
442
+ getAll();
443
+ } catch (error: any) {
444
+ const errorMessage = error?.response?._data?.message;
445
+ showMessage(errorMessage, "error");
446
+ } finally {
447
+ updateLoading.value = false;
448
+ selectedMemberId.value = null;
449
+ }
450
+ }
451
+ const updateActionText = computed(() => {
452
+ const map: Record<string, string> = {
453
+ active: "Activate",
454
+ suspended: "Suspend",
455
+ deleted: "Delete",
456
+ };
457
+ return map[updateAction.value] || updateAction.value;
458
+ });
459
+ </script>
@@ -0,0 +1,161 @@
1
+ <template>
2
+ <v-card width="100%">
3
+ <v-toolbar>
4
+ <v-row no-gutters class="fill-height px-6" align="center">
5
+ <span class="font-weight-bold text-h5">
6
+ {{ props.title }}
7
+ </span>
8
+ </v-row>
9
+ </v-toolbar>
10
+ <v-card-text style="max-height: 100vh; overflow-y: auto">
11
+ <v-form v-model="validForm" :disabled="disable">
12
+ <v-row no-gutters>
13
+ <v-col cols="12" class="mt-2">
14
+ <v-row no-gutters>
15
+ <InputLabel class="text-capitalize" title="Name" required />
16
+ <v-col cols="12">
17
+ <v-text-field
18
+ v-model="name"
19
+ density="comfortable"
20
+ :rules="[requiredRule]"
21
+ ></v-text-field>
22
+ </v-col>
23
+ </v-row>
24
+ </v-col>
25
+
26
+ <v-col cols="12">
27
+ <InputListGroupSelection
28
+ v-model="selectedPermissions"
29
+ :items="props.permissions"
30
+ variant="outlined"
31
+ border="thin"
32
+ :error-messages="requireListRule(selectedPermissions)"
33
+ />
34
+ </v-col>
35
+
36
+ <v-col cols="12" class="mt-2">
37
+ <v-checkbox v-model="createMore" density="comfortable" hide-details>
38
+ <template #label>
39
+ <span class="text-subtitle-2 font-weight-bold">
40
+ Create more
41
+ </span>
42
+ </template>
43
+ </v-checkbox>
44
+ </v-col>
45
+
46
+ <v-col cols="12" class="my-2">
47
+ <v-row no-gutters>
48
+ <v-col cols="12" class="text-center">
49
+ <span
50
+ class="text-none text-subtitle-2 font-weight-medium text-error"
51
+ >
52
+ {{ message }}
53
+ </span>
54
+ </v-col>
55
+ </v-row>
56
+ </v-col>
57
+ </v-row>
58
+ </v-form>
59
+ </v-card-text>
60
+
61
+ <v-toolbar>
62
+ <v-row class="px-6">
63
+ <v-col cols="6">
64
+ <v-btn
65
+ block
66
+ variant="text"
67
+ class="text-none"
68
+ size="large"
69
+ @click="cancel"
70
+ >
71
+ Cancel
72
+ </v-btn>
73
+ </v-col>
74
+
75
+ <v-col cols="6">
76
+ <v-btn
77
+ block
78
+ variant="flat"
79
+ color="black"
80
+ class="text-none"
81
+ size="large"
82
+ :disabled="!validForm"
83
+ @click="submit"
84
+ >
85
+ Submit
86
+ </v-btn>
87
+ </v-col>
88
+ </v-row>
89
+ </v-toolbar>
90
+ </v-card>
91
+ </template>
92
+
93
+ <script setup lang="ts">
94
+ const props = defineProps({
95
+ title: {
96
+ type: String,
97
+ default: "Role Permission Form",
98
+ },
99
+ permissions: {
100
+ type: Object,
101
+ default: () => ({}),
102
+ },
103
+ org: {
104
+ type: String,
105
+ default: "",
106
+ },
107
+ type: {
108
+ type: String,
109
+ default: "app",
110
+ },
111
+ });
112
+
113
+ const emit = defineEmits(["cancel", "success", "success:create-more"]);
114
+
115
+ const validForm = ref(false);
116
+
117
+ const name = ref("");
118
+ const selectedPermissions = ref([]);
119
+ const createMore = ref(false);
120
+ const disable = ref(false);
121
+
122
+ const { requiredRule, requireListRule } = useUtils();
123
+
124
+ const message = ref("");
125
+
126
+ const { createRole } = useRole();
127
+
128
+ async function submit() {
129
+ disable.value = true;
130
+ try {
131
+ await createRole({
132
+ name: name.value,
133
+ permissions: selectedPermissions.value,
134
+ type: props.type,
135
+ org: props.org,
136
+ });
137
+
138
+ if (createMore.value) {
139
+ name.value = "";
140
+ selectedPermissions.value = [];
141
+ message.value = "";
142
+ emit("success:create-more");
143
+ return;
144
+ }
145
+
146
+ emit("success");
147
+ } catch (error: any) {
148
+ message.value = error.response._data.message;
149
+ } finally {
150
+ disable.value = false;
151
+ }
152
+ }
153
+
154
+ function cancel() {
155
+ name.value = "";
156
+ selectedPermissions.value = [];
157
+ createMore.value = false;
158
+ message.value = "";
159
+ emit("cancel");
160
+ }
161
+ </script>