@7365admin1/layer-common 1.11.37 → 1.11.39
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 +12 -0
- package/components/CameraForm.vue +58 -13
- package/components/CameraMain.vue +19 -3
- package/components/ClientMain.vue +91 -70
- package/components/InvitationClientForm.vue +37 -19
- package/components/InvitationForm.vue +35 -5
- package/components/Layout/NavigationDrawer.vue +49 -26
- package/components/RolePermissionFormCreate.vue +106 -46
- package/components/ScheduleTaskForm.vue +168 -18
- package/components/ScheduleTaskMain.vue +115 -4
- package/components/VehicleForm.vue +6 -1
- package/components/VehicleManagement.vue +27 -17
- package/components/VisitorManagement.vue +4 -4
- package/composables/useMember.ts +16 -0
- package/composables/useSiteSettings.ts +1 -0
- package/composables/useVehicle.ts +14 -1
- package/composables/useWorkOrder.ts +13 -7
- package/package.json +1 -1
- package/types/camera.d.ts +1 -0
- package/types/org.d.ts +1 -0
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</v-row>
|
|
21
21
|
</v-toolbar>
|
|
22
22
|
|
|
23
|
-
<v-card-text class="pa-
|
|
23
|
+
<v-card-text class="pa-4 flex-grow-1" style="overflow-y: auto">
|
|
24
24
|
<v-form ref="formRef" v-model="valid">
|
|
25
25
|
<v-row dense>
|
|
26
26
|
<v-col cols="12">
|
|
@@ -52,7 +52,10 @@
|
|
|
52
52
|
<div class="text-caption text-medium-emphasis mb-2">
|
|
53
53
|
{{ selectedDates.length }} date(s) selected
|
|
54
54
|
</div>
|
|
55
|
-
<div
|
|
55
|
+
<div
|
|
56
|
+
v-if="selectedDates.length > 0"
|
|
57
|
+
class="d-flex flex-wrap ga-2"
|
|
58
|
+
>
|
|
56
59
|
<v-chip
|
|
57
60
|
v-for="date in selectedDates"
|
|
58
61
|
:key="date"
|
|
@@ -121,6 +124,108 @@
|
|
|
121
124
|
</v-select>
|
|
122
125
|
</v-col>
|
|
123
126
|
|
|
127
|
+
<v-col v-if="selectedAreas.length > 0" cols="12">
|
|
128
|
+
<InputLabel title="Units Under Selected Areas" />
|
|
129
|
+
<v-card variant="outlined" rounded class="mb-4">
|
|
130
|
+
<v-list density="compact" nav>
|
|
131
|
+
<template
|
|
132
|
+
v-for="(area, idx) in selectedAreas"
|
|
133
|
+
:key="area.value || area._id"
|
|
134
|
+
>
|
|
135
|
+
<v-divider v-if="idx > 0" />
|
|
136
|
+
|
|
137
|
+
<v-list-item
|
|
138
|
+
rounded="0"
|
|
139
|
+
class="px-3"
|
|
140
|
+
@click="toggleArea(area.value || area._id)"
|
|
141
|
+
>
|
|
142
|
+
<template #prepend>
|
|
143
|
+
<v-icon size="18" color="medium-emphasis">
|
|
144
|
+
{{
|
|
145
|
+
openAreas.includes(area.value || area._id)
|
|
146
|
+
? "mdi-chevron-down"
|
|
147
|
+
: "mdi-chevron-right"
|
|
148
|
+
}}
|
|
149
|
+
</v-icon>
|
|
150
|
+
</template>
|
|
151
|
+
|
|
152
|
+
<v-list-item-title class="text-body-2 font-weight-medium">
|
|
153
|
+
{{ area.name }}
|
|
154
|
+
</v-list-item-title>
|
|
155
|
+
|
|
156
|
+
<template #append>
|
|
157
|
+
<v-progress-circular
|
|
158
|
+
v-if="
|
|
159
|
+
loadingUnits &&
|
|
160
|
+
!(area.value || area._id in fetchedAreaUnits)
|
|
161
|
+
"
|
|
162
|
+
size="14"
|
|
163
|
+
width="2"
|
|
164
|
+
indeterminate
|
|
165
|
+
color="primary"
|
|
166
|
+
/>
|
|
167
|
+
<v-chip
|
|
168
|
+
v-else
|
|
169
|
+
size="x-small"
|
|
170
|
+
variant="tonal"
|
|
171
|
+
color="primary"
|
|
172
|
+
>
|
|
173
|
+
{{
|
|
174
|
+
(fetchedAreaUnits[area.value || area._id] || [])
|
|
175
|
+
.length
|
|
176
|
+
}}
|
|
177
|
+
</v-chip>
|
|
178
|
+
</template>
|
|
179
|
+
</v-list-item>
|
|
180
|
+
|
|
181
|
+
<v-expand-transition>
|
|
182
|
+
<div v-show="openAreas.includes(area.value || area._id)">
|
|
183
|
+
<v-card-text class="pt-1 pb-3 px-3">
|
|
184
|
+
<div
|
|
185
|
+
v-if="
|
|
186
|
+
loadingUnits &&
|
|
187
|
+
!(area.value || area._id in fetchedAreaUnits)
|
|
188
|
+
"
|
|
189
|
+
class="d-flex flex-wrap ga-2"
|
|
190
|
+
>
|
|
191
|
+
<v-skeleton-loader
|
|
192
|
+
v-for="n in 4"
|
|
193
|
+
:key="n"
|
|
194
|
+
type="chip"
|
|
195
|
+
width="80"
|
|
196
|
+
/>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
<div
|
|
200
|
+
v-else-if="
|
|
201
|
+
(fetchedAreaUnits[area.value || area._id] || [])
|
|
202
|
+
.length > 0
|
|
203
|
+
"
|
|
204
|
+
class="d-flex flex-wrap ga-1"
|
|
205
|
+
>
|
|
206
|
+
<v-chip
|
|
207
|
+
v-for="unit in fetchedAreaUnits[
|
|
208
|
+
area.value || area._id
|
|
209
|
+
]"
|
|
210
|
+
:key="unit.unit"
|
|
211
|
+
size="small"
|
|
212
|
+
variant="tonal"
|
|
213
|
+
>
|
|
214
|
+
{{ unit.name }}
|
|
215
|
+
</v-chip>
|
|
216
|
+
</div>
|
|
217
|
+
|
|
218
|
+
<span v-else class="text-caption text-disabled">
|
|
219
|
+
No units configured
|
|
220
|
+
</span>
|
|
221
|
+
</v-card-text>
|
|
222
|
+
</div>
|
|
223
|
+
</v-expand-transition>
|
|
224
|
+
</template>
|
|
225
|
+
</v-list>
|
|
226
|
+
</v-card>
|
|
227
|
+
</v-col>
|
|
228
|
+
|
|
124
229
|
<v-col cols="12">
|
|
125
230
|
<InputLabel for="description" title="Task Description" />
|
|
126
231
|
<v-textarea
|
|
@@ -138,18 +243,16 @@
|
|
|
138
243
|
</v-form>
|
|
139
244
|
</v-card-text>
|
|
140
245
|
|
|
141
|
-
<v-
|
|
142
|
-
|
|
143
|
-
<v-card-actions class="pa-0">
|
|
144
|
-
<v-row no-gutters class="fill-width">
|
|
246
|
+
<v-toolbar class="pa-0" density="compact">
|
|
247
|
+
<v-row no-gutters>
|
|
145
248
|
<v-col cols="6" class="pa-0">
|
|
146
249
|
<v-btn
|
|
147
250
|
block
|
|
148
251
|
variant="text"
|
|
149
|
-
class="text-none
|
|
150
|
-
size="
|
|
252
|
+
class="text-none"
|
|
253
|
+
size="large"
|
|
151
254
|
@click="close"
|
|
152
|
-
height="
|
|
255
|
+
height="48"
|
|
153
256
|
:disabled="submitting"
|
|
154
257
|
>
|
|
155
258
|
Cancel
|
|
@@ -161,7 +264,7 @@
|
|
|
161
264
|
variant="flat"
|
|
162
265
|
color="primary"
|
|
163
266
|
class="text-none font-weight-bold rounded-0"
|
|
164
|
-
height="
|
|
267
|
+
height="48"
|
|
165
268
|
@click="submitTask"
|
|
166
269
|
:loading="submitting"
|
|
167
270
|
>
|
|
@@ -169,7 +272,7 @@
|
|
|
169
272
|
</v-btn>
|
|
170
273
|
</v-col>
|
|
171
274
|
</v-row>
|
|
172
|
-
</v-
|
|
275
|
+
</v-toolbar>
|
|
173
276
|
</v-card>
|
|
174
277
|
</v-dialog>
|
|
175
278
|
|
|
@@ -202,7 +305,7 @@ const props = defineProps({
|
|
|
202
305
|
const show = defineModel("show", { type: Boolean, default: false });
|
|
203
306
|
const emit = defineEmits(["saved", "close", "refresh"]);
|
|
204
307
|
|
|
205
|
-
const { getAreas } = useAreas();
|
|
308
|
+
const { getAreas, getAreaById } = useAreas();
|
|
206
309
|
const { createScheduleTask, updateScheduleTask, getScheduleTaskById } =
|
|
207
310
|
useScheduleTask();
|
|
208
311
|
|
|
@@ -215,19 +318,52 @@ const subject = ref("");
|
|
|
215
318
|
const description = ref("");
|
|
216
319
|
const scheduleTime = ref("08:00");
|
|
217
320
|
const pickerDates = ref<Date[]>([]);
|
|
218
|
-
// Derived from pickerDates — single source of truth, always in sync
|
|
219
321
|
const selectedDates = computed(() =>
|
|
220
322
|
pickerDates.value.map((d) => toLocalISO(d)).sort()
|
|
221
323
|
);
|
|
222
324
|
|
|
223
325
|
const selectedAreas = ref<any[]>([]);
|
|
326
|
+
const loadingUnits = ref(false);
|
|
327
|
+
const fetchedAreaUnits = ref<Record<string, { name: string; unit: string }[]>>(
|
|
328
|
+
{}
|
|
329
|
+
);
|
|
330
|
+
const openAreas = ref<string[]>([]);
|
|
331
|
+
|
|
332
|
+
const selectedAreaIds = computed(() =>
|
|
333
|
+
selectedAreas.value.map((a: any) => a.value || a._id)
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
watch(selectedAreaIds, async (ids, prevIds) => {
|
|
337
|
+
openAreas.value = ids.slice();
|
|
338
|
+
|
|
339
|
+
const toFetch = ids.filter(
|
|
340
|
+
(id) => !prevIds?.includes(id) && !(id in fetchedAreaUnits.value)
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
if (!toFetch.length) return;
|
|
344
|
+
|
|
345
|
+
loadingUnits.value = true;
|
|
346
|
+
try {
|
|
347
|
+
await Promise.all(
|
|
348
|
+
toFetch.map(async (id) => {
|
|
349
|
+
try {
|
|
350
|
+
const result = await getAreaById(id);
|
|
351
|
+
fetchedAreaUnits.value[id] = result?.units || [];
|
|
352
|
+
} catch {
|
|
353
|
+
fetchedAreaUnits.value[id] = [];
|
|
354
|
+
}
|
|
355
|
+
})
|
|
356
|
+
);
|
|
357
|
+
} finally {
|
|
358
|
+
loadingUnits.value = false;
|
|
359
|
+
}
|
|
360
|
+
});
|
|
224
361
|
|
|
225
362
|
const message = ref("");
|
|
226
363
|
const messageSnackbar = ref(false);
|
|
227
364
|
const messageColor = ref("success");
|
|
228
365
|
const areasList = ref<any[]>([]);
|
|
229
366
|
|
|
230
|
-
// Helper function to generate all dates between start and end
|
|
231
367
|
const generateDateRange = (start: Date, end: Date): Date[] => {
|
|
232
368
|
const dates: Date[] = [];
|
|
233
369
|
const current = new Date(start);
|
|
@@ -240,7 +376,6 @@ const generateDateRange = (start: Date, end: Date): Date[] => {
|
|
|
240
376
|
return dates;
|
|
241
377
|
};
|
|
242
378
|
|
|
243
|
-
// Helper: convert a Date to a local YYYY-MM-DD string (avoids UTC-shift issues)
|
|
244
379
|
const toLocalISO = (d: Date): string => {
|
|
245
380
|
const y = d.getFullYear();
|
|
246
381
|
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
@@ -248,7 +383,6 @@ const toLocalISO = (d: Date): string => {
|
|
|
248
383
|
return `${y}-${m}-${day}`;
|
|
249
384
|
};
|
|
250
385
|
|
|
251
|
-
// Remove a single date from the selection via chip close
|
|
252
386
|
const removeDate = (dateISO: string) => {
|
|
253
387
|
pickerDates.value = pickerDates.value.filter(
|
|
254
388
|
(d) => toLocalISO(d) !== dateISO
|
|
@@ -261,12 +395,23 @@ const showMessage = (text: string, color: string = "success") => {
|
|
|
261
395
|
messageSnackbar.value = true;
|
|
262
396
|
};
|
|
263
397
|
|
|
398
|
+
const toggleArea = (id: string) => {
|
|
399
|
+
const idx = openAreas.value.indexOf(id);
|
|
400
|
+
if (idx === -1) {
|
|
401
|
+
openAreas.value.push(id);
|
|
402
|
+
} else {
|
|
403
|
+
openAreas.value.splice(idx, 1);
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
|
|
264
407
|
const resetForm = () => {
|
|
265
408
|
subject.value = "";
|
|
266
409
|
description.value = "";
|
|
267
410
|
scheduleTime.value = "08:00";
|
|
268
411
|
pickerDates.value = [];
|
|
269
412
|
selectedAreas.value = [];
|
|
413
|
+
fetchedAreaUnits.value = {};
|
|
414
|
+
openAreas.value = [];
|
|
270
415
|
};
|
|
271
416
|
|
|
272
417
|
const setFormFromTask = (task: any) => {
|
|
@@ -310,7 +455,8 @@ const setFormFromTask = (task: any) => {
|
|
|
310
455
|
|
|
311
456
|
const { data: getAreasReq, pending: loadingAreas } = await useLazyAsyncData(
|
|
312
457
|
`get-areas-${props.site}`,
|
|
313
|
-
() =>
|
|
458
|
+
() =>
|
|
459
|
+
getAreas({ site: props.site, limit: 1000, serviceType: props.serviceType }),
|
|
314
460
|
{
|
|
315
461
|
watch: [show, () => props.site],
|
|
316
462
|
immediate: false,
|
|
@@ -377,7 +523,11 @@ const submitTask = async () => {
|
|
|
377
523
|
(props.taskData as any)?._id || (props.taskData as any)?.id;
|
|
378
524
|
response = await updateScheduleTask(taskId, payload);
|
|
379
525
|
} else {
|
|
380
|
-
response = await createScheduleTask({
|
|
526
|
+
response = await createScheduleTask({
|
|
527
|
+
...payload,
|
|
528
|
+
site: props.site,
|
|
529
|
+
serviceType: props.serviceType,
|
|
530
|
+
});
|
|
381
531
|
}
|
|
382
532
|
|
|
383
533
|
showMessage(
|
|
@@ -156,6 +156,73 @@
|
|
|
156
156
|
</v-col>
|
|
157
157
|
</v-row>
|
|
158
158
|
|
|
159
|
+
<v-row
|
|
160
|
+
v-if="selectedTask.areas && selectedTask.areas.length > 0"
|
|
161
|
+
no-gutters
|
|
162
|
+
class="mb-2"
|
|
163
|
+
>
|
|
164
|
+
<v-col cols="12">
|
|
165
|
+
<div class="text-subtitle-2 font-weight-bold mb-2">Units Under Selected Areas:</div>
|
|
166
|
+
<v-card variant="outlined" rounded>
|
|
167
|
+
<v-list density="compact" nav>
|
|
168
|
+
<template
|
|
169
|
+
v-for="(area, idx) in selectedTask.areas"
|
|
170
|
+
:key="area.value || area._id"
|
|
171
|
+
>
|
|
172
|
+
<v-divider v-if="Number(idx) > 0" />
|
|
173
|
+
<v-list-item
|
|
174
|
+
:title="area.name"
|
|
175
|
+
class="font-weight-medium"
|
|
176
|
+
@click="toggleViewArea(area.value || area._id)"
|
|
177
|
+
>
|
|
178
|
+
<template #prepend>
|
|
179
|
+
<v-icon size="16">
|
|
180
|
+
{{
|
|
181
|
+
openViewAreas.includes(area.value || area._id)
|
|
182
|
+
? 'mdi-chevron-down'
|
|
183
|
+
: 'mdi-chevron-right'
|
|
184
|
+
}}
|
|
185
|
+
</v-icon>
|
|
186
|
+
</template>
|
|
187
|
+
<template #append>
|
|
188
|
+
<v-progress-circular
|
|
189
|
+
v-if="loadingViewUnits && !(area.value || area._id in fetchedViewAreaUnits)"
|
|
190
|
+
size="14"
|
|
191
|
+
width="2"
|
|
192
|
+
indeterminate
|
|
193
|
+
color="primary"
|
|
194
|
+
/>
|
|
195
|
+
<v-chip v-else size="x-small" variant="tonal" color="primary">
|
|
196
|
+
{{ (fetchedViewAreaUnits[area.value || area._id] || []).length }}
|
|
197
|
+
</v-chip>
|
|
198
|
+
</template>
|
|
199
|
+
</v-list-item>
|
|
200
|
+
<v-expand-transition>
|
|
201
|
+
<div v-show="openViewAreas.includes(area.value || area._id)">
|
|
202
|
+
<v-card-text class="px-3 py-2">
|
|
203
|
+
<div
|
|
204
|
+
v-if="(fetchedViewAreaUnits[area.value || area._id] || []).length > 0"
|
|
205
|
+
class="d-flex flex-wrap ga-3"
|
|
206
|
+
>
|
|
207
|
+
<v-chip
|
|
208
|
+
v-for="unit in fetchedViewAreaUnits[area.value || area._id]"
|
|
209
|
+
:key="unit.unit"
|
|
210
|
+
size="small"
|
|
211
|
+
variant="tonal"
|
|
212
|
+
>
|
|
213
|
+
{{ unit.name }}
|
|
214
|
+
</v-chip>
|
|
215
|
+
</div>
|
|
216
|
+
<span v-else class="text-caption text-disabled">No units configured</span>
|
|
217
|
+
</v-card-text>
|
|
218
|
+
</div>
|
|
219
|
+
</v-expand-transition>
|
|
220
|
+
</template>
|
|
221
|
+
</v-list>
|
|
222
|
+
</v-card>
|
|
223
|
+
</v-col>
|
|
224
|
+
</v-row>
|
|
225
|
+
|
|
159
226
|
<v-row v-if="selectedTask.description" no-gutters class="mb-2">
|
|
160
227
|
<v-col cols="5" class="text-subtitle-2 font-weight-bold">
|
|
161
228
|
Description:
|
|
@@ -205,12 +272,14 @@
|
|
|
205
272
|
<v-toolbar>
|
|
206
273
|
<v-row no-gutters class="fill-height px-6" align="center">
|
|
207
274
|
<span class="font-weight-bold text-h6 text-capitalize">
|
|
208
|
-
Delete {{ selectedTask?.title ||
|
|
275
|
+
Delete {{ selectedTask?.title || "Schedule Task" }}
|
|
209
276
|
</span>
|
|
210
277
|
</v-row>
|
|
211
278
|
</v-toolbar>
|
|
212
279
|
<v-card-text>
|
|
213
|
-
<span class="text-subtitle-2"
|
|
280
|
+
<span class="text-subtitle-2"
|
|
281
|
+
>Are you sure you want to delete this schedule task?</span
|
|
282
|
+
>
|
|
214
283
|
</v-card-text>
|
|
215
284
|
|
|
216
285
|
<v-toolbar class="pa-0" density="compact">
|
|
@@ -257,6 +326,8 @@
|
|
|
257
326
|
|
|
258
327
|
<script lang="ts" setup>
|
|
259
328
|
import useScheduleTask from "../composables/useScheduleTask";
|
|
329
|
+
import useUtils from "../composables/useUtils";
|
|
330
|
+
import useAreas from "../composables/useAreas";
|
|
260
331
|
|
|
261
332
|
const props = defineProps({
|
|
262
333
|
orgId: { type: String, required: true },
|
|
@@ -271,13 +342,17 @@ const props = defineProps({
|
|
|
271
342
|
});
|
|
272
343
|
|
|
273
344
|
const { formatDate, debounce } = useUtils();
|
|
274
|
-
const { getScheduleTasks, getScheduleTaskById, deleteScheduleTask } =
|
|
345
|
+
const { getScheduleTasks, getScheduleTaskById, deleteScheduleTask } =
|
|
346
|
+
useScheduleTask();
|
|
347
|
+
const { getAreaById } = useAreas();
|
|
275
348
|
|
|
276
349
|
const canViewScheduleTasks = computed(() => props.canViewScheduleTasks);
|
|
277
350
|
const canCreateScheduleTask = computed(() => props.canCreateScheduleTask);
|
|
278
351
|
const canUpdateScheduleTask = computed(() => props.canUpdateScheduleTask);
|
|
279
352
|
const canDeleteScheduleTask = computed(() => props.canDeleteScheduleTask);
|
|
280
|
-
const canViewScheduleTaskDetails = computed(
|
|
353
|
+
const canViewScheduleTaskDetails = computed(
|
|
354
|
+
() => props.canViewScheduleTaskDetails
|
|
355
|
+
);
|
|
281
356
|
|
|
282
357
|
const page = ref(1);
|
|
283
358
|
const pages = ref(0);
|
|
@@ -295,6 +370,42 @@ const message = ref("");
|
|
|
295
370
|
const messageSnackbar = ref(false);
|
|
296
371
|
const messageColor = ref("success");
|
|
297
372
|
|
|
373
|
+
const loadingViewUnits = ref(false);
|
|
374
|
+
const fetchedViewAreaUnits = ref<Record<string, { name: string; unit: string }[]>>({});
|
|
375
|
+
const openViewAreas = ref<string[]>([]);
|
|
376
|
+
|
|
377
|
+
const toggleViewArea = (id: string) => {
|
|
378
|
+
const idx = openViewAreas.value.indexOf(id);
|
|
379
|
+
if (idx === -1) openViewAreas.value.push(id);
|
|
380
|
+
else openViewAreas.value.splice(idx, 1);
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
watch(dialogShowMoreActions, async (isOpen) => {
|
|
384
|
+
if (!isOpen) return;
|
|
385
|
+
const areas = (selectedTask.value?.areas || []) as any[];
|
|
386
|
+
if (areas.length === 0) return;
|
|
387
|
+
openViewAreas.value = areas.map((a) => a.value || a._id);
|
|
388
|
+
const toFetch = areas
|
|
389
|
+
.map((a) => a.value || a._id)
|
|
390
|
+
.filter((id) => id && !(id in fetchedViewAreaUnits.value));
|
|
391
|
+
if (toFetch.length === 0) return;
|
|
392
|
+
loadingViewUnits.value = true;
|
|
393
|
+
try {
|
|
394
|
+
await Promise.all(
|
|
395
|
+
toFetch.map(async (id: string) => {
|
|
396
|
+
try {
|
|
397
|
+
const result = await getAreaById(id);
|
|
398
|
+
fetchedViewAreaUnits.value[id] = result?.units || [];
|
|
399
|
+
} catch {
|
|
400
|
+
fetchedViewAreaUnits.value[id] = [];
|
|
401
|
+
}
|
|
402
|
+
})
|
|
403
|
+
);
|
|
404
|
+
} finally {
|
|
405
|
+
loadingViewUnits.value = false;
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
298
409
|
const items = ref<any[]>([]);
|
|
299
410
|
|
|
300
411
|
const headers = [
|
|
@@ -775,7 +775,12 @@ onMounted(() => {
|
|
|
775
775
|
vehicle.seasonPassType = prop.vehicleData.seasonPassType || '';
|
|
776
776
|
vehicle.end = prop.vehicleData.end || '';
|
|
777
777
|
vehicle.start = prop.vehicleData.start || '';
|
|
778
|
-
vehicle.plateNumber = prop.vehicleData.
|
|
778
|
+
vehicle.plateNumber = prop.vehicleData.plateNumber
|
|
779
|
+
vehicle.peopleId = prop.vehicleData.peopleId || '';
|
|
780
|
+
|
|
781
|
+
if(prop.type === "seasonpass"){
|
|
782
|
+
showSubscriptionDateOptions.value = true;
|
|
783
|
+
}
|
|
779
784
|
}
|
|
780
785
|
}, 300);
|
|
781
786
|
})
|
|
@@ -37,13 +37,15 @@
|
|
|
37
37
|
</v-dialog>
|
|
38
38
|
|
|
39
39
|
<v-dialog v-model="dialog.createVehicle" v-if="vehicleType" width="450" persistent>
|
|
40
|
-
<VehicleForm :type="vehicleType" :mode="mode" :vehicle-data="selectedVehicleObject"
|
|
41
|
-
|
|
40
|
+
<VehicleForm :type="vehicleType" :mode="mode" :vehicle-data="selectedVehicleObject"
|
|
41
|
+
:plate-number-id="selectedPlateNumberId" @back="handleBackToSelection" @done="handleAddVehicleComplete"
|
|
42
|
+
:org="org" :site="props.site" @close:all="handleCloseAll" />
|
|
42
43
|
</v-dialog>
|
|
43
44
|
|
|
44
45
|
<v-dialog v-model="dialog.updateVehicle" v-if="vehicleType" width="450" persistent>
|
|
45
|
-
<VehicleForm :type="vehicleType" :mode="mode" :vehicle-data="selectedPlateNumberObject"
|
|
46
|
-
|
|
46
|
+
<VehicleForm :type="vehicleType" :mode="mode" :vehicle-data="selectedPlateNumberObject"
|
|
47
|
+
:plate-number-id="selectedPlateNumberId" @back="handleBackToSelection" @done="handleAddVehicleComplete"
|
|
48
|
+
:org="org" :site="props.site" @close:all="handleCloseAll" @close="handleCloseAll" />
|
|
47
49
|
</v-dialog>
|
|
48
50
|
|
|
49
51
|
<!-- <v-dialog v-model="dialog.updateVehicle" v-if="vehicleType" width="450" persistent>
|
|
@@ -77,7 +79,8 @@
|
|
|
77
79
|
</template>
|
|
78
80
|
<v-list density="compact">
|
|
79
81
|
<v-list-item v-if="(plateNumberItem as TPlateNumber)?.status == 'active'"
|
|
80
|
-
title="Edit Vehicle" prepend-icon="mdi-pencil"
|
|
82
|
+
title="Edit Vehicle" prepend-icon="mdi-pencil"
|
|
83
|
+
@click="handleEditVehicleAction(plateNumberItem as TPlateNumber)" />
|
|
81
84
|
<v-list-item
|
|
82
85
|
v-if="props.app === 'property_management_agency' && (plateNumberItem as TPlateNumber)?.status == 'pending'"
|
|
83
86
|
title="Approve" prepend-icon="mdi-check-circle" base-color="success"
|
|
@@ -110,7 +113,7 @@
|
|
|
110
113
|
<v-col v-else-if="selectedVehicleObject[key]" cols="12">
|
|
111
114
|
<span class="d-flex ga-3 align-center"><strong>{{ label }}:</strong> {{ formatValues(key,
|
|
112
115
|
selectedVehicleObject[key])
|
|
113
|
-
|
|
116
|
+
}}</span>
|
|
114
117
|
</v-col>
|
|
115
118
|
</template>
|
|
116
119
|
</v-row>
|
|
@@ -184,7 +187,7 @@ const plateHeaders = [
|
|
|
184
187
|
|
|
185
188
|
|
|
186
189
|
const { formatCamelCaseToWords, formatDate, debounce } = useUtils();
|
|
187
|
-
const { getVehicles, deleteVehicle, formatVehicleStatus, approveVehicle, updateVehicle,
|
|
190
|
+
const { getVehicles, deleteVehicle, formatVehicleStatus, approveVehicle, updateVehicle, getSpecificVehicleById } = useVehicle();
|
|
188
191
|
|
|
189
192
|
const items = ref<Array<Record<string, any>>>([]);
|
|
190
193
|
const page = ref(1);
|
|
@@ -322,23 +325,30 @@ async function handleEditVehicleAction(item: TPlateNumber) {
|
|
|
322
325
|
|
|
323
326
|
try {
|
|
324
327
|
loadingPlateNumberDetails.value = true;
|
|
325
|
-
const res = await
|
|
326
|
-
|
|
328
|
+
const res = await getSpecificVehicleById(selectedPlateNumberId.value as string)
|
|
329
|
+
|
|
330
|
+
if (res.type === 'blocklist') {
|
|
331
|
+
vehicleType.value = "blocklist";
|
|
332
|
+
} else {
|
|
333
|
+
if (res?.seasonPassType) {
|
|
327
334
|
vehicleType.value = "seasonpass";
|
|
328
335
|
} else {
|
|
329
|
-
vehicleType.value =
|
|
336
|
+
vehicleType.value = "whitelist";
|
|
330
337
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
selectedPlateNumberObject.value = res || null;
|
|
342
|
+
dialog.showMoreActions = false;
|
|
343
|
+
mode.value = "edit";
|
|
344
|
+
dialog.updateVehicle = true;
|
|
345
|
+
|
|
336
346
|
} catch (error) {
|
|
337
347
|
console.error("Error fetching vehicle details:", error);
|
|
338
348
|
} finally {
|
|
339
349
|
loadingPlateNumberDetails.value = false;
|
|
340
|
-
}
|
|
341
|
-
|
|
350
|
+
}
|
|
351
|
+
|
|
342
352
|
}
|
|
343
353
|
|
|
344
354
|
function handleDeleteVehicleAction(item: TPlateNumber) {
|
|
@@ -1331,10 +1331,10 @@ const {
|
|
|
1331
1331
|
params.status = activeTab.value;
|
|
1332
1332
|
}
|
|
1333
1333
|
|
|
1334
|
-
if (activeTab.value !== "registered") {
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
}
|
|
1334
|
+
// if (activeTab.value !== "registered") {
|
|
1335
|
+
// delete params.type;
|
|
1336
|
+
// delete params.checkedOut;
|
|
1337
|
+
// }
|
|
1338
1338
|
|
|
1339
1339
|
return await getVisitors(params);
|
|
1340
1340
|
},
|
package/composables/useMember.ts
CHANGED
|
@@ -93,6 +93,21 @@ export default function useMember() {
|
|
|
93
93
|
}
|
|
94
94
|
);
|
|
95
95
|
}
|
|
96
|
+
|
|
97
|
+
function createMemberDirect(payload: {
|
|
98
|
+
userId: string;
|
|
99
|
+
orgId: string;
|
|
100
|
+
roleId: string;
|
|
101
|
+
app: string;
|
|
102
|
+
siteId?: string;
|
|
103
|
+
siteName?:string;
|
|
104
|
+
}) {
|
|
105
|
+
return useNuxtApp().$api<TMember>('/api/members/direct', {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
body: payload,
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
96
111
|
return {
|
|
97
112
|
members,
|
|
98
113
|
member,
|
|
@@ -107,5 +122,6 @@ export default function useMember() {
|
|
|
107
122
|
getByUserIdType,
|
|
108
123
|
updateMemberStatus,
|
|
109
124
|
updateMemberRole,
|
|
125
|
+
createMemberDirect
|
|
110
126
|
};
|
|
111
127
|
}
|
|
@@ -131,6 +131,18 @@ export default function useVehicle() {
|
|
|
131
131
|
return { label, color }
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
// fetch specific plateNumber Vehicle data
|
|
135
|
+
|
|
136
|
+
function getSpecificVehicleById(id: string){
|
|
137
|
+
return useNuxtApp().$api<Record<string, any>>(
|
|
138
|
+
`/api/vehicles/specific/${id}`,
|
|
139
|
+
{
|
|
140
|
+
method: "GET",
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
134
146
|
return {
|
|
135
147
|
getVehicles,
|
|
136
148
|
addVehicle,
|
|
@@ -141,6 +153,7 @@ export default function useVehicle() {
|
|
|
141
153
|
getVehicleByNRIC,
|
|
142
154
|
formatVehicleStatus,
|
|
143
155
|
approveVehicle,
|
|
144
|
-
searchMultipleVehiclesByUnitId
|
|
156
|
+
searchMultipleVehiclesByUnitId,
|
|
157
|
+
getSpecificVehicleById
|
|
145
158
|
};
|
|
146
159
|
}
|
|
@@ -137,15 +137,21 @@ export default function useWorkOrder() {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
function deleteWorkOrder(id: string) {
|
|
140
|
-
return useNuxtApp().$api<Record<string, any>>(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
method: "PUT",
|
|
144
|
-
// query: { id },
|
|
145
|
-
}
|
|
146
|
-
);
|
|
140
|
+
return useNuxtApp().$api<Record<string, any>>(`/api/work-orders/${id}`, {
|
|
141
|
+
method: "DELETE",
|
|
142
|
+
});
|
|
147
143
|
}
|
|
148
144
|
|
|
145
|
+
// function deleteWorkOrder(id: string) {
|
|
146
|
+
// return useNuxtApp().$api<Record<string, any>>(
|
|
147
|
+
// `/api/work-orders/deleted/work-order/${id}`,
|
|
148
|
+
// {
|
|
149
|
+
// method: "PUT",
|
|
150
|
+
// // query: { id },
|
|
151
|
+
// }
|
|
152
|
+
// );
|
|
153
|
+
// }
|
|
154
|
+
|
|
149
155
|
function getWorkOrderSettings(_workOrderSettings: Record<string, any>) {
|
|
150
156
|
return useNuxtApp().$api<Record<string, any>>(
|
|
151
157
|
"/api/work-order-settings/get-by-site",
|