@7365admin1/layer-common 1.10.0 → 1.10.2

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 (86) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/components/AcceptDialog.vue +44 -0
  3. package/components/AccessCard/AvailableStats.vue +55 -0
  4. package/components/AccessCardAddForm.vue +284 -19
  5. package/components/AccessCardAssignToUnitForm.vue +440 -0
  6. package/components/AccessManagement.vue +218 -85
  7. package/components/AddSupplyForm.vue +165 -0
  8. package/components/AreaChecklistHistoryLogs.vue +235 -0
  9. package/components/AreaChecklistHistoryMain.vue +176 -0
  10. package/components/AreaFormDialog.vue +266 -0
  11. package/components/AreaMain.vue +863 -0
  12. package/components/AttendanceCheckInOutDialog.vue +416 -0
  13. package/components/AttendanceDetailsDialog.vue +184 -0
  14. package/components/AttendanceMain.vue +155 -0
  15. package/components/AttendanceMapSearchDialog.vue +393 -0
  16. package/components/AttendanceSettingsDialog.vue +398 -0
  17. package/components/BuildingManagement/buildings.vue +5 -5
  18. package/components/BuildingManagement/units.vue +5 -5
  19. package/components/BulletinBoardManagement.vue +322 -0
  20. package/components/ChecklistItemRow.vue +54 -0
  21. package/components/CheckoutItemMain.vue +705 -0
  22. package/components/CleaningScheduleMain.vue +271 -0
  23. package/components/DocumentManagement.vue +4 -0
  24. package/components/EntryPass/QrTemplatePreview.vue +104 -0
  25. package/components/EntryPassMain.vue +252 -200
  26. package/components/HygieneUpdateMoreAction.vue +238 -0
  27. package/components/ManageChecklistMain.vue +384 -0
  28. package/components/MemberMain.vue +48 -20
  29. package/components/MyAttendanceMain.vue +224 -0
  30. package/components/OnlineFormsConfiguration.vue +9 -2
  31. package/components/PhotoUpload.vue +410 -0
  32. package/components/ScheduleAreaMain.vue +313 -0
  33. package/components/ScheduleTaskAreaFormDialog.vue +144 -0
  34. package/components/ScheduleTaskAreaUpdateMoreAction.vue +109 -0
  35. package/components/ScheduleTaskForm.vue +471 -0
  36. package/components/ScheduleTaskMain.vue +345 -0
  37. package/components/ScheduleTastTicketMain.vue +182 -0
  38. package/components/SignaturePad.vue +17 -5
  39. package/components/StockCard.vue +191 -0
  40. package/components/SupplyManagementMain.vue +557 -0
  41. package/components/TableHygiene.vue +617 -0
  42. package/components/UnitMain.vue +451 -0
  43. package/components/VisitorManagement.vue +28 -15
  44. package/composables/useAccessManagement.ts +163 -0
  45. package/composables/useAreaPermission.ts +51 -0
  46. package/composables/useAreas.ts +99 -0
  47. package/composables/useAttendance.ts +89 -0
  48. package/composables/useAttendancePermission.ts +68 -0
  49. package/composables/useBuilding.ts +2 -2
  50. package/composables/useBuildingUnit.ts +2 -2
  51. package/composables/useBulletin.ts +82 -0
  52. package/composables/useCard.ts +2 -0
  53. package/composables/useCheckout.ts +61 -0
  54. package/composables/useCheckoutPermission.ts +80 -0
  55. package/composables/useCleaningPermission.ts +229 -0
  56. package/composables/useCleaningSchedulePermission.ts +58 -0
  57. package/composables/useCleaningSchedules.ts +233 -0
  58. package/composables/useCountry.ts +8 -0
  59. package/composables/useDashboardData.ts +2 -2
  60. package/composables/useFeedback.ts +1 -1
  61. package/composables/useLocation.ts +78 -0
  62. package/composables/useOnlineForm.ts +16 -9
  63. package/composables/usePeople.ts +87 -72
  64. package/composables/useQR.ts +29 -0
  65. package/composables/useScheduleTask.ts +89 -0
  66. package/composables/useScheduleTaskArea.ts +85 -0
  67. package/composables/useScheduleTaskPermission.ts +68 -0
  68. package/composables/useSiteEntryPassSettings.ts +4 -15
  69. package/composables/useStock.ts +45 -0
  70. package/composables/useSupply.ts +63 -0
  71. package/composables/useSupplyPermission.ts +92 -0
  72. package/composables/useUnitPermission.ts +51 -0
  73. package/composables/useUnits.ts +82 -0
  74. package/composables/useWebUsb.ts +389 -0
  75. package/composables/useWorkOrder.ts +1 -1
  76. package/nuxt.config.ts +3 -0
  77. package/package.json +4 -1
  78. package/types/area.d.ts +22 -0
  79. package/types/attendance.d.ts +38 -0
  80. package/types/checkout-item.d.ts +27 -0
  81. package/types/cleaner-schedule.d.ts +54 -0
  82. package/types/location.d.ts +42 -0
  83. package/types/schedule-task.d.ts +18 -0
  84. package/types/stock.d.ts +16 -0
  85. package/types/supply.d.ts +11 -0
  86. package/utils/acm-crypto.ts +30 -0
@@ -0,0 +1,322 @@
1
+ <template>
2
+ <v-row no-gutters>
3
+ <TableMain :headers="headers" :items="paginatePlaceholderItem" v-model:search="searchInput"
4
+ :loading="getAnnouncementPending" :page="page" :pages="pages" :pageRange="pageRange"
5
+ @refresh="getAnnouncementsRefresh" show-header @update:page="handleUpdatePage" @row-click="handleRowClick"
6
+ @create="handleCreateEvent" :can-create="canCreateBulletinBoard" create-label="Add Announcement">
7
+ <template #extension>
8
+ <v-row no-gutters class="w-100 d-flex flex-column">
9
+ <v-tabs v-model="status" color="primary" :height="40" @update:model-value="toRoute" class="w-100">
10
+ <v-tab v-for="tab in tabOptions" :value="tab.status" :key="tab.status" class="text-capitalize">
11
+ {{ tab.name }}
12
+ </v-tab>
13
+ </v-tabs>
14
+ </v-row>
15
+ </template>
16
+
17
+ <template v-slot:item.createdAt="{ item }">
18
+ <span class="d-flex align-center ga-2">
19
+ <v-icon icon="mdi-calendar-start" color="green" size="20" />
20
+ <span class="text-capitalize">{{ toLocalDate(item.createdAt) || "-" }}</span>
21
+ </span>
22
+
23
+ </template>
24
+
25
+ <template v-slot:item.noExpiration="{ item }">
26
+ <BulletinExpirationChip :value="item?.noExpiration" />
27
+ </template>
28
+
29
+ <template v-slot:item.duration="{ item }">
30
+ <span class="d-flex align-center ga-2">
31
+ <v-icon icon="mdi-calendar-start" color="green" size="20" />
32
+ <span class="text-capitalize">{{ toLocalDate(item.startDate) || "-" }}</span>
33
+ </span>
34
+ <span class="d-flex align-center ga-2">
35
+ <v-icon icon="mdi-calendar-end" color="red" size="20" />
36
+ <span class="text-capitalize">{{ toLocalDate(item.endDate) || "_" }}</span>
37
+ </span>
38
+ </template>
39
+ </TableMain>
40
+
41
+ <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" style="z-index: 3000;" />
42
+
43
+ <v-dialog v-model="dialog.showForm" width="600" persistent>
44
+ <BulletinBoardForm :mode="mode" :site-id="siteId" :active-id="selectedAnnouncementId"
45
+ @close="dialog.showForm = false" @done="handleDone" />
46
+ </v-dialog>
47
+
48
+ <v-dialog v-model="dialog.moreActions" v-if="activeAnnouncementObj && canViewBulletinBoardDetails" width="600"
49
+ persistent>
50
+ <BulletinBoardView :active-announcement="activeAnnouncementObj" :can-delete="canDeleteBulletinBoard"
51
+ :can-update="canUpdateBulletinBoard" @edit="handleEditAnnouncement" @close="dialog.moreActions = false"
52
+ @delete="dialog.deletePrompt = true" />
53
+ </v-dialog>
54
+
55
+ <v-dialog v-model="dialog.deletePrompt" width="450" persistent>
56
+ <CardDeleteConfirmation prompt-title="Are you sure want to delete this announcement?"
57
+ :loading="loading.deletingAnnouncement" @close="dialog.deletePrompt = false"
58
+ @delete="handleProceedDeleteAnnouncement" />
59
+ </v-dialog>
60
+ </v-row>
61
+ </template>
62
+ <script setup lang="ts">
63
+ definePageMeta({
64
+ memberOnly: true,
65
+ })
66
+
67
+ const props = defineProps({
68
+ siteId: {
69
+ type: String,
70
+ required: true
71
+ },
72
+ canCreateBulletinBoard: {
73
+ type: Boolean,
74
+ default: true
75
+ },
76
+ canUpdateBulletinBoard: {
77
+ type: Boolean,
78
+ default: true
79
+ },
80
+ canViewBulletinBoardDetails: {
81
+ type: Boolean,
82
+ default: true
83
+ }, canDeleteBulletinBoard: {
84
+ type: Boolean,
85
+ default: true
86
+ }
87
+ })
88
+
89
+
90
+ const { authenticate } = useLocalAuth();
91
+ authenticate();
92
+
93
+ const route = useRoute();
94
+ const orgId = route.params.org as string;
95
+ const siteId = props.siteId;
96
+ const routeName = (useRoute().name as string) ?? "";
97
+ const { getAll, deleteBulletinById } = useBulletin()
98
+ const { debounce } = useUtils()
99
+
100
+
101
+
102
+ const headers = [
103
+ { title: "Title", value: "title" },
104
+ { title: "Date Created", value: "createdAt", align: "start" },
105
+ { title: "Start Date/End Date", value: "duration", align: "start" },
106
+ { title: "No Expiration", value: "noExpiration", align: "start" },
107
+ { title: "", value: "actions" },
108
+ ];
109
+ const items = ref<TAnnouncement[]>([]);
110
+ const page = ref(1);
111
+ const pages = ref(0);
112
+ const pageRange = ref("-- - -- of --");
113
+ const selectedAnnouncementId = ref<string>("")
114
+ const mode = ref<'add' | 'edit'>('add')
115
+ const status = ref<TAnnouncementStatus>()
116
+ const searchInput = ref('')
117
+
118
+ const dialog = reactive({
119
+ showForm: false,
120
+ moreActions: false,
121
+ viewDetails: false,
122
+ deletePrompt: false,
123
+ })
124
+
125
+ const loading = reactive({
126
+ deletingAnnouncement: false
127
+ })
128
+
129
+ const messageSnackbar = ref(false)
130
+ const message = ref('')
131
+ const messageColor = ref<'success' | 'error' | 'info'>()
132
+
133
+ const activeAnnouncementObj = computed(() => {
134
+ return items.value.find(x => x._id === selectedAnnouncementId.value)
135
+ })
136
+
137
+ const paginatePlaceholderItem = computed(() => {
138
+ const pageSize = 10
139
+ const total = items.value.length
140
+ const currentPage = page.value
141
+
142
+ const start = (currentPage - 1) * pageSize
143
+ const end = start + pageSize
144
+
145
+ const from = total === 0 ? 0 : start + 1
146
+ const to = Math.min(end, total)
147
+ pageRange.value = `${from}-${to} of ${total}`
148
+
149
+ pages.value = Math.ceil(total / pageSize)
150
+
151
+ return items.value.slice(start, end)
152
+ })
153
+
154
+
155
+ const {
156
+ data: getAnnouncementReq,
157
+ refresh: getAnnouncementsRefresh,
158
+ pending: getAnnouncementPending,
159
+ } = await useLazyAsyncData(
160
+ `get-all-announcements-${page.value}`,
161
+ () => getAll({ page: page.value, site: siteId, status: status.value }),
162
+ {
163
+ watch: [page, () => route.query],
164
+ }
165
+ );
166
+
167
+ watch(getAnnouncementReq, (newVal) => {
168
+ items.value = newVal?.items || [];
169
+ pages.value = newVal?.pages || 0;
170
+ pageRange.value = newVal?.pageRange || "-- - -- of --";
171
+ });
172
+
173
+
174
+ function eventStatusFormat(status: any) {
175
+ switch (status) {
176
+ case 'In Progress':
177
+ return {
178
+ color: 'orange',
179
+ text: 'In Progress'
180
+ };
181
+ case 'Active':
182
+ return {
183
+ color: 'green',
184
+ text: status
185
+ }
186
+ case 'Scheduled':
187
+ return {
188
+ color: 'blue',
189
+ text: status
190
+ }
191
+ default:
192
+ return {
193
+ color: 'grey',
194
+ text: status
195
+ }
196
+ }
197
+ }
198
+
199
+ const tabOptions = [
200
+ { name: "Active", status: "active" },
201
+ { name: "Expired", status: "expired" },
202
+ ];
203
+
204
+ function toRoute(status: any) {
205
+ const obj = tabOptions.find((x) => x.status === status);
206
+ if (!obj) return;
207
+ page.value = 1
208
+ navigateTo({
209
+ name: routeName,
210
+ params: {
211
+ org: orgId,
212
+ },
213
+ query: {
214
+ status: obj.status,
215
+ },
216
+ });
217
+ }
218
+
219
+ function toLocalDate(utcString: string) {
220
+ if (!utcString) return ""
221
+ return new Date(utcString).toLocaleString("en-US", {
222
+ year: "numeric",
223
+ month: "2-digit",
224
+ day: "2-digit",
225
+ })
226
+ }
227
+
228
+ function handleRowClick(data: any) {
229
+ selectedAnnouncementId.value = data?.item?._id;
230
+ dialog.moreActions = true;
231
+ }
232
+
233
+ function handleUpdatePage(newPageNum: number) {
234
+ page.value = newPageNum;
235
+ }
236
+
237
+ function handleClose() {
238
+ dialog.showForm = false;
239
+
240
+ }
241
+
242
+ function handleFormDone() {
243
+ getAnnouncementsRefresh();
244
+ dialog.showForm = false;
245
+ }
246
+
247
+ function handleFormCreateMore() {
248
+ getAnnouncementsRefresh();
249
+ }
250
+
251
+ function handleCreateEvent() {
252
+ selectedAnnouncementId.value = ""
253
+ mode.value = 'add'
254
+ dialog.showForm = true;
255
+ }
256
+
257
+ function handleDeleteAnnouncement() {
258
+ dialog.moreActions = false;
259
+ dialog.showForm = false;
260
+ dialog.deletePrompt = true;
261
+ }
262
+
263
+ function handleEditAnnouncement() {
264
+ dialog.moreActions = false
265
+ mode.value = "edit"
266
+ dialog.showForm = true;
267
+ }
268
+
269
+ function showMessage(text: string, type: "error" | 'success' | 'info') {
270
+ messageSnackbar.value = true;
271
+ message.value = text;
272
+ messageColor.value = type
273
+ }
274
+
275
+
276
+
277
+
278
+
279
+ async function handleProceedDeleteAnnouncement() {
280
+ try {
281
+ loading.deletingAnnouncement = true;
282
+ const bulletinId = selectedAnnouncementId.value;
283
+ const res = await deleteBulletinById(bulletinId as string);
284
+ if (res) {
285
+ showMessage("Announcement successfully deleted!", "info");
286
+ await getAnnouncementsRefresh();
287
+ dialog.deletePrompt = false;
288
+ }
289
+ } catch (error: any) {
290
+ const errorMessage = error?.response?._data?.message;
291
+ console.log("[ERROR]", error);
292
+ showMessage(
293
+ errorMessage || "Something went wrong. Please try again later.",
294
+ "error"
295
+ );
296
+ } finally {
297
+ loading.deletingAnnouncement = false;
298
+ }
299
+ }
300
+
301
+
302
+
303
+
304
+ async function handleDone() {
305
+ await getAnnouncementsRefresh()
306
+ dialog.showForm = false
307
+ }
308
+
309
+
310
+ const debounceSearch = debounce(getAnnouncementsRefresh, 500)
311
+
312
+ watch([searchInput], ([search]) => {
313
+ debounceSearch()
314
+ })
315
+
316
+
317
+ onMounted(() => {
318
+ const statusQuery = (useRoute()?.query?.status)
319
+ status.value = (statusQuery === "active" || statusQuery === "expired") ? statusQuery : "active"
320
+ })
321
+
322
+ </script>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <v-row no-gutters class="py-3 px-2" align="center">
3
+ <v-col cols="auto">
4
+ <v-btn
5
+ :variant="
6
+ item?._action === 'rejected' || item?.reject ? 'tonal' : 'outlined'
7
+ "
8
+ :color="
9
+ item?._action === 'rejected' || item?.reject ? 'error' : undefined
10
+ "
11
+ :disabled="readOnly"
12
+ size="small"
13
+ class="me-2"
14
+ icon
15
+ @click.stop="handleReject"
16
+ >
17
+ <v-icon>mdi-close</v-icon>
18
+ </v-btn>
19
+ </v-col>
20
+ <v-col cols="auto">
21
+ <v-btn
22
+ :variant="
23
+ item?._action === 'accepted' || item?.approve ? 'tonal' : 'outlined'
24
+ "
25
+ :color="
26
+ item?._action === 'accepted' || item?.approve ? 'success' : undefined
27
+ "
28
+ :disabled="readOnly"
29
+ size="small"
30
+ icon
31
+ @click.stop="handleApprove"
32
+ >
33
+ <v-icon>mdi-check</v-icon>
34
+ </v-btn>
35
+ </v-col>
36
+ </v-row>
37
+ </template>
38
+
39
+ <script setup lang="ts">
40
+ const props = defineProps({
41
+ item: { type: Object, required: true },
42
+ readOnly: { type: Boolean, default: false },
43
+ });
44
+
45
+ const emit = defineEmits(["reject", "approve"]);
46
+
47
+ function handleReject() {
48
+ emit("reject", props.item);
49
+ }
50
+
51
+ function handleApprove() {
52
+ emit("approve", props.item);
53
+ }
54
+ </script>