@iservice365/layer-common 0.1.0 → 0.2.1

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 (93) 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 +14 -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 +62 -20
  45. package/composables/useLocalSetup.ts +13 -0
  46. package/composables/useMember.ts +111 -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/middleware/member.ts +4 -0
  63. package/nuxt.config.ts +3 -1
  64. package/package.json +7 -3
  65. package/pages/index.vue +3 -0
  66. package/pages/payment-method-linked.vue +31 -0
  67. package/pages/require-customer.vue +56 -0
  68. package/pages/require-organization-membership.vue +47 -0
  69. package/pages/unauthorized.vue +29 -0
  70. package/plugins/API.ts +2 -25
  71. package/plugins/iconify.client.ts +5 -0
  72. package/plugins/secure-member.client.ts +54 -0
  73. package/plugins/vuetify.ts +2 -0
  74. package/public/bg-camera.jpg +0 -0
  75. package/public/bg-city.jpg +0 -0
  76. package/public/bg-condo.jpg +0 -0
  77. package/public/images/icons/delete-icon.png +0 -0
  78. package/public/sprite.svg +1 -0
  79. package/types/address.d.ts +13 -0
  80. package/types/customer.d.ts +15 -0
  81. package/types/feedback.d.ts +63 -0
  82. package/types/local.d.ts +47 -38
  83. package/types/member.d.ts +21 -0
  84. package/types/org.d.ts +13 -0
  85. package/types/permission.d.ts +1 -0
  86. package/types/price.d.ts +17 -0
  87. package/types/promo-code.d.ts +19 -0
  88. package/types/service-provider.d.ts +15 -0
  89. package/types/site.d.ts +13 -0
  90. package/types/subscription.d.ts +23 -0
  91. package/types/user.d.ts +19 -0
  92. package/types/verification.d.ts +20 -0
  93. package/types/work-order.d.ts +40 -0
@@ -0,0 +1,195 @@
1
+ <template>
2
+ <v-row no-gutters>
3
+ <v-col cols="12" class="mb-2">
4
+ <v-row no-gutters>
5
+ <v-btn
6
+ class="text-none mr-2"
7
+ rounded="pill"
8
+ variant="tonal"
9
+ @click="createDialog = true"
10
+ size="large"
11
+ >
12
+ Add Service Provider
13
+ </v-btn>
14
+ </v-row>
15
+ </v-col>
16
+ <v-col cols="12">
17
+ <v-card
18
+ width="100%"
19
+ variant="outlined"
20
+ border="thin"
21
+ rounded="lg"
22
+ :loading="loading"
23
+ >
24
+ <v-toolbar density="compact" color="grey-lighten-4">
25
+ <template #prepend>
26
+ <v-btn fab icon density="comfortable" @click="getServiceProvider()">
27
+ <v-icon>mdi-refresh</v-icon>
28
+ </v-btn>
29
+ </template>
30
+
31
+ <template #append>
32
+ <v-row no-gutters justify="end" align="center">
33
+ <span class="mr-2 text-caption text-fontgray">
34
+ {{ pageRange }}
35
+ </span>
36
+ <local-pagination
37
+ v-model="page"
38
+ :length="pages"
39
+ @update:value="_getServiceProvider()"
40
+ />
41
+ </v-row>
42
+ </template>
43
+ </v-toolbar>
44
+
45
+ <v-data-table
46
+ :headers="headers"
47
+ :items="items"
48
+ item-value="_id"
49
+ items-per-page="20"
50
+ fixed-header
51
+ hide-default-footer
52
+ hide-default-header
53
+ style="max-height: calc(100vh - (180px))"
54
+ >
55
+ <template #item.permissions="{ value }">
56
+ <span class="text-caption font-weight-bold text-capitalize">
57
+ permissions
58
+ </span>
59
+ <v-chip>{{ value.length }}</v-chip>
60
+ </template>
61
+
62
+ <template #item.nature="{ item }">
63
+ <span class="text-capitalize">
64
+ {{ item.nature }}
65
+ </span>
66
+ </template>
67
+
68
+ <template #item.action-table="{ item }">
69
+ <v-menu :close-on-content-click="false" offset-y width="150">
70
+ <template v-slot:activator="{ props }">
71
+ <v-icon v-bind="props">mdi-dots-horizontal</v-icon>
72
+ </template>
73
+ <v-list>
74
+ <v-list-item @click=""> Delete Service Provider </v-list-item>
75
+ </v-list>
76
+ </v-menu>
77
+ </template>
78
+ </v-data-table>
79
+ </v-card>
80
+ </v-col>
81
+ </v-row>
82
+
83
+ <v-dialog v-model="createDialog" width="500" persistent>
84
+ <ServiceProviderFormCreate
85
+ @cancel="createDialog = false"
86
+ :org="props.orgId"
87
+ :type="props.type"
88
+ :site-id="props.siteId"
89
+ :service-provider-org-id="props.orgId"
90
+ @success="success()"
91
+ @success:create-more="getServiceProvider()"
92
+ @notify="onNotify"
93
+ />
94
+ </v-dialog>
95
+
96
+ <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
97
+ </template>
98
+
99
+ <script lang="ts" setup>
100
+ const props = defineProps({
101
+ orgId: {
102
+ type: String,
103
+ default: "",
104
+ },
105
+ customerId: {
106
+ type: String,
107
+ default: "",
108
+ },
109
+ siteId: {
110
+ type: String,
111
+ default: "",
112
+ },
113
+ siteName: {
114
+ type: String,
115
+ default: "",
116
+ },
117
+ serviceProviderOrgId: {
118
+ type: String,
119
+ default: "",
120
+ },
121
+ type: {
122
+ type: String,
123
+ required: true,
124
+ default: "app",
125
+ },
126
+ route: {
127
+ type: String,
128
+ default: "",
129
+ },
130
+ });
131
+
132
+ const headers = [
133
+ { title: "Name", value: "name" },
134
+ { title: "Nature", value: "nature" },
135
+ ];
136
+
137
+ const page = ref(1);
138
+ const pages = ref(0);
139
+ const pageRange = ref("-- - -- of --");
140
+
141
+ const message = ref("");
142
+ const messageSnackbar = ref(false);
143
+ const messageColor = ref("");
144
+
145
+ const items = ref<Array<Record<string, any>>>([]);
146
+
147
+ const { getAll: _getServiceProvider } = useServiceProvider();
148
+
149
+ const {
150
+ data: getAllReq,
151
+ refresh: getServiceProvider,
152
+ status: getServiceProviderReqStatus,
153
+ } = useLazyAsyncData(
154
+ "service-provider-get-all",
155
+ () =>
156
+ _getServiceProvider({
157
+ page: page.value,
158
+ orgId: props.orgId,
159
+ }),
160
+ {
161
+ watch: [page],
162
+ }
163
+ );
164
+
165
+ const loading = computed(() => getServiceProviderReqStatus.value === "pending");
166
+
167
+ watchEffect(() => {
168
+ if (getAllReq.value) {
169
+ items.value = getAllReq.value.items.map((i: any) => ({
170
+ ...i,
171
+ name: i.name,
172
+ nature: i.nature.replace(/_/g, " "),
173
+ }));
174
+ pages.value = getAllReq.value.pages;
175
+ pageRange.value = getAllReq.value.pageRange;
176
+ }
177
+ });
178
+
179
+ const createDialog = ref(false);
180
+
181
+ const success = () => {
182
+ createDialog.value = false;
183
+ getServiceProvider();
184
+ };
185
+
186
+ function showMessage(msg: string, color: string) {
187
+ message.value = msg;
188
+ messageColor.value = color;
189
+ messageSnackbar.value = true;
190
+ }
191
+
192
+ function onNotify(payload: { message: string; color: string }) {
193
+ showMessage(payload.message, payload.color);
194
+ }
195
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <div>
3
+ <Vue3Signature
4
+ ref="signatureRef"
5
+ :sigOption="options"
6
+ @save="onSave"
7
+ style="border: 1px solid #ccc; width: 100%; height: 200px"
8
+ />
9
+ <div class="mt-4 flex justify-end">
10
+ <button @click="clear" class="px-4 py-2 bg-red-500 rounded">Clear</button>
11
+ <button @click="save" class="px-4 py-2 bg-green-500 rounded ml-2">
12
+ Save
13
+ </button>
14
+ </div>
15
+
16
+ <div style="position: fixed; top: 20px; right: 20px; z-index: 9999">
17
+ <Snackbar
18
+ v-model="messageSnackbar"
19
+ :text="message"
20
+ :color="messageColor"
21
+ />
22
+ </div>
23
+ </div>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import { ref, defineProps, defineEmits } from "vue";
28
+ import Vue3Signature from "vue3-signature";
29
+
30
+ defineProps({
31
+ modelValue: String,
32
+ });
33
+
34
+ const emit = defineEmits(["update:modelValue"]);
35
+
36
+ const signatureRef = ref();
37
+
38
+ const options = {
39
+ penColor: "black",
40
+ backgroundColor: "white",
41
+ };
42
+
43
+ // Snackbar control
44
+ const message = ref("");
45
+ const messageColor = ref("");
46
+ const messageSnackbar = ref(false);
47
+
48
+ function showMessage(msg: string, color: string) {
49
+ message.value = msg;
50
+ messageColor.value = color;
51
+ messageSnackbar.value = true;
52
+ }
53
+
54
+ function onSave(data: string) {
55
+ emit("update:modelValue", data);
56
+ showMessage("Signature saved successfully.", "success");
57
+ }
58
+
59
+ function save() {
60
+ const signatureData = signatureRef.value?.save("image/jpeg");
61
+ if (signatureData) {
62
+ emit("update:modelValue", signatureData);
63
+ showMessage("Signature saved successfully.", "success");
64
+ } else {
65
+ showMessage("No signature to save.", "error");
66
+ }
67
+ }
68
+
69
+ function clear() {
70
+ signatureRef.value?.clear();
71
+ showMessage("Signature cleared.", "success");
72
+ }
73
+ </script>
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <v-row no-gutters class="pa-4" justify="center">
3
+ <v-col cols="12" :lg="props.lg" :md="props.md" :sm="props.sm">
4
+ <v-row no-gutters>
5
+ <v-col cols="12">
6
+ <span
7
+ class="font-weight-medium text-subtitle-1 text-decoration-underline cursor-pointer"
8
+ @click="emit('back')"
9
+ >
10
+ Back
11
+ </span>
12
+ </v-col>
13
+ <v-col cols="12">
14
+ <span class="text-h5">{{ props.title }}</span>
15
+ </v-col>
16
+
17
+ <v-col cols="12" class="mt-4">
18
+ <slot name="default"> </slot>
19
+ </v-col>
20
+
21
+ <v-col cols="12" class="mt-4">
22
+ <slot name="footer"> </slot>
23
+ </v-col>
24
+ </v-row>
25
+ </v-col>
26
+ </v-row>
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ const emit = defineEmits(["back"]);
31
+ const props = defineProps({
32
+ title: {
33
+ type: String,
34
+ default: "Title",
35
+ },
36
+ lg: {
37
+ type: String,
38
+ default: "4",
39
+ },
40
+ md: {
41
+ type: String,
42
+ default: "6",
43
+ },
44
+ sm: {
45
+ type: String,
46
+ default: "6",
47
+ },
48
+ fluid: {
49
+ type: Boolean,
50
+ default: false,
51
+ },
52
+ });
53
+ </script>
@@ -16,7 +16,7 @@
16
16
  class="text-subtitle-2 font-weight-bold"
17
17
  >
18
18
  <v-list-item-title class="text-truncate">
19
- {{ selected || `Select ${props.title}` }}
19
+ {{ name || `Select ${prop.title}` }}
20
20
  </v-list-item-title>
21
21
  </v-list-item>
22
22
  </v-list>
@@ -26,7 +26,14 @@
26
26
  <span class="text-subtitle-2 font-weight-bold">
27
27
  Switch {{ prop.title }} context
28
28
  </span>
29
- <v-text-field density="compact" width="100%" hide-details class="mb-2">
29
+ <v-text-field
30
+ v-model="search"
31
+ @keydown.enter="emit('search')"
32
+ density="compact"
33
+ width="100%"
34
+ hide-details
35
+ class="mb-2"
36
+ >
30
37
  <template #prepend-inner>
31
38
  <v-icon>mdi-magnify</v-icon>
32
39
  </template>
@@ -38,7 +45,7 @@
38
45
  class="text-caption font-weight-bold"
39
46
  v-for="item in prop.items"
40
47
  :key="item.value"
41
- @click="selected = item.value"
48
+ @click="selectItem(item.value)"
42
49
  >
43
50
  <v-icon size="16" class="mr-2">
44
51
  {{ selected === item.value ? "mdi-check" : "" }}
@@ -77,11 +84,25 @@ const prop = defineProps({
77
84
  },
78
85
  });
79
86
 
80
- const emit = defineEmits(["click:switch"]);
81
-
82
87
  const menu = defineModel<boolean>("menu", { required: false, default: false });
83
88
  const selected = defineModel<string>("selected", {
84
89
  required: false,
85
90
  default: "",
86
91
  });
92
+ const search = defineModel<string>("search", {
93
+ required: false,
94
+ default: "",
95
+ });
96
+
97
+ const emit = defineEmits(["search", "select"]);
98
+
99
+ const name = computed(() => {
100
+ return prop.items.find((item) => item.value === selected.value)?.text ?? "";
101
+ });
102
+
103
+ const selectItem = (value: string) => {
104
+ selected.value = value;
105
+ menu.value = false;
106
+ emit("select", value);
107
+ };
87
108
  </script>
@@ -0,0 +1,150 @@
1
+ <template>
2
+ <v-card
3
+ width="100%"
4
+ variant="outlined"
5
+ border="thin"
6
+ rounded="lg"
7
+ :loading="loading"
8
+ >
9
+ <v-toolbar density="compact" color="grey-lighten-4">
10
+ <template #prepend>
11
+ <v-checkbox v-model="selectAll" hide-details class="mx-1"></v-checkbox>
12
+
13
+ <v-btn fab icon density="comfortable" @click="emit('refresh')">
14
+ <v-icon>mdi-refresh</v-icon>
15
+ </v-btn>
16
+ </template>
17
+
18
+ <template #append>
19
+ <v-row no-gutters justify="end" align="center">
20
+ <span class="mr-2 text-caption text-fontgray">
21
+ {{ props.pageRange }}
22
+ </span>
23
+ <div class="arrow-navigation">
24
+ <v-btn
25
+ icon="mdi-chevron-left"
26
+ variant="text"
27
+ density="comfortable"
28
+ :disabled="page <= 1"
29
+ @click="decrement"
30
+ />
31
+ <v-btn
32
+ icon="mdi-chevron-right"
33
+ variant="text"
34
+ density="comfortable"
35
+ :disabled="page >= props.length"
36
+ @click="increment"
37
+ />
38
+ </div>
39
+ <slot name="action-button"></slot>
40
+ </v-row>
41
+ </template>
42
+
43
+ <template v-if="$slots.extension" v-slot:extension>
44
+ <slot name="extension"></slot>
45
+ </template>
46
+ </v-toolbar>
47
+ <div :style="{ overflowY: 'auto', height }">
48
+ <v-data-table
49
+ v-model="selected"
50
+ :headers="props.headers"
51
+ :items="props.items"
52
+ item-value="_id"
53
+ items-per-page="20"
54
+ show-select
55
+ fixed-header
56
+ hide-default-footer
57
+ hide-default-header
58
+ :max-height="props.height"
59
+ :loading="props.loading"
60
+ @click:row="tableRowClickHandler"
61
+ >
62
+ <template v-if="$slots.item" v-slot:item>
63
+ <slot name="item" :items="props.items"></slot>
64
+ </template>
65
+
66
+ <template v-slot:item="{ item }">
67
+ <tr>
68
+ <td v-for="col in props.headers" :key="col.value">
69
+ <slot :name="col.value" :item="item">
70
+ {{ item[col.value] }}
71
+ </slot>
72
+ </td>
73
+ </tr>
74
+ </template>
75
+ </v-data-table>
76
+ </div>
77
+ </v-card>
78
+ </template>
79
+
80
+ <script setup lang="ts">
81
+ const selected = defineModel({
82
+ type: Array as PropType<Array<string>>,
83
+ default: () => [],
84
+ });
85
+ const page = defineModel("page", { type: Number, default: 0 });
86
+
87
+ const props = defineProps({
88
+ headers: {
89
+ type: Array as PropType<Array<Record<string, string>>>,
90
+ required: true,
91
+ default: () => [],
92
+ },
93
+ items: {
94
+ type: Array as PropType<Array<Record<string, any>>>,
95
+ required: true,
96
+ default: () => [],
97
+ },
98
+ pages: {
99
+ type: Number,
100
+ required: true,
101
+ default: 0,
102
+ },
103
+ pageRange: {
104
+ type: String,
105
+ required: true,
106
+ default: "-- - -- of --",
107
+ },
108
+ length: {
109
+ type: Number,
110
+ required: true,
111
+ default: 0,
112
+ },
113
+ loading: {
114
+ type: Boolean,
115
+ required: true,
116
+ default: true,
117
+ },
118
+ height: {
119
+ type: String,
120
+ default: "500px",
121
+ },
122
+ });
123
+
124
+ const emit = defineEmits(["refresh", "update:pagination", "row-click"]);
125
+
126
+ function increment() {
127
+ page.value++;
128
+ emit("update:pagination", page.value);
129
+ }
130
+
131
+ function decrement() {
132
+ page.value--;
133
+ emit("update:pagination", page.value);
134
+ }
135
+
136
+ function tableRowClickHandler(_: any, row: any) {
137
+ const item = props.items[row.index];
138
+ emit("row-click", item);
139
+ }
140
+
141
+ const selectAll = ref(false);
142
+
143
+ watch(selectAll, (curr) => {
144
+ selected.value.splice(0, selected.value.length);
145
+ if (curr) {
146
+ const ids = props.items.map((i) => i._id as string);
147
+ selected.value.push(...ids);
148
+ }
149
+ });
150
+ </script>
@@ -0,0 +1,164 @@
1
+ <template>
2
+ <v-card width="100%" variant="outlined" border="thin" rounded="lg">
3
+ <v-toolbar density="compact" class="px-3 border-b-sm" color="transparent">
4
+ <template #prepend>
5
+ <slot name="title">Title</slot>
6
+ </template>
7
+
8
+ <template #append>
9
+ <v-row no-gutters justify="end" align="center">
10
+ <slot name="action-button"></slot>
11
+ </v-row>
12
+ </template>
13
+
14
+ <template v-if="$slots.extension" v-slot:extension>
15
+ <slot name="extension"></slot>
16
+ </template>
17
+ </v-toolbar>
18
+
19
+ <v-data-table
20
+ v-model="selected"
21
+ :headers="props.headers"
22
+ :items="props.items"
23
+ item-value="_id"
24
+ items-per-page="20"
25
+ fixed-header
26
+ hide-default-footer
27
+ selec
28
+ :loading="props.loading"
29
+ @click:row="handleRowClick"
30
+ :style="`max-height:${props.height}`"
31
+ :class="{ 'clickable-rows': props.clickableRows }"
32
+ >
33
+ <template v-if="$slots.item" v-slot:item>
34
+ <slot name="item" :items="props.items"></slot>
35
+ </template>
36
+
37
+ <template v-slot:item="{ item }">
38
+ <tr @click="handleRowClick(item)">
39
+ <td v-for="col in props.headers" :key="col.value">
40
+ <slot :name="col.value" :item="item">
41
+ {{ item[col.value] }}
42
+ </slot>
43
+ </td>
44
+ </tr>
45
+ </template>
46
+ </v-data-table>
47
+ <v-toolbar density="compact" class="px-3 border-t-sm" color="transparent">
48
+ <template #append>
49
+ <v-row no-gutters justify="end" align="center">
50
+ <span class="mr-2 text-caption text-fontgray">
51
+ {{ props.pageRange }}
52
+ </span>
53
+ <div class="arrow-navigation">
54
+ <v-btn
55
+ icon="mdi-chevron-left"
56
+ variant="text"
57
+ density="comfortable"
58
+ :disabled="page <= 1"
59
+ @click="decrement"
60
+ />
61
+ <v-btn
62
+ icon="mdi-chevron-right"
63
+ variant="text"
64
+ density="comfortable"
65
+ :disabled="page >= props.length"
66
+ @click="increment"
67
+ />
68
+ </div>
69
+ </v-row>
70
+ </template>
71
+
72
+ <template v-if="$slots.extension" v-slot:extension>
73
+ <slot name="extension"></slot>
74
+ </template>
75
+ </v-toolbar>
76
+ </v-card>
77
+ </template>
78
+
79
+ <script setup lang="ts">
80
+ const selected = defineModel({
81
+ type: Array as PropType<Array<string>>,
82
+ default: () => [],
83
+ });
84
+ const page = defineModel("page", { type: Number, default: 0 });
85
+
86
+ const props = defineProps({
87
+ headers: {
88
+ type: Array as PropType<Array<Record<string, string>>>,
89
+ required: true,
90
+ default: () => [],
91
+ },
92
+ items: {
93
+ type: Array as PropType<Array<Record<string, any>>>,
94
+ required: true,
95
+ default: () => [],
96
+ },
97
+ pages: {
98
+ type: Number,
99
+ required: true,
100
+ default: 0,
101
+ },
102
+ pageRange: {
103
+ type: String,
104
+ required: true,
105
+ default: "-- - -- of --",
106
+ },
107
+ length: {
108
+ type: Number,
109
+ required: true,
110
+ default: 0,
111
+ },
112
+ loading: {
113
+ type: Boolean,
114
+ required: true,
115
+ default: true,
116
+ },
117
+ height: {
118
+ type: String,
119
+ default: "500px",
120
+ },
121
+ clickableRows: {
122
+ type: Boolean,
123
+ default: false,
124
+ },
125
+ });
126
+
127
+ const emit = defineEmits(["refresh", "update:pagination", "row-click"]);
128
+
129
+ function increment() {
130
+ page.value++;
131
+ emit("update:pagination", page.value);
132
+ }
133
+
134
+ function decrement() {
135
+ page.value--;
136
+ emit("update:pagination", page.value);
137
+ }
138
+
139
+ function handleRowClick(item: any) {
140
+ if (props.clickableRows) {
141
+ emit("row-click", item);
142
+ }
143
+ }
144
+
145
+ const selectAll = ref(false);
146
+
147
+ watch(selectAll, (curr) => {
148
+ selected.value.splice(0, selected.value.length);
149
+ if (curr) {
150
+ const ids = props.items.map((i) => i._id as string);
151
+ selected.value.push(...ids);
152
+ }
153
+ });
154
+ </script>
155
+
156
+ <style scoped>
157
+ .clickable-rows tbody tr {
158
+ cursor: pointer;
159
+ }
160
+
161
+ .clickable-rows tbody tr:hover {
162
+ background-color: #f5f5f5;
163
+ }
164
+ </style>