@7365admin1/layer-common 1.11.22 → 1.11.24

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,5 +1,17 @@
1
1
  # @iservice365/layer-common
2
2
 
3
+ ## 1.11.24
4
+
5
+ ### Patch Changes
6
+
7
+ - 68d57fd: Update Enhancement in VMS
8
+
9
+ ## 1.11.23
10
+
11
+ ### Patch Changes
12
+
13
+ - 6d68511: Update layer-comon qr code package
14
+
3
15
  ## 1.11.22
4
16
 
5
17
  ### Patch Changes
@@ -97,7 +97,7 @@ const props = defineProps({
97
97
  site: { type: String, required: true, default: "" },
98
98
  scheduleAreaId: { type: String, required: true, default: "" },
99
99
  type: { type: String, required: true, default: "cleaner" },
100
- scheduleRoute: { type: String, default: "cleaning-schedule" },
100
+ scheduleRoute: { type: String, default: "pest-schedule" },
101
101
  });
102
102
 
103
103
  const { formatDate, back, debounce } = useUtils();
@@ -61,20 +61,20 @@
61
61
 
62
62
  <script setup lang="ts">
63
63
  import useAttendance from "../composables/useAttendance";
64
- import { useAttendancePermission } from "../composables/useAttendancePermission";
65
64
  import useUtils from "../composables/useUtils";
66
65
 
67
66
  const props = defineProps({
68
67
  orgId: { type: String, default: "" },
69
68
  site: { type: String, default: "" },
70
69
  serviceType: { type: String, default: "" },
70
+ canViewAllAttendance: { type: Boolean, default: true },
71
+ canViewAttendanceDetails: { type: Boolean, default: true },
72
+ canManageAttendanceSettings: { type: Boolean, default: false },
71
73
  });
72
74
 
73
- const {
74
- canViewAllAttendance,
75
- canViewAttendanceDetails,
76
- canManageAttendanceSettings,
77
- } = useAttendancePermission();
75
+ const canViewAllAttendance = computed(() => props.canViewAllAttendance);
76
+ const canViewAttendanceDetails = computed(() => props.canViewAttendanceDetails);
77
+ const canManageAttendanceSettings = computed(() => props.canManageAttendanceSettings);
78
78
 
79
79
  const submitting = ref(false);
80
80
  const page = ref(1);
@@ -76,6 +76,15 @@
76
76
  {{ value || "No Status" }}
77
77
  </v-chip>
78
78
  </template>
79
+ <template #item.completedAt="{ value }">
80
+ {{
81
+ formatDate
82
+ ? formatDate(value)
83
+ : value
84
+ ? new Date(value).toLocaleString()
85
+ : ""
86
+ }}
87
+ </template>
79
88
  <template #item.download="{ item }">
80
89
  <v-btn
81
90
  v-if="canDownloadSchedule"
@@ -102,7 +111,6 @@
102
111
  </template>
103
112
 
104
113
  <script lang="ts" setup>
105
- import { useCleaningSchedulePermission } from "../composables/useCleaningSchedulePermission";
106
114
  import useCleaningSchedules from "../composables/useCleaningSchedules";
107
115
  import useUtils from "../composables/useUtils";
108
116
 
@@ -112,6 +120,10 @@ const props = defineProps({
112
120
  type: { type: String, required: true },
113
121
  serviceType: { type: String, default: "" },
114
122
  scheduleRoute: { type: String, default: "cleaning-schedule" },
123
+ canViewSchedules: { type: Boolean, default: true },
124
+ canViewScheduleDetails: { type: Boolean, default: true },
125
+ canDownloadSchedule: { type: Boolean, default: false },
126
+ canManageScheduleTasks: { type: Boolean, default: false },
115
127
  });
116
128
 
117
129
  const startDate = ref("");
@@ -133,7 +145,7 @@ const headers = [
133
145
  { title: "Created Date", value: "createdAt" },
134
146
  { title: "Close in", value: "closeIn" },
135
147
  { title: "Status", value: "status" },
136
- { title: "Completion Date", value: "completionDate" },
148
+ { title: "Completion Date", value: "completedAt" },
137
149
  { title: "", value: "download" },
138
150
  ];
139
151
  const remainingTime = ref({} as Record<string, string>);
@@ -172,12 +184,10 @@ const getCloseInColor = (id: string): string => {
172
184
  return "primary";
173
185
  };
174
186
 
175
- const {
176
- canDownloadSchedule,
177
- canViewSchedules,
178
- canViewScheduleDetails,
179
- canManageScheduleTasks,
180
- } = useCleaningSchedulePermission();
187
+ const canDownloadSchedule = computed(() => props.canDownloadSchedule);
188
+ const canViewSchedules = computed(() => props.canViewSchedules);
189
+ const canViewScheduleDetails = computed(() => props.canViewScheduleDetails);
190
+ const canManageScheduleTasks = computed(() => props.canManageScheduleTasks);
181
191
 
182
192
  const {
183
193
  data: getCleanerChecklistReq,
@@ -441,7 +441,6 @@
441
441
 
442
442
  <script setup lang="ts">
443
443
  import useEquipmentItem from "../composables/useEquipmentItem";
444
- import { useEquipmentItemPermission } from "../composables/useEquipmentItemPermission";
445
444
  import useEquipmentManagement from "../composables/useEquipmentManagement";
446
445
  import useFile from "../composables/useFile";
447
446
  import useUtils from "../composables/useUtils";
@@ -450,9 +449,12 @@ const props = defineProps({
450
449
  orgId: { type: String, default: "" },
451
450
  site: { type: String, default: "" },
452
451
  serviceType: { type: String, default: "" },
452
+ canViewAllEquipmentItems: { type: Boolean, default: true },
453
+ canCreateEquipmentItem: { type: Boolean, default: false },
453
454
  });
454
455
 
455
- const { canCreateEquipmentItem } = useEquipmentItemPermission();
456
+ const canViewAllEquipmentItems = computed(() => props.canViewAllEquipmentItems);
457
+ const canCreateEquipmentItem = computed(() => props.canCreateEquipmentItem);
456
458
 
457
459
  const items = ref<Array<Record<string, any>>>([]);
458
460
  const siteName = ref<string>("");
@@ -247,7 +247,6 @@
247
247
  <script setup lang="ts">
248
248
  import useEquipment from "../composables/useEquipment";
249
249
  import useStock from "../composables/useStock";
250
- import { useEquipmentPermission } from "../composables/useEquipmentPermission";
251
250
  import useUtils from "../composables/useUtils";
252
251
  import useEquipmentManagement from "../composables/useEquipmentManagement";
253
252
 
@@ -255,17 +254,22 @@ const props = defineProps({
255
254
  orgId: { type: String, default: "" },
256
255
  site: { type: String, default: "" },
257
256
  serviceType: { type: String, default: "" },
257
+ canViewEquipments: { type: Boolean, default: true },
258
+ canAddEquipment: { type: Boolean, default: false },
259
+ canUpdateEquipment: { type: Boolean, default: false },
260
+ canDeleteEquipment: { type: Boolean, default: false },
261
+ canAddStock: { type: Boolean, default: false },
262
+ canViewStock: { type: Boolean, default: true },
263
+ canRequestItem: { type: Boolean, default: false },
258
264
  });
259
265
 
260
- const {
261
- canViewEquipments,
262
- canAddEquipment,
263
- canUpdateEquipment,
264
- canDeleteEquipment,
265
- canAddStock,
266
- canViewStock,
267
- canRequestItem,
268
- } = useEquipmentPermission();
266
+ const canViewEquipments = computed(() => props.canViewEquipments);
267
+ const canAddEquipment = computed(() => props.canAddEquipment);
268
+ const canUpdateEquipment = computed(() => props.canUpdateEquipment);
269
+ const canDeleteEquipment = computed(() => props.canDeleteEquipment);
270
+ const canAddStock = computed(() => props.canAddStock);
271
+ const canViewStock = computed(() => props.canViewStock);
272
+ const canRequestItem = computed(() => props.canRequestItem);
269
273
 
270
274
  const items = ref<Array<Record<string, any>>>([]);
271
275
  const siteName = ref<string>("");
@@ -17,7 +17,7 @@
17
17
  </v-col>
18
18
  </v-row>
19
19
  <TableHygiene
20
- :title="'Cleaner Checklist'"
20
+ :title="scheduleTitle"
21
21
  :headers="headers"
22
22
  :items="items"
23
23
  :item-value="'unit'"
@@ -300,7 +300,6 @@
300
300
  </template>
301
301
 
302
302
  <script setup lang="ts">
303
- import { useCleaningSchedulePermission } from "../composables/useCleaningSchedulePermission";
304
303
  import useCleaningSchedules from "../composables/useCleaningSchedules";
305
304
  import useCustomerSite from "../composables/useCustomerSite";
306
305
  import useFile from "../composables/useFile";
@@ -313,13 +312,27 @@ const props = defineProps({
313
312
  scheduleAreaId: { type: String, default: "" },
314
313
  type: { type: String, default: "cleaner" },
315
314
  serviceType: { type: String, default: "" },
315
+ canAddRemarks: { type: Boolean, default: false },
316
+ canManageScheduleTasks: { type: Boolean, default: false },
316
317
  });
317
318
 
318
319
  const { getUnitCleanerChecklist, updateUnitChecklist } = useCleaningSchedules();
319
320
  const { getBySiteAsServiceProvider } = useCustomerSite();
320
321
  const { back } = useUtils();
321
- const { canAddRemarks, canManageScheduleTasks } =
322
- useCleaningSchedulePermission();
322
+
323
+ const route = useRoute();
324
+ const scheduleTitle = computed(() => {
325
+ const path = route.path;
326
+ if (path.includes('cleaning-schedule')) return 'Cleaning Checklist';
327
+ if (path.includes('technician-schedule')) return 'Technician Checklist';
328
+ if (path.includes('landscape-schedule')) return 'Landscape Checklist';
329
+ if (path.includes('pool-schedule')) return 'Pool Checklist';
330
+ if (path.includes('pest-schedule')) return 'Pest Checklist';
331
+ return 'Cleaner Checklist';
332
+ });
333
+
334
+ const canAddRemarks = computed(() => props.canAddRemarks);
335
+ const canManageScheduleTasks = computed(() => props.canManageScheduleTasks);
323
336
 
324
337
  const selectedScheduleStatus = useState<string>(
325
338
  "selectedScheduleStatus",
@@ -2,9 +2,9 @@
2
2
  <v-row no-gutters class="w-100">
3
3
  <v-card class="w-100">
4
4
  <v-card-text>
5
- <v-btn block color="primary-button" :height="40" text="Scan QR Code" class="text-capitalize" disabled
6
- prepend-icon="mdi-qrcode" />
7
- <v-form ref="formRef" v-model="validForm" :disabled="processing" @click="errorMessage = ''">
5
+ <v-btn block color="primary-button" :height="40" text="Scan QR Code" class="text-capitalize"
6
+ prepend-icon="mdi-qrcode" @click="handleScanQRPass" />
7
+ <v-form ref="formRef" v-model="validForm" :disabled="processing" @click="errorScanPassMessage = ''">
8
8
  <v-row no-gutters class="pt-5 ga-2">
9
9
  <v-col cols="12">
10
10
  <InputLabel class="text-capitalize" title="Full Name" required />
@@ -19,10 +19,10 @@
19
19
  </v-col>
20
20
 
21
21
  <v-col cols="12">
22
- <v-autocomplete v-model="selectedPass" v-model:search="passInput"
23
- :hide-no-data="false" class="mt-3" :items="passItemsFilteredFinal"
24
- item-title="prefixAndName" item-value="_id" label="Pass (optional)" variant="outlined"
25
- hide-details density="compact" persistent-hint small-chips>
22
+ <v-autocomplete v-model="selectedPass" v-model:search="passInput" :hide-no-data="false"
23
+ class="mt-3" :items="passItemsFilteredFinal" item-title="prefixAndName" item-value="_id"
24
+ label="Pass (optional)" variant="outlined" density="compact" :error-messages="errorScanPassMessage"
25
+ persistent-hint small-chips>
26
26
  <template v-slot:no-data>
27
27
  <v-list-item density="compact">
28
28
  <v-list-item-title v-if="passInput">
@@ -35,8 +35,7 @@
35
35
  </template>
36
36
 
37
37
  <template v-slot:chip="{ props, item }">
38
- <v-chip v-if="selectedPass" v-bind="props"
39
- prepend-icon="mdi-card-bulleted-outline"
38
+ <v-chip v-if="selectedPass" v-bind="props" prepend-icon="mdi-card-bulleted-outline"
40
39
  :text="item.raw?.prefixAndName"></v-chip>
41
40
  </template>
42
41
  </v-autocomplete>
@@ -62,12 +61,15 @@
62
61
  </v-form>
63
62
  </v-card-text>
64
63
  </v-card>
64
+ <visitor-pass-key-q-r-scanner :dialog="dialog.scanQRCode" v-model:scannedValue="scannedPassValue"
65
+ @close-dialog="dialog.scanQRCode = false" />
65
66
  <v-divider class="my-3" />
66
67
  <v-row v-if="committedMembers.length > 0" no-gutters class="w-100 mt-5 ga-3">
67
68
  <template v-for="member, index in committedMembers" :key="member.nric">
68
69
  <CardMemberInfoSummary :member="membersDisplayed[index]" @remove="handleRemoveMember(index)" />
69
70
  </template>
70
71
  </v-row>
72
+ <!-- <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" /> -->
71
73
  </v-row>
72
74
  </template>
73
75
 
@@ -103,18 +105,33 @@ const { getPassKeysByPageSearch } = usePassKey()
103
105
  const memberForm = reactive<TMemberInfo>({
104
106
  name: "",
105
107
  nric: "",
106
- visitorPass: "",
108
+ visitorPass: [] as { keyId: string }[],
107
109
  contact: ""
108
110
  })
109
111
 
110
112
  const validForm = ref(false)
111
113
  const formRef = ref<HTMLFormElement>()
112
114
  const processing = ref(false);
113
- const errorMessage = ref('')
115
+ const errorScanPassMessage = ref('')
116
+
117
+ const message = ref("");
118
+ const messageColor = ref("");
119
+ const messageSnackbar = ref(false);
120
+
121
+ function showMessage(msg: string, color: string) {
122
+ message.value = msg;
123
+ messageColor.value = color;
124
+ messageSnackbar.value = true;
125
+ }
114
126
 
115
127
  // pass
116
128
  const passInput = ref('')
117
129
  const passItems = ref<TPassKey[]>([])
130
+ const scannedPassValue = ref<string>("")
131
+
132
+ const dialog = reactive({
133
+ scanQRCode: false,
134
+ })
118
135
 
119
136
  const selectedPass = ref<string>('')
120
137
 
@@ -160,7 +177,7 @@ watch(passesData, (data: any) => {
160
177
 
161
178
  const passItemsFilteredFinal = computed(() => {
162
179
  return passItems.value.filter((item: TPassKey) => {
163
- return !props.selectedVisitorPass.some((pass: TPassKeyPayload) => pass.keyId === item._id) && !committedMembers.value.some((member: TMemberInfo) => member.visitorPass === item._id)
180
+ return !props.selectedVisitorPass.some((pass: TPassKeyPayload) => pass.keyId === item._id) && !committedMembers.value.some((member: TMemberInfo) => member.visitorPass?.some((pass) => pass.keyId === item._id))
164
181
  })
165
182
  })
166
183
 
@@ -168,15 +185,34 @@ const membersDisplayed = computed(() => {
168
185
  return committedMembers.value.map((member: TMemberInfo) => {
169
186
  return {
170
187
  ...member,
171
- visitorPass: passItems.value.find((item: TPassKey) => item._id === member.visitorPass)?.prefixAndName || ""
188
+ visitorPass: passItems.value.find((item: TPassKey) => item._id === member.visitorPass?.[0]?.keyId)?.prefixAndName || ""
172
189
  }
173
190
  })
174
191
  })
175
192
 
193
+ function handleScanQRPass() {
194
+ errorScanPassMessage.value = ""
195
+ dialog.scanQRCode = true
196
+ }
197
+
176
198
  watch(selectedPass, (newVal) => {
177
199
  memberForm.visitorPass = [{ keyId: newVal }]
178
200
  })
179
201
 
202
+ watch(scannedPassValue, (newVal) => {
203
+ if (!newVal) return
204
+
205
+ const matchedPass = passItemsFilteredFinal.value.find((p) => p.prefixAndName === newVal)
206
+
207
+ if (matchedPass) {
208
+ selectedPass.value = matchedPass._id ?? ""
209
+ return
210
+ }
211
+
212
+ errorScanPassMessage.value = "Scanned pass not available"
213
+ showMessage("Scanned pass not available", "error")
214
+ })
215
+
180
216
 
181
217
 
182
218
  function handleClearForm() {
@@ -79,16 +79,19 @@
79
79
 
80
80
  <script setup lang="ts">
81
81
  import useAttendance from "../composables/useAttendance";
82
- import { useAttendancePermission } from "../composables/useAttendancePermission";
83
82
 
84
83
  const props = defineProps({
85
84
  orgId: { type: String, default: "" },
86
85
  site: { type: String, default: "" },
87
86
  serviceType: { type: String, default: "" },
87
+ canViewOwnAttendance: { type: Boolean, default: true },
88
+ canCheckInOut: { type: Boolean, default: false },
89
+ canViewAttendanceDetails: { type: Boolean, default: true },
88
90
  });
89
91
 
90
- const { canViewOwnAttendance, canCheckInOut, canViewAttendanceDetails } =
91
- useAttendancePermission();
92
+ const canViewOwnAttendance = computed(() => props.canViewOwnAttendance);
93
+ const canCheckInOut = computed(() => props.canCheckInOut);
94
+ const canViewAttendanceDetails = computed(() => props.canViewAttendanceDetails);
92
95
 
93
96
  const searchInput = ref("");
94
97
  const dialogShowForm = ref(false);