@7365admin1/layer-common 1.10.0 → 1.10.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 +6 -0
- package/components/AcceptDialog.vue +44 -0
- package/components/AccessCardAddForm.vue +101 -13
- package/components/AccessManagement.vue +130 -47
- package/components/AddSupplyForm.vue +165 -0
- package/components/AreaChecklistHistoryLogs.vue +235 -0
- package/components/AreaChecklistHistoryMain.vue +176 -0
- package/components/AreaFormDialog.vue +266 -0
- package/components/AreaMain.vue +841 -0
- package/components/AttendanceCheckInOutDialog.vue +416 -0
- package/components/AttendanceDetailsDialog.vue +184 -0
- package/components/AttendanceMain.vue +155 -0
- package/components/AttendanceMapSearchDialog.vue +393 -0
- package/components/AttendanceSettingsDialog.vue +398 -0
- package/components/BuildingManagement/buildings.vue +5 -5
- package/components/BuildingManagement/units.vue +5 -5
- package/components/ChecklistItemRow.vue +54 -0
- package/components/CheckoutItemMain.vue +705 -0
- package/components/CleaningScheduleMain.vue +271 -0
- package/components/DocumentManagement.vue +4 -0
- package/components/EntryPass/QrTemplatePreview.vue +104 -0
- package/components/EntryPassMain.vue +252 -200
- package/components/HygieneUpdateMoreAction.vue +238 -0
- package/components/ManageChecklistMain.vue +384 -0
- package/components/MemberMain.vue +48 -20
- package/components/MyAttendanceMain.vue +224 -0
- package/components/OnlineFormsConfiguration.vue +9 -2
- package/components/PhotoUpload.vue +410 -0
- package/components/ScheduleAreaMain.vue +313 -0
- package/components/ScheduleTaskAreaFormDialog.vue +144 -0
- package/components/ScheduleTaskAreaUpdateMoreAction.vue +109 -0
- package/components/ScheduleTaskForm.vue +471 -0
- package/components/ScheduleTaskMain.vue +345 -0
- package/components/ScheduleTastTicketMain.vue +182 -0
- package/components/StockCard.vue +191 -0
- package/components/SupplyManagementMain.vue +557 -0
- package/components/TableHygiene.vue +617 -0
- package/components/UnitMain.vue +451 -0
- package/components/VisitorManagement.vue +28 -15
- package/composables/useAccessManagement.ts +90 -0
- package/composables/useAreaPermission.ts +51 -0
- package/composables/useAreas.ts +99 -0
- package/composables/useAttendance.ts +89 -0
- package/composables/useAttendancePermission.ts +68 -0
- package/composables/useBuilding.ts +2 -2
- package/composables/useBuildingUnit.ts +2 -2
- package/composables/useCard.ts +2 -0
- package/composables/useCheckout.ts +61 -0
- package/composables/useCheckoutPermission.ts +80 -0
- package/composables/useCleaningPermission.ts +229 -0
- package/composables/useCleaningSchedulePermission.ts +58 -0
- package/composables/useCleaningSchedules.ts +233 -0
- package/composables/useCountry.ts +8 -0
- package/composables/useDashboardData.ts +2 -2
- package/composables/useFeedback.ts +1 -1
- package/composables/useLocation.ts +78 -0
- package/composables/useOnlineForm.ts +16 -9
- package/composables/usePeople.ts +87 -72
- package/composables/useQR.ts +29 -0
- package/composables/useScheduleTask.ts +89 -0
- package/composables/useScheduleTaskArea.ts +85 -0
- package/composables/useScheduleTaskPermission.ts +68 -0
- package/composables/useSiteEntryPassSettings.ts +4 -15
- package/composables/useStock.ts +45 -0
- package/composables/useSupply.ts +63 -0
- package/composables/useSupplyPermission.ts +92 -0
- package/composables/useUnitPermission.ts +51 -0
- package/composables/useUnits.ts +82 -0
- package/composables/useWebUsb.ts +389 -0
- package/composables/useWorkOrder.ts +1 -1
- package/nuxt.config.ts +3 -0
- package/package.json +4 -1
- package/types/area.d.ts +22 -0
- package/types/attendance.d.ts +38 -0
- package/types/checkout-item.d.ts +27 -0
- package/types/cleaner-schedule.d.ts +54 -0
- package/types/location.d.ts +42 -0
- package/types/schedule-task.d.ts +18 -0
- package/types/stock.d.ts +16 -0
- package/types/supply.d.ts +11 -0
- package/utils/acm-crypto.ts +30 -0
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-dialog v-model="show" max-width="680" persistent>
|
|
3
|
+
<v-card class="d-flex flex-column" max-height="90vh">
|
|
4
|
+
<v-toolbar flat color="grey-lighten-4">
|
|
5
|
+
<v-row no-gutters class="fill-height px-6" align="center">
|
|
6
|
+
<v-toolbar-title class="text-h6 font-weight-bold">
|
|
7
|
+
{{
|
|
8
|
+
props.mode === "edit"
|
|
9
|
+
? "Edit Schedule Task"
|
|
10
|
+
: "Create Schedule Task"
|
|
11
|
+
}}
|
|
12
|
+
</v-toolbar-title>
|
|
13
|
+
<v-spacer />
|
|
14
|
+
<v-btn
|
|
15
|
+
icon="mdi-close"
|
|
16
|
+
variant="text"
|
|
17
|
+
@click="close"
|
|
18
|
+
:disabled="submitting"
|
|
19
|
+
/>
|
|
20
|
+
</v-row>
|
|
21
|
+
</v-toolbar>
|
|
22
|
+
|
|
23
|
+
<v-card-text class="pa-8 flex-grow-1" style="overflow-y: auto">
|
|
24
|
+
<v-form ref="formRef" v-model="valid">
|
|
25
|
+
<v-row dense>
|
|
26
|
+
<v-col cols="12">
|
|
27
|
+
<InputLabel for="title" title="Title" required />
|
|
28
|
+
<v-text-field
|
|
29
|
+
id="title"
|
|
30
|
+
v-model="subject"
|
|
31
|
+
variant="outlined"
|
|
32
|
+
density="comfortable"
|
|
33
|
+
placeholder="Enter task title"
|
|
34
|
+
hide-details="auto"
|
|
35
|
+
class="mb-4"
|
|
36
|
+
/>
|
|
37
|
+
</v-col>
|
|
38
|
+
|
|
39
|
+
<v-col cols="12">
|
|
40
|
+
<InputLabel for="date-range" title="Date Range" required />
|
|
41
|
+
<v-sheet border rounded class="pa-4 mb-4" color="grey-lighten-5">
|
|
42
|
+
<div class="d-flex align-center gap-3 mb-3">
|
|
43
|
+
<v-text-field
|
|
44
|
+
v-model="startDateInput"
|
|
45
|
+
type="date"
|
|
46
|
+
variant="outlined"
|
|
47
|
+
density="compact"
|
|
48
|
+
label="Start Date"
|
|
49
|
+
hide-details
|
|
50
|
+
class="flex-grow-1"
|
|
51
|
+
@update:model-value="handleStartDateChange"
|
|
52
|
+
/>
|
|
53
|
+
<v-icon>mdi-arrow-right</v-icon>
|
|
54
|
+
<v-text-field
|
|
55
|
+
v-model="endDateInput"
|
|
56
|
+
type="date"
|
|
57
|
+
variant="outlined"
|
|
58
|
+
density="compact"
|
|
59
|
+
label="End Date"
|
|
60
|
+
hide-details
|
|
61
|
+
class="flex-grow-1"
|
|
62
|
+
@update:model-value="handleEndDateChange"
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<v-expand-transition>
|
|
67
|
+
<div v-if="showCalendar">
|
|
68
|
+
<v-divider class="mb-3" />
|
|
69
|
+
<v-date-picker
|
|
70
|
+
v-model="pickerDates"
|
|
71
|
+
multiple
|
|
72
|
+
@update:model-value="handlePickerChange"
|
|
73
|
+
:show-current="false"
|
|
74
|
+
color="primary"
|
|
75
|
+
elevation="0"
|
|
76
|
+
width="100%"
|
|
77
|
+
class="ma-0"
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
</v-expand-transition>
|
|
81
|
+
|
|
82
|
+
<v-btn
|
|
83
|
+
variant="text"
|
|
84
|
+
size="small"
|
|
85
|
+
@click="showCalendar = !showCalendar"
|
|
86
|
+
class="mt-2"
|
|
87
|
+
prepend-icon="mdi-calendar"
|
|
88
|
+
>
|
|
89
|
+
{{ showCalendar ? "Hide Calendar" : "Show Calendar" }}
|
|
90
|
+
</v-btn>
|
|
91
|
+
</v-sheet>
|
|
92
|
+
</v-col>
|
|
93
|
+
|
|
94
|
+
<v-col cols="12">
|
|
95
|
+
<InputLabel for="schedule-time" title="Time" required />
|
|
96
|
+
<v-text-field
|
|
97
|
+
id="schedule-time"
|
|
98
|
+
v-model="scheduleTime"
|
|
99
|
+
type="time"
|
|
100
|
+
variant="outlined"
|
|
101
|
+
density="comfortable"
|
|
102
|
+
hide-details="auto"
|
|
103
|
+
prepend-inner-icon="mdi-clock-outline"
|
|
104
|
+
class="mb-4"
|
|
105
|
+
/>
|
|
106
|
+
</v-col>
|
|
107
|
+
|
|
108
|
+
<v-col cols="12">
|
|
109
|
+
<InputLabel for="selected-areas" title="Select Areas" required />
|
|
110
|
+
<v-select
|
|
111
|
+
id="selected-areas"
|
|
112
|
+
v-model="selectedAreas"
|
|
113
|
+
:items="areasList"
|
|
114
|
+
item-title="name"
|
|
115
|
+
item-value="value"
|
|
116
|
+
return-object
|
|
117
|
+
multiple
|
|
118
|
+
variant="outlined"
|
|
119
|
+
density="comfortable"
|
|
120
|
+
:loading="loadingAreas"
|
|
121
|
+
placeholder="Choose one or more areas"
|
|
122
|
+
hide-details="auto"
|
|
123
|
+
class="mb-4"
|
|
124
|
+
chips
|
|
125
|
+
closable-chips
|
|
126
|
+
>
|
|
127
|
+
<template v-slot:selection="{ item, index }">
|
|
128
|
+
<v-chip
|
|
129
|
+
v-if="index < 3"
|
|
130
|
+
size="small"
|
|
131
|
+
closable
|
|
132
|
+
@click:close="selectedAreas.splice(index, 1)"
|
|
133
|
+
>
|
|
134
|
+
{{ item.title }}
|
|
135
|
+
</v-chip>
|
|
136
|
+
<span
|
|
137
|
+
v-if="index === 3"
|
|
138
|
+
class="text-grey text-caption align-self-center"
|
|
139
|
+
>
|
|
140
|
+
(+{{ selectedAreas.length - 3 }} others)
|
|
141
|
+
</span>
|
|
142
|
+
</template>
|
|
143
|
+
</v-select>
|
|
144
|
+
</v-col>
|
|
145
|
+
|
|
146
|
+
<v-col cols="12">
|
|
147
|
+
<InputLabel for="description" title="Task Description" />
|
|
148
|
+
<v-textarea
|
|
149
|
+
id="description"
|
|
150
|
+
v-model="description"
|
|
151
|
+
variant="outlined"
|
|
152
|
+
density="comfortable"
|
|
153
|
+
rows="4"
|
|
154
|
+
placeholder="Add additional details about this task..."
|
|
155
|
+
hide-details="auto"
|
|
156
|
+
class="mb-2"
|
|
157
|
+
/>
|
|
158
|
+
</v-col>
|
|
159
|
+
</v-row>
|
|
160
|
+
</v-form>
|
|
161
|
+
</v-card-text>
|
|
162
|
+
|
|
163
|
+
<v-divider />
|
|
164
|
+
|
|
165
|
+
<v-card-actions class="pa-0">
|
|
166
|
+
<v-row no-gutters class="fill-width">
|
|
167
|
+
<v-col cols="6" class="pa-0">
|
|
168
|
+
<v-btn
|
|
169
|
+
block
|
|
170
|
+
variant="text"
|
|
171
|
+
class="text-none rounded-0"
|
|
172
|
+
size="x-large"
|
|
173
|
+
@click="close"
|
|
174
|
+
height="56"
|
|
175
|
+
:disabled="submitting"
|
|
176
|
+
>
|
|
177
|
+
Cancel
|
|
178
|
+
</v-btn>
|
|
179
|
+
</v-col>
|
|
180
|
+
<v-col cols="6" class="pa-0">
|
|
181
|
+
<v-btn
|
|
182
|
+
block
|
|
183
|
+
variant="flat"
|
|
184
|
+
color="primary"
|
|
185
|
+
class="text-none font-weight-bold rounded-0"
|
|
186
|
+
height="56"
|
|
187
|
+
@click="submitTask"
|
|
188
|
+
:loading="submitting"
|
|
189
|
+
>
|
|
190
|
+
{{ props.mode === "edit" ? "Save Changes" : "Add Schedule Task" }}
|
|
191
|
+
</v-btn>
|
|
192
|
+
</v-col>
|
|
193
|
+
</v-row>
|
|
194
|
+
</v-card-actions>
|
|
195
|
+
</v-card>
|
|
196
|
+
</v-dialog>
|
|
197
|
+
|
|
198
|
+
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
199
|
+
</template>
|
|
200
|
+
|
|
201
|
+
<script setup lang="ts">
|
|
202
|
+
const props = defineProps({
|
|
203
|
+
mode: {
|
|
204
|
+
type: String as PropType<"add" | "edit">,
|
|
205
|
+
default: "add",
|
|
206
|
+
},
|
|
207
|
+
taskData: {
|
|
208
|
+
type: Object,
|
|
209
|
+
default: null,
|
|
210
|
+
},
|
|
211
|
+
site: {
|
|
212
|
+
type: String,
|
|
213
|
+
required: true,
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const show = defineModel("show", { type: Boolean, default: false });
|
|
218
|
+
const emit = defineEmits(["saved", "close", "refresh"]);
|
|
219
|
+
|
|
220
|
+
const { getAreas } = useAreas();
|
|
221
|
+
const { createScheduleTask, updateScheduleTask, getScheduleTaskById } =
|
|
222
|
+
useScheduleTask();
|
|
223
|
+
|
|
224
|
+
const formRef = ref<HTMLFormElement | null>(null);
|
|
225
|
+
const valid = ref(false);
|
|
226
|
+
const submitting = ref(false);
|
|
227
|
+
const loadingTask = ref(false);
|
|
228
|
+
const showCalendar = ref(false);
|
|
229
|
+
|
|
230
|
+
const subject = ref("");
|
|
231
|
+
const description = ref("");
|
|
232
|
+
const scheduleTime = ref("08:00");
|
|
233
|
+
const startDateInput = ref("");
|
|
234
|
+
const endDateInput = ref("");
|
|
235
|
+
const pickerDates = ref<Date[]>([]);
|
|
236
|
+
const selectedAreas = ref<any[]>([]);
|
|
237
|
+
|
|
238
|
+
const message = ref("");
|
|
239
|
+
const messageSnackbar = ref(false);
|
|
240
|
+
const messageColor = ref("success");
|
|
241
|
+
const areasList = ref<any[]>([]);
|
|
242
|
+
|
|
243
|
+
// Helper function to generate all dates between start and end
|
|
244
|
+
const generateDateRange = (start: Date, end: Date): Date[] => {
|
|
245
|
+
const dates: Date[] = [];
|
|
246
|
+
const current = new Date(start);
|
|
247
|
+
|
|
248
|
+
while (current <= end) {
|
|
249
|
+
dates.push(new Date(current));
|
|
250
|
+
current.setDate(current.getDate() + 1);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return dates;
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// Handle changes from the start date input
|
|
257
|
+
const handleStartDateChange = (value: string) => {
|
|
258
|
+
if (value && endDateInput.value) {
|
|
259
|
+
const start = new Date(value);
|
|
260
|
+
const end = new Date(endDateInput.value);
|
|
261
|
+
|
|
262
|
+
if (start <= end) {
|
|
263
|
+
pickerDates.value = generateDateRange(start, end);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// Handle changes from the end date input
|
|
269
|
+
const handleEndDateChange = (value: string) => {
|
|
270
|
+
if (startDateInput.value && value) {
|
|
271
|
+
const start = new Date(startDateInput.value);
|
|
272
|
+
const end = new Date(value);
|
|
273
|
+
|
|
274
|
+
if (start <= end) {
|
|
275
|
+
pickerDates.value = generateDateRange(start, end);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// Handle changes from the calendar picker
|
|
281
|
+
const handlePickerChange = (dates: Date[]) => {
|
|
282
|
+
if (dates && dates.length > 0) {
|
|
283
|
+
// Sort dates to find earliest and latest
|
|
284
|
+
const sortedDates = [...dates].sort((a, b) => a.getTime() - b.getTime());
|
|
285
|
+
const start = sortedDates[0];
|
|
286
|
+
const end = sortedDates[sortedDates.length - 1];
|
|
287
|
+
|
|
288
|
+
// Update input fields
|
|
289
|
+
startDateInput.value = start.toISOString().slice(0, 10);
|
|
290
|
+
endDateInput.value = end.toISOString().slice(0, 10);
|
|
291
|
+
|
|
292
|
+
// Fill in all dates between start and end
|
|
293
|
+
pickerDates.value = generateDateRange(start, end);
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const showMessage = (text: string, color: string = "success") => {
|
|
298
|
+
message.value = text;
|
|
299
|
+
messageColor.value = color;
|
|
300
|
+
messageSnackbar.value = true;
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const resetForm = () => {
|
|
304
|
+
subject.value = "";
|
|
305
|
+
description.value = "";
|
|
306
|
+
scheduleTime.value = "08:00";
|
|
307
|
+
startDateInput.value = "";
|
|
308
|
+
endDateInput.value = "";
|
|
309
|
+
pickerDates.value = [];
|
|
310
|
+
selectedAreas.value = [];
|
|
311
|
+
showCalendar.value = false;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const setFormFromTask = (task: any) => {
|
|
315
|
+
if (!task) return;
|
|
316
|
+
|
|
317
|
+
subject.value = task.title || "";
|
|
318
|
+
description.value = task.description || "";
|
|
319
|
+
scheduleTime.value = task.time || "08:00";
|
|
320
|
+
|
|
321
|
+
const toISODate = (d: any) => {
|
|
322
|
+
if (!d) return null;
|
|
323
|
+
try {
|
|
324
|
+
const dt = new Date(d);
|
|
325
|
+
if (isNaN(dt.getTime())) return null;
|
|
326
|
+
return dt.toISOString().slice(0, 10);
|
|
327
|
+
} catch (e) {
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
if (task.startDate || task.endDate) {
|
|
333
|
+
const start = toISODate(task.startDate || task.start);
|
|
334
|
+
const end = toISODate(task.endDate || task.end);
|
|
335
|
+
|
|
336
|
+
if (start) startDateInput.value = start;
|
|
337
|
+
if (end) endDateInput.value = end;
|
|
338
|
+
|
|
339
|
+
if (start && end) {
|
|
340
|
+
pickerDates.value = generateDateRange(new Date(start), new Date(end));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
selectedAreas.value = Array.isArray(task.areas)
|
|
345
|
+
? task.areas.map((area: any) => ({
|
|
346
|
+
_id: area.value,
|
|
347
|
+
name: area.name,
|
|
348
|
+
value: area.value,
|
|
349
|
+
}))
|
|
350
|
+
: [];
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
const { data: getAreasReq, pending: loadingAreas } = await useLazyAsyncData(
|
|
354
|
+
`get-areas-${props.site}`,
|
|
355
|
+
() => getAreas({ site: props.site, limit: 1000 }),
|
|
356
|
+
{
|
|
357
|
+
watch: [show, () => props.site],
|
|
358
|
+
immediate: false,
|
|
359
|
+
},
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
watchEffect(() => {
|
|
363
|
+
if (getAreasReq.value) {
|
|
364
|
+
areasList.value = (getAreasReq.value?.items || []).map((item: any) => ({
|
|
365
|
+
...item,
|
|
366
|
+
value: item._id || item.value,
|
|
367
|
+
}));
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const loadTaskData = async () => {
|
|
372
|
+
if (props.mode !== "edit") return;
|
|
373
|
+
|
|
374
|
+
const id = (props.taskData as any)?._id || (props.taskData as any)?.id;
|
|
375
|
+
|
|
376
|
+
if (!id) {
|
|
377
|
+
if ((props.taskData as any)?.title) setFormFromTask(props.taskData);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
loadingTask.value = true;
|
|
382
|
+
try {
|
|
383
|
+
const response = await getScheduleTaskById(id);
|
|
384
|
+
|
|
385
|
+
if (response) {
|
|
386
|
+
setFormFromTask(response as any);
|
|
387
|
+
} else if ((props.taskData as any)?.title) {
|
|
388
|
+
setFormFromTask(props.taskData);
|
|
389
|
+
}
|
|
390
|
+
} catch (error: any) {
|
|
391
|
+
if ((props.taskData as any)?.title) setFormFromTask(props.taskData);
|
|
392
|
+
showMessage(
|
|
393
|
+
error?.data?.message || "Failed to load schedule task",
|
|
394
|
+
"error",
|
|
395
|
+
);
|
|
396
|
+
} finally {
|
|
397
|
+
loadingTask.value = false;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
const submitTask = async () => {
|
|
402
|
+
submitting.value = true;
|
|
403
|
+
try {
|
|
404
|
+
const payload = {
|
|
405
|
+
title: subject.value,
|
|
406
|
+
time: scheduleTime.value,
|
|
407
|
+
startDate: startDateInput.value,
|
|
408
|
+
endDate: endDateInput.value,
|
|
409
|
+
description: description.value?.trim() || "",
|
|
410
|
+
areas: selectedAreas.value.map((area: any) => ({
|
|
411
|
+
name: area.name || area.title || "",
|
|
412
|
+
value: area._id || area.value || area,
|
|
413
|
+
})),
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
if (startDateInput.value) {
|
|
417
|
+
payload.startDate = startDateInput.value;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (endDateInput.value) {
|
|
421
|
+
payload.endDate = endDateInput.value;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
let response;
|
|
425
|
+
|
|
426
|
+
if (props.mode === "edit" && props.taskData) {
|
|
427
|
+
const taskId =
|
|
428
|
+
(props.taskData as any)?._id || (props.taskData as any)?.id;
|
|
429
|
+
response = await updateScheduleTask(taskId, payload);
|
|
430
|
+
} else {
|
|
431
|
+
response = await createScheduleTask({ ...payload, site: props.site });
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
showMessage(
|
|
435
|
+
response?.message ||
|
|
436
|
+
`Schedule task ${
|
|
437
|
+
props.mode === "edit" ? "updated" : "created"
|
|
438
|
+
} successfully`,
|
|
439
|
+
"success",
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
emit("saved");
|
|
443
|
+
emit("refresh");
|
|
444
|
+
close();
|
|
445
|
+
} catch (error: any) {
|
|
446
|
+
showMessage(
|
|
447
|
+
error?.data?.message || "Failed to submit schedule task",
|
|
448
|
+
"error",
|
|
449
|
+
);
|
|
450
|
+
} finally {
|
|
451
|
+
submitting.value = false;
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
const close = () => {
|
|
456
|
+
show.value = false;
|
|
457
|
+
emit("close");
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
watch(
|
|
461
|
+
[show, () => props.mode, () => props.taskData],
|
|
462
|
+
async ([isOpen, mode, taskData]) => {
|
|
463
|
+
if (isOpen && mode === "edit") {
|
|
464
|
+
await loadTaskData();
|
|
465
|
+
} else if (!isOpen) {
|
|
466
|
+
resetForm();
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
{ immediate: false },
|
|
470
|
+
);
|
|
471
|
+
</script>
|