@7365admin1/layer-common 1.11.2 → 1.11.4
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 +2 -2
- package/components/AreaMain.vue +4 -0
- package/components/DashboardMain.vue +2 -2
- package/components/{SupplyManagementMain.vue → EquipmentManagementMain.vue} +107 -115
- package/components/ManageChecklistMain.vue +68 -13
- package/components/OvernightParkingAvailability.vue +267 -0
- package/components/OvernightParkingManagement.vue +130 -0
- package/components/Signature.vue +36 -28
- package/components/UnitMain.vue +4 -1
- package/components/VisitorForm.vue +44 -14
- package/composables/useAccessManagement.ts +11 -0
- package/composables/useAreas.ts +3 -0
- package/composables/useComment.ts +1 -1
- package/composables/useFacilityUtils.ts +140 -0
- package/composables/useFeedback.ts +1 -1
- package/composables/useLocalAuth.ts +1 -0
- package/composables/useSiteSettings.ts +21 -0
- package/composables/useUnits.ts +9 -6
- package/composables/useWorkOrder.ts +50 -18
- package/nuxt.config.ts +2 -1
- package/package.json +1 -1
- package/pages/require-organization-membership.vue +3 -3
- package/types/area.d.ts +1 -0
- package/types/dashboard.d.ts +4 -3
- package/types/overnight-parking.d.ts +35 -0
- package/types/user.d.ts +1 -1
- package/types/work-order.d.ts +1 -0
- package/utils/data.ts +17 -0
- package/components/EquipmentManagement.vue +0 -292
package/composables/useAreas.ts
CHANGED
|
@@ -5,6 +5,7 @@ export default function useAreas() {
|
|
|
5
5
|
page = 1,
|
|
6
6
|
limit = 10,
|
|
7
7
|
type = "",
|
|
8
|
+
serviceType = "",
|
|
8
9
|
} = {}) {
|
|
9
10
|
return useNuxtApp().$api<Record<string, any>>(
|
|
10
11
|
`/api/hygiene-areas/site/${site}`,
|
|
@@ -15,6 +16,7 @@ export default function useAreas() {
|
|
|
15
16
|
page,
|
|
16
17
|
limit,
|
|
17
18
|
type,
|
|
19
|
+
serviceType,
|
|
18
20
|
},
|
|
19
21
|
},
|
|
20
22
|
);
|
|
@@ -30,6 +32,7 @@ export default function useAreas() {
|
|
|
30
32
|
set: payload.set,
|
|
31
33
|
type: payload.type,
|
|
32
34
|
units: payload.units,
|
|
35
|
+
serviceType: payload.serviceType,
|
|
33
36
|
},
|
|
34
37
|
},
|
|
35
38
|
);
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export default function(){
|
|
2
|
+
|
|
3
|
+
function generateTimeSlots(
|
|
4
|
+
intervalHours: number,
|
|
5
|
+
startTime?: string | null,
|
|
6
|
+
endTime?: string | null
|
|
7
|
+
): TTimeSlotOption[] {
|
|
8
|
+
if (!intervalHours || intervalHours <= 0) {
|
|
9
|
+
throw new Error("Interval must be greater than 0");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const intervalMinutes = intervalHours * 60;
|
|
13
|
+
const startMinutes = toMinutes(startTime ?? "00:00");
|
|
14
|
+
const endMinutes = toMinutes(endTime ?? "24:00");
|
|
15
|
+
|
|
16
|
+
const slots: TTimeSlotOption[] = [];
|
|
17
|
+
let key = 1;
|
|
18
|
+
|
|
19
|
+
let current = startMinutes + intervalMinutes;
|
|
20
|
+
|
|
21
|
+
for (; current <= endMinutes; current += intervalMinutes) {
|
|
22
|
+
slots.push({
|
|
23
|
+
key: key++,
|
|
24
|
+
time: toTimeString(current),
|
|
25
|
+
disabled: false
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return slots;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const toMinutes = (time: string): number => {
|
|
33
|
+
const [h, m] = time.split(":").map(Number);
|
|
34
|
+
return h * 60 + m;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const toTimeString = (minutes: number): string => {
|
|
38
|
+
const hours = Math.floor(minutes / 60);
|
|
39
|
+
const mins = minutes % 60;
|
|
40
|
+
return `${hours.toString().padStart(2, "0")}:${mins.toString().padStart(2, "0")}`;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
function generateTimeSlotsFromStart(
|
|
44
|
+
intervalHours: number,
|
|
45
|
+
startTime?: string | null,
|
|
46
|
+
endTime?: string | null
|
|
47
|
+
): TTimeSlotOption[] {
|
|
48
|
+
if (!intervalHours || intervalHours <= 0) {
|
|
49
|
+
throw new Error("Interval must be greater than 0");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const intervalMinutes = intervalHours * 60;
|
|
53
|
+
const startMinutes = toMinutes(startTime ?? "00:00");
|
|
54
|
+
const endMinutes = toMinutes(endTime ?? "24:00");
|
|
55
|
+
|
|
56
|
+
const slots: TTimeSlotOption[] = [];
|
|
57
|
+
let key = 1;
|
|
58
|
+
|
|
59
|
+
let current = startMinutes
|
|
60
|
+
|
|
61
|
+
for (; current <= endMinutes; current += intervalMinutes) {
|
|
62
|
+
slots.push({
|
|
63
|
+
key: key++,
|
|
64
|
+
time: toTimeString(current),
|
|
65
|
+
disabled: false
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return slots;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 11/24/2025, 09:05 format
|
|
73
|
+
function toLocalTimeNumeric(utcString: string) {
|
|
74
|
+
return new Date(utcString).toLocaleString("en-US", {
|
|
75
|
+
year: "numeric",
|
|
76
|
+
month: "2-digit",
|
|
77
|
+
day: "2-digit",
|
|
78
|
+
hour: "2-digit",
|
|
79
|
+
minute: "2-digit",
|
|
80
|
+
hour12: false,
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
const monthlyOptions = [
|
|
87
|
+
{ value: 1, title: "1st" },
|
|
88
|
+
{ value: 2, title: "2nd" },
|
|
89
|
+
{ value: 3, title: "3rd" },
|
|
90
|
+
{ value: 4, title: "4th" },
|
|
91
|
+
{ value: 5, title: "5th" },
|
|
92
|
+
{ value: 6, title: "6th" },
|
|
93
|
+
{ value: 7, title: "7th" },
|
|
94
|
+
{ value: 8, title: "8th" },
|
|
95
|
+
{ value: 9, title: "9th" },
|
|
96
|
+
{ value: 10, title: "10th" },
|
|
97
|
+
{ value: 11, title: "11th" },
|
|
98
|
+
{ value: 12, title: "12th" },
|
|
99
|
+
{ value: 13, title: "13th" },
|
|
100
|
+
{ value: 14, title: "14th" },
|
|
101
|
+
{ value: 15, title: "15th" },
|
|
102
|
+
{ value: 16, title: "16th" },
|
|
103
|
+
{ value: 17, title: "17th" },
|
|
104
|
+
{ value: 18, title: "18th" },
|
|
105
|
+
{ value: 19, title: "19th" },
|
|
106
|
+
{ value: 20, title: "20th" },
|
|
107
|
+
{ value: 21, title: "21st" },
|
|
108
|
+
{ value: 22, title: "22nd" },
|
|
109
|
+
{ value: 23, title: "23rd" },
|
|
110
|
+
{ value: 24, title: "24th" },
|
|
111
|
+
{ value: 25, title: "25th" },
|
|
112
|
+
{ value: 26, title: "26th" },
|
|
113
|
+
{ value: 27, title: "27th" },
|
|
114
|
+
{ value: 28, title: "28th" },
|
|
115
|
+
{ value: "Last Day", title: "Last Day" }
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
function defaultCurrencyObject (){
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
symbol: "S$",
|
|
123
|
+
code: "SGD",
|
|
124
|
+
taxType: "GST",
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
generateTimeSlots,
|
|
131
|
+
toMinutes,
|
|
132
|
+
toTimeString,
|
|
133
|
+
generateTimeSlotsFromStart,
|
|
134
|
+
monthlyOptions,
|
|
135
|
+
toLocalTimeNumeric,
|
|
136
|
+
defaultCurrencyObject
|
|
137
|
+
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
}
|
|
@@ -108,6 +108,25 @@ export default function () {
|
|
|
108
108
|
);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
async function getOvernightParkingAvailability(siteId: string): Promise<{ data: TOvernightParkingAvailability }> {
|
|
112
|
+
return await useNuxtApp().$api<TOvernightParkingAvailability>(
|
|
113
|
+
`/api/overnight-parking-approval-settings/site/${siteId}`,
|
|
114
|
+
{
|
|
115
|
+
method: "GET",
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function updateOvernightParkingAvailability(siteId: string, payload: TOvernightParkingAvailability) {
|
|
121
|
+
return await useNuxtApp().$api<Record<string, any>>(
|
|
122
|
+
`/api/overnight-parking-approval-settings/site/${siteId}`,
|
|
123
|
+
{
|
|
124
|
+
method: "PUT",
|
|
125
|
+
body: JSON.stringify(payload),
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
111
130
|
return {
|
|
112
131
|
getSiteById,
|
|
113
132
|
getSiteLevels,
|
|
@@ -119,5 +138,7 @@ export default function () {
|
|
|
119
138
|
updateSiteCamera,
|
|
120
139
|
deleteSiteCameraById,
|
|
121
140
|
updateSitebyId,
|
|
141
|
+
getOvernightParkingAvailability,
|
|
142
|
+
updateOvernightParkingAvailability
|
|
122
143
|
};
|
|
123
144
|
}
|
package/composables/useUnits.ts
CHANGED
|
@@ -4,6 +4,7 @@ export default function useUnits() {
|
|
|
4
4
|
search = "",
|
|
5
5
|
page = 1,
|
|
6
6
|
limit = 10,
|
|
7
|
+
serviceType = "",
|
|
7
8
|
} = {}) {
|
|
8
9
|
return useNuxtApp().$api<Record<string, any>>(
|
|
9
10
|
`/api/hygiene-units/site/${site}`,
|
|
@@ -13,20 +14,22 @@ export default function useUnits() {
|
|
|
13
14
|
search,
|
|
14
15
|
page,
|
|
15
16
|
limit,
|
|
17
|
+
serviceType,
|
|
16
18
|
},
|
|
17
|
-
}
|
|
19
|
+
}
|
|
18
20
|
);
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
function createUnit(name: string, site: string) {
|
|
23
|
+
function createUnit(name: string, site: string, serviceType: string) {
|
|
22
24
|
return useNuxtApp().$api<Record<string, any>>(
|
|
23
25
|
`/api/hygiene-units/site/${site}`,
|
|
24
26
|
{
|
|
25
27
|
method: "POST",
|
|
26
28
|
body: {
|
|
27
29
|
name,
|
|
30
|
+
serviceType,
|
|
28
31
|
},
|
|
29
|
-
}
|
|
32
|
+
}
|
|
30
33
|
);
|
|
31
34
|
}
|
|
32
35
|
|
|
@@ -38,7 +41,7 @@ export default function useUnits() {
|
|
|
38
41
|
body: {
|
|
39
42
|
name,
|
|
40
43
|
},
|
|
41
|
-
}
|
|
44
|
+
}
|
|
42
45
|
);
|
|
43
46
|
}
|
|
44
47
|
|
|
@@ -47,7 +50,7 @@ export default function useUnits() {
|
|
|
47
50
|
`/api/hygiene-units/id/${id}`,
|
|
48
51
|
{
|
|
49
52
|
method: "DELETE",
|
|
50
|
-
}
|
|
53
|
+
}
|
|
51
54
|
);
|
|
52
55
|
}
|
|
53
56
|
|
|
@@ -60,7 +63,7 @@ export default function useUnits() {
|
|
|
60
63
|
{
|
|
61
64
|
method: "POST",
|
|
62
65
|
body: formData,
|
|
63
|
-
}
|
|
66
|
+
}
|
|
64
67
|
);
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -9,6 +9,7 @@ export default function useWorkOrder() {
|
|
|
9
9
|
status?: string;
|
|
10
10
|
assignee?: string | TUser;
|
|
11
11
|
assigneeName?: string;
|
|
12
|
+
assigneeInfo?: Record<string, any>;
|
|
12
13
|
attachments?: string[];
|
|
13
14
|
createdBy?: string | TUser;
|
|
14
15
|
createdByName?: string;
|
|
@@ -66,33 +67,63 @@ export default function useWorkOrder() {
|
|
|
66
67
|
|
|
67
68
|
async function getWorkOrders({
|
|
68
69
|
page = 1,
|
|
69
|
-
site = "",
|
|
70
|
-
status = "to-do",
|
|
71
|
-
search = "",
|
|
72
70
|
limit = 10,
|
|
73
|
-
|
|
71
|
+
organization,
|
|
72
|
+
provider,
|
|
73
|
+
providerService,
|
|
74
|
+
site,
|
|
75
|
+
status,
|
|
76
|
+
startDate = "",
|
|
77
|
+
endDate = "",
|
|
78
|
+
date,
|
|
79
|
+
search = "",
|
|
80
|
+
}: {
|
|
81
|
+
page?: number;
|
|
82
|
+
limit?: number;
|
|
83
|
+
search?: string;
|
|
84
|
+
startDate?: any;
|
|
85
|
+
endDate?: any;
|
|
86
|
+
date?: any;
|
|
87
|
+
status?: string;
|
|
88
|
+
organization?: string;
|
|
89
|
+
site?: string;
|
|
90
|
+
provider?: string | any;
|
|
91
|
+
providerService?: string;
|
|
92
|
+
service?: string;
|
|
74
93
|
} = {}) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
return useNuxtApp().$api<Record<string, any>[]>("/api/work-orders2/v1", {
|
|
95
|
+
method: "GET",
|
|
96
|
+
query: {
|
|
97
|
+
page,
|
|
98
|
+
limit,
|
|
99
|
+
search,
|
|
100
|
+
status,
|
|
101
|
+
startDate,
|
|
102
|
+
endDate,
|
|
103
|
+
date,
|
|
104
|
+
organization,
|
|
105
|
+
site,
|
|
106
|
+
provider,
|
|
107
|
+
providerService,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
86
110
|
}
|
|
87
111
|
|
|
88
112
|
function getWorkOrderById(id: string) {
|
|
89
|
-
return useNuxtApp().$api<TWorkOrder>(`/api/work-
|
|
113
|
+
return useNuxtApp().$api<TWorkOrder>(`/api/work-orders2/v1/id/${id}`, {
|
|
90
114
|
method: "GET",
|
|
91
115
|
});
|
|
92
116
|
}
|
|
93
117
|
|
|
94
|
-
function createWorkOrder(payload:
|
|
95
|
-
return useNuxtApp().$api<Record<string, any>>("/api/work-
|
|
118
|
+
function createWorkOrder(payload: any) {
|
|
119
|
+
return useNuxtApp().$api<Record<string, any>>("/api/work-orders2/v1", {
|
|
120
|
+
method: "POST",
|
|
121
|
+
body: payload,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function updateStatusWorkOrder(payload: any) {
|
|
126
|
+
return useNuxtApp().$api("/api/work-orders2/status-update", {
|
|
96
127
|
method: "POST",
|
|
97
128
|
body: payload,
|
|
98
129
|
});
|
|
@@ -140,6 +171,7 @@ export default function useWorkOrder() {
|
|
|
140
171
|
pages,
|
|
141
172
|
pageRange,
|
|
142
173
|
createWorkOrder,
|
|
174
|
+
updateStatusWorkOrder,
|
|
143
175
|
getWorkOrders,
|
|
144
176
|
getWorkOrderById,
|
|
145
177
|
updateWorkOrder,
|
package/nuxt.config.ts
CHANGED
|
@@ -17,7 +17,7 @@ export default defineNuxtConfig({
|
|
|
17
17
|
APP: (process.env.APP as string) ?? "App",
|
|
18
18
|
API_DO_STORAGE_ENDPOINT:
|
|
19
19
|
(process.env.API_DO_STORAGE_ENDPOINT as string) ?? "",
|
|
20
|
-
API_DO_STORAGE_ENDPOINT_ANPR:
|
|
20
|
+
API_DO_STORAGE_ENDPOINT_ANPR:
|
|
21
21
|
(process.env.API_DO_STORAGE_ENDPOINT_ANPR as string) ?? "",
|
|
22
22
|
APP_NAME: (process.env.APP_NAME as string) ?? "App",
|
|
23
23
|
APP_NAME_ROUTE: (process.env.APP_NAME_ROUTE as string) ?? "index",
|
|
@@ -47,6 +47,7 @@ export default defineNuxtConfig({
|
|
|
47
47
|
config.plugins.push(vuetify({ autoImport: true }));
|
|
48
48
|
});
|
|
49
49
|
},
|
|
50
|
+
"nuxt-signature-pad",
|
|
50
51
|
],
|
|
51
52
|
|
|
52
53
|
vite: {
|
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@ definePageMeta({
|
|
|
31
31
|
layout: "plain",
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
const { APP_ACCOUNT, APP_NAME, APP_ORG } = useRuntimeConfig().public;
|
|
34
|
+
const { APP_ACCOUNT, APP_NAME, APP_ORG, APP } = useRuntimeConfig().public;
|
|
35
35
|
|
|
36
36
|
function goToAccount() {
|
|
37
37
|
window.location.href = `${APP_ACCOUNT}/home`;
|
|
@@ -39,9 +39,9 @@ function goToAccount() {
|
|
|
39
39
|
|
|
40
40
|
function createOrg() {
|
|
41
41
|
if (APP_NAME.toLowerCase() === "org") {
|
|
42
|
-
navigateTo({ name: "organizations-create" });
|
|
42
|
+
navigateTo({ name: "organizations-create", query: { app: APP as string ?? "" } });
|
|
43
43
|
} else {
|
|
44
|
-
window.location.href = `${APP_ORG}/organizations/create`;
|
|
44
|
+
window.location.href = `${APP_ORG}/organizations/create?app=${APP as string ?? ""}`;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
</script>
|
package/types/area.d.ts
CHANGED
package/types/dashboard.d.ts
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
declare type TOvernightParkingDay = {
|
|
2
|
+
isEnabled: boolean;
|
|
3
|
+
startTime: string | null;
|
|
4
|
+
endTime: string | null;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
declare type TOvernightParkingAvailability = {
|
|
8
|
+
monday: TOvernightParkingDay;
|
|
9
|
+
tuesday: TOvernightParkingDay;
|
|
10
|
+
wednesday: TOvernightParkingDay;
|
|
11
|
+
thursday: TOvernightParkingDay;
|
|
12
|
+
friday: TOvernightParkingDay;
|
|
13
|
+
saturday: TOvernightParkingDay;
|
|
14
|
+
sunday: TOvernightParkingDay;
|
|
15
|
+
autoApproveOvernightParking?: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
declare type TOvernightParkingRequestStatus =
|
|
19
|
+
| "approved"
|
|
20
|
+
| "expired"
|
|
21
|
+
| "rejected"
|
|
22
|
+
| "pending"
|
|
23
|
+
| (string & {});
|
|
24
|
+
|
|
25
|
+
declare type TOvernightParkingRequest = {
|
|
26
|
+
_id?: string;
|
|
27
|
+
name?: string | null;
|
|
28
|
+
plateNumber?: string | null;
|
|
29
|
+
dateRequested?: string | Date | null;
|
|
30
|
+
status?: TOvernightParkingRequestStatus | null;
|
|
31
|
+
start?: string | Date | null;
|
|
32
|
+
end?: string | Date | null;
|
|
33
|
+
remarks?: string | null;
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
};
|
package/types/user.d.ts
CHANGED
package/types/work-order.d.ts
CHANGED
package/utils/data.ts
CHANGED
|
@@ -29,3 +29,20 @@ export const errorConverter = (data: any): string => {
|
|
|
29
29
|
}
|
|
30
30
|
return error;
|
|
31
31
|
};
|
|
32
|
+
|
|
33
|
+
export const findServiceProviderIdBySite = (
|
|
34
|
+
type: string,
|
|
35
|
+
serviceProviders: any,
|
|
36
|
+
siteId: string
|
|
37
|
+
) => {
|
|
38
|
+
if (type === "service-provider") {
|
|
39
|
+
const result = serviceProviders.find(
|
|
40
|
+
(item: Record<string, any>) => item.siteId === siteId
|
|
41
|
+
);
|
|
42
|
+
if (!result?._id) {
|
|
43
|
+
throw new Error(`Service provider with siteId ${siteId} not found`);
|
|
44
|
+
}
|
|
45
|
+
return result?._id;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
};
|