@7365admin1/layer-common 1.10.10 → 1.11.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.
- package/CHANGELOG.md +12 -0
- package/components/AccessCardAddForm.vue +1 -1
- package/components/AccessCardAssignToUnitForm.vue +10 -13
- package/components/AccessCardQrTagging.vue +2 -2
- package/components/Chat/SkeletonLoader.vue +71 -0
- package/components/DashboardMain.vue +176 -0
- package/components/EntryPassInformation.vue +3 -7
- package/components/FileInputWithList.vue +304 -0
- package/components/IncidentReport/IncidentInformation.vue +14 -2
- package/components/IncidentReport/IncidentInformationDownload.vue +22 -9
- package/components/IncidentReport/affectedEntities.vue +5 -0
- package/components/Signature.vue +133 -0
- package/components/SlideCardGroup.vue +194 -0
- package/components/VisitorForm.vue +17 -1
- package/composables/useAccessManagement.ts +25 -6
- package/composables/useComment.ts +147 -0
- package/composables/useFeedback.ts +79 -29
- package/composables/usePDFDownload.ts +1 -1
- package/composables/useWorkOrder.ts +61 -26
- package/package.json +2 -1
- package/public/default-image.svg +4 -0
- package/public/placeholder-image.svg +6 -0
- package/types/comment.d.ts +38 -0
- package/types/dashboard.d.ts +10 -0
- package/types/feedback.d.ts +56 -20
- package/types/work-order.d.ts +54 -18
- package/utils/data.ts +31 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-sheet class="mx-auto">
|
|
3
|
+
<v-slide-group
|
|
4
|
+
class="pa-1"
|
|
5
|
+
show-arrows
|
|
6
|
+
:style="{ backgroundColor: '#FFFF' }"
|
|
7
|
+
>
|
|
8
|
+
<v-slide-group-item
|
|
9
|
+
v-for="(data, idx) in localDataFiles"
|
|
10
|
+
:key="idx"
|
|
11
|
+
v-slot="{ isSelected }"
|
|
12
|
+
>
|
|
13
|
+
<v-card
|
|
14
|
+
:class="['ma-1', isSelected && 'selected']"
|
|
15
|
+
width="150"
|
|
16
|
+
height="100"
|
|
17
|
+
@click="clickable && emit('onClickCarousel', data.path)"
|
|
18
|
+
class="rounded-lg border-thin"
|
|
19
|
+
border=" opacity-50 thin "
|
|
20
|
+
>
|
|
21
|
+
<v-btn
|
|
22
|
+
icon
|
|
23
|
+
variant="text"
|
|
24
|
+
size="x-small"
|
|
25
|
+
class="remove-btn pa-0 ma-0"
|
|
26
|
+
@click.stop="removeFile(data)"
|
|
27
|
+
>
|
|
28
|
+
<v-icon color="red" class="pa-0 ma-0" size="x-large"
|
|
29
|
+
>mdi-close-circle</v-icon
|
|
30
|
+
>
|
|
31
|
+
</v-btn>
|
|
32
|
+
<!-- File Icons -->
|
|
33
|
+
|
|
34
|
+
<v-img :src="data.url" cover height="200">
|
|
35
|
+
<template #placeholder>
|
|
36
|
+
<v-skeleton-loader height="100%" width="100%" />
|
|
37
|
+
</template>
|
|
38
|
+
</v-img>
|
|
39
|
+
<!-- <template v-if="url.type !== 'image'">
|
|
40
|
+
<div
|
|
41
|
+
class="d-flex fill-height align-center justify-center flex-column"
|
|
42
|
+
>
|
|
43
|
+
<v-icon
|
|
44
|
+
:icon="getFileIcon(url.type)"
|
|
45
|
+
size="64"
|
|
46
|
+
:color="getFileColor(url.type)"
|
|
47
|
+
></v-icon>
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
<template v-else>
|
|
54
|
+
<v-img :src="url.path" cover height="200">
|
|
55
|
+
<template #placeholder>
|
|
56
|
+
<v-skeleton-loader height="100%" width="100%" />
|
|
57
|
+
</template>
|
|
58
|
+
</v-img>
|
|
59
|
+
</template> -->
|
|
60
|
+
|
|
61
|
+
<!-- Edit Button -->
|
|
62
|
+
<!-- <div v-if="imgEditable" class="edit-btn">
|
|
63
|
+
<v-btn
|
|
64
|
+
color="primary"
|
|
65
|
+
size="small"
|
|
66
|
+
@click.stop="onImageEdit(url.path, idx)"
|
|
67
|
+
>
|
|
68
|
+
<v-icon start>mdi-pencil</v-icon>
|
|
69
|
+
Edit
|
|
70
|
+
</v-btn>
|
|
71
|
+
</div> -->
|
|
72
|
+
</v-card>
|
|
73
|
+
</v-slide-group-item>
|
|
74
|
+
</v-slide-group>
|
|
75
|
+
</v-sheet>
|
|
76
|
+
|
|
77
|
+
<DrawImage
|
|
78
|
+
v-if="isShowImageEdit"
|
|
79
|
+
:is-show-dialog="isShowImageEdit"
|
|
80
|
+
:image-url="imageUrl"
|
|
81
|
+
:image-idx="imageIdx"
|
|
82
|
+
@on-submit="onImageSubmitEdit"
|
|
83
|
+
@on-close-dialog="isShowImageEdit = false"
|
|
84
|
+
/>
|
|
85
|
+
</template>
|
|
86
|
+
|
|
87
|
+
<script setup lang="ts">
|
|
88
|
+
const { getImage } = useUtils();
|
|
89
|
+
const { attachedFiles } = useUploadFiles();
|
|
90
|
+
|
|
91
|
+
const emit = defineEmits<{
|
|
92
|
+
(event: "onClickCarousel", url: string): void;
|
|
93
|
+
(event: "onImageEdit", url: string, idx: number): void;
|
|
94
|
+
(event: "onFileRemove"): void;
|
|
95
|
+
}>();
|
|
96
|
+
|
|
97
|
+
const props = defineProps<{
|
|
98
|
+
clickable?: boolean;
|
|
99
|
+
imgEditable?: boolean;
|
|
100
|
+
dataFiles?: File[];
|
|
101
|
+
}>();
|
|
102
|
+
const localDataFiles = ref([...props.dataFiles]);
|
|
103
|
+
const isShowImageEdit = ref(false);
|
|
104
|
+
const imageUrl = ref("");
|
|
105
|
+
const imageIdx = ref(0);
|
|
106
|
+
|
|
107
|
+
const getFileType = (url: string) => {
|
|
108
|
+
const extension = url.split(".").pop()?.toLowerCase() || "";
|
|
109
|
+
if (["jpg", "jpeg", "png", "gif", "webp"].includes(extension)) return "image";
|
|
110
|
+
if (["pdf"].includes(extension)) return "pdf";
|
|
111
|
+
if (["doc", "docx"].includes(extension)) return "word";
|
|
112
|
+
return "other";
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const getFileIcon = (type: string) => {
|
|
116
|
+
switch (type) {
|
|
117
|
+
case "pdf":
|
|
118
|
+
return "mdi-file-pdf-box";
|
|
119
|
+
case "word":
|
|
120
|
+
return "mdi-file-word-box";
|
|
121
|
+
default:
|
|
122
|
+
return "mdi-file-outline";
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const getFileColor = (type: string) => {
|
|
127
|
+
switch (type) {
|
|
128
|
+
case "pdf":
|
|
129
|
+
return "red";
|
|
130
|
+
case "word":
|
|
131
|
+
return "blue";
|
|
132
|
+
default:
|
|
133
|
+
return "grey";
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const onImageEdit = (url: string, idx: number) => {
|
|
138
|
+
isShowImageEdit.value = true;
|
|
139
|
+
imageUrl.value = url;
|
|
140
|
+
imageIdx.value = idx;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const onImageSubmitEdit = async (url: string, idx: number) => {
|
|
144
|
+
const response = await getImage(url);
|
|
145
|
+
if (!response) return;
|
|
146
|
+
attachedFiles.value[idx].data = new File(
|
|
147
|
+
[response],
|
|
148
|
+
attachedFiles.value[idx].data?.name
|
|
149
|
+
);
|
|
150
|
+
attachedFiles.value[idx].url = url;
|
|
151
|
+
isShowImageEdit.value = false;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const isImageFile = (type: string) => {
|
|
155
|
+
return type?.startsWith("image/");
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
watch(
|
|
159
|
+
() => props.dataFiles,
|
|
160
|
+
(newDataFiles) => {
|
|
161
|
+
localDataFiles.value = [...newDataFiles];
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const removeFile = (file) => {
|
|
166
|
+
const index = localDataFiles.value.findIndex(
|
|
167
|
+
(dataFile) => dataFile.id === file.id
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
if (index !== -1) {
|
|
171
|
+
localDataFiles.value.splice(index, 1);
|
|
172
|
+
emit("onFileRemove", file);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
</script>
|
|
176
|
+
|
|
177
|
+
<style scoped>
|
|
178
|
+
.edit-btn {
|
|
179
|
+
position: absolute;
|
|
180
|
+
bottom: 8px;
|
|
181
|
+
right: 8px;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.selected {
|
|
185
|
+
border: 2px solid var(--v-theme-primary);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.remove-btn {
|
|
189
|
+
position: absolute;
|
|
190
|
+
top: 0px;
|
|
191
|
+
right: 0px;
|
|
192
|
+
z-index: 2;
|
|
193
|
+
}
|
|
194
|
+
</style>
|
|
@@ -322,6 +322,7 @@ const { requiredRule, debounce, UTCToLocalTIme } = useUtils();
|
|
|
322
322
|
const { getSiteById, getSiteLevels, getSiteUnits } = useSiteSettings();
|
|
323
323
|
const { createVisitor, typeFieldMap, contractorTypes, getVisitors, updateVisitor } = useVisitor();
|
|
324
324
|
const { getBySiteId: getEntryPassSettingsBySiteId } = useSiteEntryPassSettings();
|
|
325
|
+
const { createVisitorPass } = useAccessManagement();
|
|
325
326
|
const { findPersonByNRIC, findPersonByContact, searchCompanyList, findUsersByPlateNumber } = usePeople()
|
|
326
327
|
const { getById: getUnitDataById } = useBuildingUnit()
|
|
327
328
|
|
|
@@ -354,7 +355,7 @@ const visitor = reactive<Partial<TVisitorPayload>>({
|
|
|
354
355
|
|
|
355
356
|
const passType = ref("");
|
|
356
357
|
const passQuantity = ref<number | null>(1);
|
|
357
|
-
const passCards = ref<string[]>([]);
|
|
358
|
+
const passCards = ref<{ _id: string; cardNo: string }[]>([]);
|
|
358
359
|
|
|
359
360
|
const registeredUnitCompanyName = ref('N/A')
|
|
360
361
|
|
|
@@ -906,6 +907,21 @@ async function submit() {
|
|
|
906
907
|
try {
|
|
907
908
|
const res = await createVisitor(payload);
|
|
908
909
|
if (res) {
|
|
910
|
+
if (prop.type === "contractor" && passType.value) {
|
|
911
|
+
const visitorId = res?._id;
|
|
912
|
+
const acmUrl = entryPassSettings.value?.data?.settings?.acm_url;
|
|
913
|
+
if (visitorId && acmUrl) {
|
|
914
|
+
await createVisitorPass({
|
|
915
|
+
site: prop.site,
|
|
916
|
+
unitId: visitor.unit!,
|
|
917
|
+
quantity: passQuantity.value ?? 1,
|
|
918
|
+
type: passType.value === "QR" ? "QRCODE" : passType.value,
|
|
919
|
+
nfcCards: passCards.value,
|
|
920
|
+
acm_url: acmUrl,
|
|
921
|
+
visitorId,
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
}
|
|
909
925
|
if (createMore.value) {
|
|
910
926
|
emit("done:more");
|
|
911
927
|
} else emit("done");
|
|
@@ -111,8 +111,8 @@ export default function useAccessManagement() {
|
|
|
111
111
|
site: string;
|
|
112
112
|
userType: string;
|
|
113
113
|
type: string;
|
|
114
|
-
accessLevel: string;
|
|
115
|
-
liftAccessLevel: string;
|
|
114
|
+
accessLevel: string | null;
|
|
115
|
+
liftAccessLevel: string | null;
|
|
116
116
|
}) {
|
|
117
117
|
return useNuxtApp().$api<Record<string, any>>(
|
|
118
118
|
`/api/access-management/access-and-lift-cards`,
|
|
@@ -122,8 +122,8 @@ export default function useAccessManagement() {
|
|
|
122
122
|
site: params.site,
|
|
123
123
|
userType: params.userType,
|
|
124
124
|
type: params.type,
|
|
125
|
-
accessLevel: params.accessLevel,
|
|
126
|
-
liftAccessLevel: params.liftAccessLevel,
|
|
125
|
+
...(params.accessLevel != null ? { accessLevel: params.accessLevel } : {}),
|
|
126
|
+
...(params.liftAccessLevel != null ? { liftAccessLevel: params.liftAccessLevel } : {}),
|
|
127
127
|
},
|
|
128
128
|
}
|
|
129
129
|
);
|
|
@@ -135,8 +135,8 @@ export default function useAccessManagement() {
|
|
|
135
135
|
type: string;
|
|
136
136
|
site: string;
|
|
137
137
|
userType: string;
|
|
138
|
-
accessLevel: string;
|
|
139
|
-
liftAccessLevel: string;
|
|
138
|
+
accessLevel: string | null;
|
|
139
|
+
liftAccessLevel: string | null;
|
|
140
140
|
}) {
|
|
141
141
|
return useNuxtApp().$api<Record<string, any>>(
|
|
142
142
|
`/api/access-management/assign-access-card`,
|
|
@@ -261,6 +261,24 @@ export default function useAccessManagement() {
|
|
|
261
261
|
);
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
function createVisitorPass(payload: {
|
|
265
|
+
site: string;
|
|
266
|
+
unitId: string;
|
|
267
|
+
quantity: number;
|
|
268
|
+
type: string;
|
|
269
|
+
nfcCards: { _id: string; cardNo: string }[];
|
|
270
|
+
acm_url: string;
|
|
271
|
+
visitorId: string;
|
|
272
|
+
}) {
|
|
273
|
+
return useNuxtApp().$api<Record<string, any>>(
|
|
274
|
+
`/api/access-management/visitor`,
|
|
275
|
+
{
|
|
276
|
+
method: "POST",
|
|
277
|
+
body: payload,
|
|
278
|
+
}
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
264
282
|
return {
|
|
265
283
|
getDoorAccessLevels,
|
|
266
284
|
getLiftAccessLevels,
|
|
@@ -280,5 +298,6 @@ export default function useAccessManagement() {
|
|
|
280
298
|
getAllVisitorAccessCardsQrTags,
|
|
281
299
|
getAvailableContractorCards,
|
|
282
300
|
generateQrVms,
|
|
301
|
+
createVisitorPass,
|
|
283
302
|
};
|
|
284
303
|
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const { currentUser } = useLocalAuth();
|
|
2
|
+
export default function useComment() {
|
|
3
|
+
class MComment implements TCommentChat {
|
|
4
|
+
_id?: string;
|
|
5
|
+
comment: string;
|
|
6
|
+
attachments?: TAttachment[];
|
|
7
|
+
createdBy: string;
|
|
8
|
+
workOrder: string;
|
|
9
|
+
createdAt?: string;
|
|
10
|
+
updatedAt?: string;
|
|
11
|
+
createdByName?: string;
|
|
12
|
+
createdByType?: string;
|
|
13
|
+
feedback?: string;
|
|
14
|
+
justify?: string | undefined;
|
|
15
|
+
seenByNames: string;
|
|
16
|
+
|
|
17
|
+
constructor(comment: Partial<TCommentChat> = {}) {
|
|
18
|
+
this._id = comment._id || "";
|
|
19
|
+
this.comment = comment.comment || "";
|
|
20
|
+
this.attachments = comment.attachments || [];
|
|
21
|
+
this.workOrder = comment.workOrder || "";
|
|
22
|
+
this.createdAt = comment.createdAt
|
|
23
|
+
? comment.createdAt.toString()
|
|
24
|
+
: undefined;
|
|
25
|
+
this.updatedAt = comment.updatedAt || "";
|
|
26
|
+
this.createdBy = comment.createdBy || "";
|
|
27
|
+
this.createdByName = comment.createdByName || "";
|
|
28
|
+
this.createdByType = comment.createdByType || "";
|
|
29
|
+
this.justify = comment.justify || "";
|
|
30
|
+
this.feedback = comment.feedback || "";
|
|
31
|
+
this.seenByNames = comment.seenByNames ?? "";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const comment = useState("comment", () => new MComment());
|
|
36
|
+
const comments = useState("comments", (): TCommentChat[] => []);
|
|
37
|
+
const page = useState("commentPage", () => 1);
|
|
38
|
+
const itemsPerPage = useState("itemsPerPage", () => 2);
|
|
39
|
+
const search = useState("commentSearch", () => "");
|
|
40
|
+
const pageRange = useState("commentPageRange", () => "-- - -- of --");
|
|
41
|
+
const isCommentsLoaded = useState("isCommentsLoaded", () => false);
|
|
42
|
+
|
|
43
|
+
function addComment(payload: TCommentChat) {
|
|
44
|
+
delete payload._id;
|
|
45
|
+
return useNuxtApp().$api<{ value?: { message: string } }>(
|
|
46
|
+
"/api/comments/v1",
|
|
47
|
+
{
|
|
48
|
+
method: "POST",
|
|
49
|
+
body: payload,
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getCommentById(id: string) {
|
|
55
|
+
return useNuxtApp().$api(`/api/auth/comments/id/${id}`, {
|
|
56
|
+
method: "GET",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function setComment(data?: TCommentChat) {
|
|
61
|
+
comment.value = new MComment(data);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const isInviteValid = useState("isInviteValid", () => false);
|
|
65
|
+
|
|
66
|
+
function getCommentsByWorkOrder(id: string) {
|
|
67
|
+
return useNuxtApp().$api(`/api/comments/v1/work-order/${id}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getCommentsByWorkOrderId(id: string) {
|
|
71
|
+
return useNuxtApp().$api(`/api/comments/v1/work-order/${id}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getCommentsByFeedBackId(id: string, type?: string) {
|
|
75
|
+
const commentFeedbackOrWOD =
|
|
76
|
+
type === "workOrder" ? "work-order" : "feedback";
|
|
77
|
+
return useNuxtApp().$api(`/api/comments/v1/${commentFeedbackOrWOD}/${id}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function setComments(id: string, type?: string) {
|
|
81
|
+
try {
|
|
82
|
+
isCommentsLoaded.value = true;
|
|
83
|
+
const _comments = (await getCommentsByFeedBackId(
|
|
84
|
+
id,
|
|
85
|
+
type
|
|
86
|
+
)) as TCommentPaginated;
|
|
87
|
+
|
|
88
|
+
let updateSeenIds: any = [];
|
|
89
|
+
|
|
90
|
+
comments.value = _comments.items
|
|
91
|
+
.map((comment: any) => {
|
|
92
|
+
if (comment.createdBy === currentUser.value._id) {
|
|
93
|
+
comment.justify = "end";
|
|
94
|
+
} else {
|
|
95
|
+
comment.justify = "start";
|
|
96
|
+
if (
|
|
97
|
+
((Array.isArray(comment.seenBy) &&
|
|
98
|
+
!comment.seenBy.includes(currentUser.value._id)) ||
|
|
99
|
+
!comment?.seenBy) &&
|
|
100
|
+
comment?._id
|
|
101
|
+
) {
|
|
102
|
+
updateSeenIds.push(comment._id);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return comment;
|
|
106
|
+
})
|
|
107
|
+
.sort(
|
|
108
|
+
(firstComment: any, secondComment: any) =>
|
|
109
|
+
new Date(firstComment.createdAt).getTime() -
|
|
110
|
+
new Date(secondComment.createdAt).getTime()
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
if (Array.isArray(updateSeenIds) && updateSeenIds.length > 0) {
|
|
114
|
+
const seenBy = await updateSeenBy(updateSeenIds, currentUser.value._id);
|
|
115
|
+
}
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.log("error :", error);
|
|
118
|
+
} finally {
|
|
119
|
+
isCommentsLoaded.value = false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function updateSeenBy(ids: string[], seenById: string) {
|
|
124
|
+
return useNuxtApp().$api(`/api/comments/v1/seen-by`, {
|
|
125
|
+
method: "PUT",
|
|
126
|
+
body: { seenById, ids },
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
comment,
|
|
132
|
+
comments,
|
|
133
|
+
page,
|
|
134
|
+
itemsPerPage,
|
|
135
|
+
pageRange,
|
|
136
|
+
addComment,
|
|
137
|
+
setComment,
|
|
138
|
+
search,
|
|
139
|
+
isCommentsLoaded,
|
|
140
|
+
isInviteValid,
|
|
141
|
+
setComments,
|
|
142
|
+
getCommentById,
|
|
143
|
+
getCommentsByWorkOrderId,
|
|
144
|
+
updateSeenBy,
|
|
145
|
+
getCommentsByFeedBackId,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
@@ -1,36 +1,63 @@
|
|
|
1
1
|
export default function useFeedback() {
|
|
2
|
-
|
|
2
|
+
class MFeedback implements TFeedback {
|
|
3
|
+
_id?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
subject?: string;
|
|
6
|
+
service?: string;
|
|
7
|
+
provider?: string | null;
|
|
8
|
+
location: string;
|
|
9
|
+
status?: string;
|
|
10
|
+
createdBy?: any;
|
|
11
|
+
createdByName?: string;
|
|
12
|
+
createdByEmail?: string;
|
|
13
|
+
attachments?: TAttachment[];
|
|
14
|
+
workOrders?: object[];
|
|
15
|
+
workOrder?: Record<string, any>;
|
|
16
|
+
organization: string;
|
|
17
|
+
site: string;
|
|
18
|
+
createdAt?: string | Date;
|
|
19
|
+
updatedAt?: string | Date;
|
|
20
|
+
app: string;
|
|
21
|
+
assignee?: string;
|
|
22
|
+
assigneeName?: string;
|
|
23
|
+
assigneeInfo?: Record<string, any>;
|
|
24
|
+
statusUpdates?: any[];
|
|
25
|
+
attachedIR?: Array<Record<string, any>>;
|
|
26
|
+
|
|
27
|
+
constructor(feedback: Partial<TFeedback> = {}) {
|
|
28
|
+
this._id = feedback._id || "";
|
|
29
|
+
this.description = feedback.description || "";
|
|
30
|
+
this.subject = feedback.subject || "";
|
|
31
|
+
this.service = feedback.service || "";
|
|
32
|
+
this.status = feedback.status || "";
|
|
33
|
+
this.createdBy = feedback.createdBy || {};
|
|
34
|
+
this.provider = feedback.provider || null;
|
|
35
|
+
this.location = feedback.location || "";
|
|
36
|
+
this.attachments = feedback.attachments || [];
|
|
37
|
+
this.workOrders = feedback.workOrders || [];
|
|
38
|
+
this.workOrder = feedback.workOrder ?? {};
|
|
39
|
+
this.organization = feedback.organization || "";
|
|
40
|
+
this.site = feedback.site || "";
|
|
41
|
+
this.createdAt = "";
|
|
42
|
+
this.updatedAt = "";
|
|
43
|
+
this.app = feedback.app || "";
|
|
44
|
+
this.assignee = feedback.assignee || "";
|
|
45
|
+
this.assigneeName = feedback.assigneeName || "";
|
|
46
|
+
this.assigneeInfo = feedback.assigneeInfo ?? {};
|
|
47
|
+
this.statusUpdates = feedback.statusUpdates ?? [];
|
|
48
|
+
this.attachedIR = feedback.attachedIR ?? [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const feedback = useState("feedback", () => new MFeedback());
|
|
53
|
+
const feedbacks = useState("feedbacks", (): TFeedback[] => []);
|
|
3
54
|
const page = useState("page", () => 1);
|
|
4
55
|
const pages = useState("pages", () => 0);
|
|
5
56
|
const pageRange = useState("pageRange", () => "-- - -- of --");
|
|
6
57
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
_id: "",
|
|
11
|
-
attachments: [],
|
|
12
|
-
category: "",
|
|
13
|
-
categoryInfo: "",
|
|
14
|
-
subject: "",
|
|
15
|
-
location: "",
|
|
16
|
-
description: "",
|
|
17
|
-
createdBy: "",
|
|
18
|
-
createdAt: "",
|
|
19
|
-
updatedAt: "",
|
|
20
|
-
status: "pending",
|
|
21
|
-
metadata: {
|
|
22
|
-
serviceProvider: "",
|
|
23
|
-
assignee: "",
|
|
24
|
-
organization: "",
|
|
25
|
-
site: "",
|
|
26
|
-
name: "",
|
|
27
|
-
signature: "",
|
|
28
|
-
attachments: "",
|
|
29
|
-
completedAt: "",
|
|
30
|
-
},
|
|
31
|
-
workOrderNo: "",
|
|
32
|
-
})
|
|
33
|
-
);
|
|
58
|
+
function setFeedback(data?: TFeedback) {
|
|
59
|
+
feedback.value = data || new MFeedback();
|
|
60
|
+
}
|
|
34
61
|
|
|
35
62
|
const { currentUser } = useLocalAuth();
|
|
36
63
|
|
|
@@ -89,7 +116,7 @@ export default function useFeedback() {
|
|
|
89
116
|
});
|
|
90
117
|
}
|
|
91
118
|
|
|
92
|
-
function createFeedback(payload:
|
|
119
|
+
function createFeedback(payload: TFeedback) {
|
|
93
120
|
return useNuxtApp().$api<Record<string, any>>("/api/feedbacks2", {
|
|
94
121
|
method: "POST",
|
|
95
122
|
body: payload,
|
|
@@ -135,8 +162,29 @@ export default function useFeedback() {
|
|
|
135
162
|
);
|
|
136
163
|
}
|
|
137
164
|
|
|
165
|
+
function addFeedBackWorkOrder(payload: any) {
|
|
166
|
+
return useNuxtApp().$api<Record<string, any>>(
|
|
167
|
+
"/api/feedbacks2/create-work-order",
|
|
168
|
+
{
|
|
169
|
+
method: "POST",
|
|
170
|
+
body: payload,
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function updateStatusFeedback(payload: any) {
|
|
176
|
+
return useNuxtApp().$api<Record<string, any>>(
|
|
177
|
+
"/api/feedbacks2/status-update",
|
|
178
|
+
{
|
|
179
|
+
method: "POST",
|
|
180
|
+
body: payload,
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
138
185
|
return {
|
|
139
186
|
feedbacks,
|
|
187
|
+
setFeedback,
|
|
140
188
|
feedback,
|
|
141
189
|
page,
|
|
142
190
|
pages,
|
|
@@ -148,5 +196,7 @@ export default function useFeedback() {
|
|
|
148
196
|
deleteFeedback,
|
|
149
197
|
updateFeedbackServiceProvider,
|
|
150
198
|
updateStatusComplete,
|
|
199
|
+
addFeedBackWorkOrder,
|
|
200
|
+
updateStatusFeedback,
|
|
151
201
|
};
|
|
152
202
|
}
|
|
@@ -11,7 +11,7 @@ export default function(){
|
|
|
11
11
|
const downloadUrl = window.URL.createObjectURL(res);
|
|
12
12
|
const a = document.createElement("a");
|
|
13
13
|
a.href = downloadUrl;
|
|
14
|
-
a.download =
|
|
14
|
+
a.download = title; // Specify the file name
|
|
15
15
|
document.body.appendChild(a);
|
|
16
16
|
a.click(); // Trigger the download
|
|
17
17
|
window.URL.revokeObjectURL(downloadUrl); // Clean up
|
|
@@ -1,34 +1,68 @@
|
|
|
1
1
|
export default function useWorkOrder() {
|
|
2
|
+
class MWorkOrder implements TWorkOrder {
|
|
3
|
+
_id?: string;
|
|
4
|
+
description: string;
|
|
5
|
+
service: string;
|
|
6
|
+
subject: string | null;
|
|
7
|
+
provider: string | null;
|
|
8
|
+
providerName?: string;
|
|
9
|
+
status?: string;
|
|
10
|
+
assignee?: string | TUser;
|
|
11
|
+
assigneeName?: string;
|
|
12
|
+
attachments?: string[];
|
|
13
|
+
createdBy?: string | TUser;
|
|
14
|
+
createdByName?: string;
|
|
15
|
+
site: string;
|
|
16
|
+
organization: string;
|
|
17
|
+
location?: string;
|
|
18
|
+
comments?: TComment[];
|
|
19
|
+
createdAt?: string | Date;
|
|
20
|
+
updatedAt?: string | Date;
|
|
21
|
+
feedback?: string;
|
|
22
|
+
statusUpdates?: any[];
|
|
23
|
+
prefix?: string;
|
|
24
|
+
noOfDigits?: any;
|
|
25
|
+
number?: number;
|
|
26
|
+
version?: number;
|
|
27
|
+
isHighPriority?: boolean;
|
|
28
|
+
|
|
29
|
+
constructor(workOrder: Partial<TWorkOrder> = {}) {
|
|
30
|
+
this._id = workOrder._id || "";
|
|
31
|
+
this.description = workOrder.description || "";
|
|
32
|
+
this.service = workOrder.service || "";
|
|
33
|
+
this.subject = workOrder.subject || null;
|
|
34
|
+
this.provider = workOrder.provider || null;
|
|
35
|
+
this.providerName = workOrder.providerName || "";
|
|
36
|
+
this.status = workOrder.status || "";
|
|
37
|
+
this.assignee = workOrder.assignee;
|
|
38
|
+
this.attachments = workOrder.attachments || [];
|
|
39
|
+
this.createdBy = workOrder.createdBy || "";
|
|
40
|
+
this.createdByName = workOrder.createdByName;
|
|
41
|
+
this.site = workOrder.site || "";
|
|
42
|
+
this.organization = workOrder.organization || "";
|
|
43
|
+
this.location = workOrder.location || "";
|
|
44
|
+
this.assigneeName = workOrder.assigneeName || "";
|
|
45
|
+
this.comments = workOrder.comments || [];
|
|
46
|
+
this.createdAt = "";
|
|
47
|
+
this.updatedAt = "";
|
|
48
|
+
this.feedback = workOrder.feedback || "";
|
|
49
|
+
this.prefix = workOrder.prefix || "";
|
|
50
|
+
this.noOfDigits = workOrder.noOfDigits || 1;
|
|
51
|
+
this.number = workOrder.number || 1;
|
|
52
|
+
this.version = workOrder.version || 0;
|
|
53
|
+
this.isHighPriority = workOrder.isHighPriority || false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const workOrder = useState("workOrder", () => new MWorkOrder());
|
|
2
58
|
const workOrders = useState<Array<TWorkOrder>>("workOrders", () => []);
|
|
3
59
|
const page = useState("page", () => 1);
|
|
4
60
|
const pages = useState("pages", () => 0);
|
|
5
61
|
const pageRange = useState("pageRange", () => "-- - -- of --");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
subject: "",
|
|
11
|
-
description: "",
|
|
12
|
-
createdBy: "",
|
|
13
|
-
service: "",
|
|
14
|
-
provider: "",
|
|
15
|
-
organization: "",
|
|
16
|
-
site: "",
|
|
17
|
-
createdByName: "",
|
|
18
|
-
assignee: "",
|
|
19
|
-
location: "",
|
|
20
|
-
attachments: [],
|
|
21
|
-
feedback: "",
|
|
22
|
-
status: "",
|
|
23
|
-
createdAt: "",
|
|
24
|
-
updatedAt: "",
|
|
25
|
-
deletedAt: "",
|
|
26
|
-
highPriority: false,
|
|
27
|
-
block: "",
|
|
28
|
-
level: "",
|
|
29
|
-
unit: "",
|
|
30
|
-
serviceProvider: "",
|
|
31
|
-
}));
|
|
62
|
+
|
|
63
|
+
function setWorkOrder(data?: TWorkOrder) {
|
|
64
|
+
workOrder.value = data || new MWorkOrder();
|
|
65
|
+
}
|
|
32
66
|
|
|
33
67
|
async function getWorkOrders({
|
|
34
68
|
page = 1,
|
|
@@ -100,6 +134,7 @@ export default function useWorkOrder() {
|
|
|
100
134
|
|
|
101
135
|
return {
|
|
102
136
|
workOrders,
|
|
137
|
+
setWorkOrder,
|
|
103
138
|
workOrder,
|
|
104
139
|
page,
|
|
105
140
|
pages,
|