@7365admin1/layer-common 1.10.0 → 1.10.2

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.
Files changed (86) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/components/AcceptDialog.vue +44 -0
  3. package/components/AccessCard/AvailableStats.vue +55 -0
  4. package/components/AccessCardAddForm.vue +284 -19
  5. package/components/AccessCardAssignToUnitForm.vue +440 -0
  6. package/components/AccessManagement.vue +218 -85
  7. package/components/AddSupplyForm.vue +165 -0
  8. package/components/AreaChecklistHistoryLogs.vue +235 -0
  9. package/components/AreaChecklistHistoryMain.vue +176 -0
  10. package/components/AreaFormDialog.vue +266 -0
  11. package/components/AreaMain.vue +863 -0
  12. package/components/AttendanceCheckInOutDialog.vue +416 -0
  13. package/components/AttendanceDetailsDialog.vue +184 -0
  14. package/components/AttendanceMain.vue +155 -0
  15. package/components/AttendanceMapSearchDialog.vue +393 -0
  16. package/components/AttendanceSettingsDialog.vue +398 -0
  17. package/components/BuildingManagement/buildings.vue +5 -5
  18. package/components/BuildingManagement/units.vue +5 -5
  19. package/components/BulletinBoardManagement.vue +322 -0
  20. package/components/ChecklistItemRow.vue +54 -0
  21. package/components/CheckoutItemMain.vue +705 -0
  22. package/components/CleaningScheduleMain.vue +271 -0
  23. package/components/DocumentManagement.vue +4 -0
  24. package/components/EntryPass/QrTemplatePreview.vue +104 -0
  25. package/components/EntryPassMain.vue +252 -200
  26. package/components/HygieneUpdateMoreAction.vue +238 -0
  27. package/components/ManageChecklistMain.vue +384 -0
  28. package/components/MemberMain.vue +48 -20
  29. package/components/MyAttendanceMain.vue +224 -0
  30. package/components/OnlineFormsConfiguration.vue +9 -2
  31. package/components/PhotoUpload.vue +410 -0
  32. package/components/ScheduleAreaMain.vue +313 -0
  33. package/components/ScheduleTaskAreaFormDialog.vue +144 -0
  34. package/components/ScheduleTaskAreaUpdateMoreAction.vue +109 -0
  35. package/components/ScheduleTaskForm.vue +471 -0
  36. package/components/ScheduleTaskMain.vue +345 -0
  37. package/components/ScheduleTastTicketMain.vue +182 -0
  38. package/components/SignaturePad.vue +17 -5
  39. package/components/StockCard.vue +191 -0
  40. package/components/SupplyManagementMain.vue +557 -0
  41. package/components/TableHygiene.vue +617 -0
  42. package/components/UnitMain.vue +451 -0
  43. package/components/VisitorManagement.vue +28 -15
  44. package/composables/useAccessManagement.ts +163 -0
  45. package/composables/useAreaPermission.ts +51 -0
  46. package/composables/useAreas.ts +99 -0
  47. package/composables/useAttendance.ts +89 -0
  48. package/composables/useAttendancePermission.ts +68 -0
  49. package/composables/useBuilding.ts +2 -2
  50. package/composables/useBuildingUnit.ts +2 -2
  51. package/composables/useBulletin.ts +82 -0
  52. package/composables/useCard.ts +2 -0
  53. package/composables/useCheckout.ts +61 -0
  54. package/composables/useCheckoutPermission.ts +80 -0
  55. package/composables/useCleaningPermission.ts +229 -0
  56. package/composables/useCleaningSchedulePermission.ts +58 -0
  57. package/composables/useCleaningSchedules.ts +233 -0
  58. package/composables/useCountry.ts +8 -0
  59. package/composables/useDashboardData.ts +2 -2
  60. package/composables/useFeedback.ts +1 -1
  61. package/composables/useLocation.ts +78 -0
  62. package/composables/useOnlineForm.ts +16 -9
  63. package/composables/usePeople.ts +87 -72
  64. package/composables/useQR.ts +29 -0
  65. package/composables/useScheduleTask.ts +89 -0
  66. package/composables/useScheduleTaskArea.ts +85 -0
  67. package/composables/useScheduleTaskPermission.ts +68 -0
  68. package/composables/useSiteEntryPassSettings.ts +4 -15
  69. package/composables/useStock.ts +45 -0
  70. package/composables/useSupply.ts +63 -0
  71. package/composables/useSupplyPermission.ts +92 -0
  72. package/composables/useUnitPermission.ts +51 -0
  73. package/composables/useUnits.ts +82 -0
  74. package/composables/useWebUsb.ts +389 -0
  75. package/composables/useWorkOrder.ts +1 -1
  76. package/nuxt.config.ts +3 -0
  77. package/package.json +4 -1
  78. package/types/area.d.ts +22 -0
  79. package/types/attendance.d.ts +38 -0
  80. package/types/checkout-item.d.ts +27 -0
  81. package/types/cleaner-schedule.d.ts +54 -0
  82. package/types/location.d.ts +42 -0
  83. package/types/schedule-task.d.ts +18 -0
  84. package/types/stock.d.ts +16 -0
  85. package/types/supply.d.ts +11 -0
  86. package/utils/acm-crypto.ts +30 -0
@@ -2,16 +2,28 @@
2
2
  <v-row no-gutters>
3
3
  <v-col cols="12" class="mb-2">
4
4
  <v-row no-gutters align="center" justify="space-between">
5
- <v-btn
6
- class="text-none"
7
- rounded="pill"
8
- variant="tonal"
9
- size="large"
10
- @click="setCard()"
11
- v-if="canCreate && canCreateAccessCard"
12
- >
13
- Add Access Card
14
- </v-btn>
5
+ <v-row no-gutters class="ga-2">
6
+ <v-btn
7
+ class="text-none"
8
+ rounded="pill"
9
+ variant="tonal"
10
+ size="large"
11
+ @click="setCard()"
12
+ v-if="canCreate && canCreateAccessCard"
13
+ >
14
+ Add Access Card
15
+ </v-btn>
16
+ <v-btn
17
+ class="text-none"
18
+ rounded="pill"
19
+ variant="tonal"
20
+ size="large"
21
+ @click="assignDialog = true"
22
+ v-if="canCreate && canAssignAccessCard"
23
+ >
24
+ Assign to Unit
25
+ </v-btn>
26
+ </v-row>
15
27
 
16
28
  <v-text-field
17
29
  v-model="searchText"
@@ -25,6 +37,11 @@
25
37
  />
26
38
  </v-row>
27
39
  </v-col>
40
+ <!-- Available Card Stats -->
41
+ <v-col cols="12" class="mb-2">
42
+ <AccessCardAvailableStats ref="statsRef" :site-id="siteId" />
43
+ </v-col>
44
+
28
45
  <v-col cols="12">
29
46
  <v-card
30
47
  width="100%"
@@ -71,16 +88,17 @@
71
88
  <AccessCardAddForm
72
89
  @cancel="createDialog = false"
73
90
  @success="successCreate()"
91
+ @error="(msg) => showMessage(msg, 'error')"
74
92
  />
75
93
  </v-dialog>
76
94
 
77
- <!-- Edit Dialog -->
78
- <v-dialog v-model="editDialog" width="650" persistent>
79
- <AccessCardAddForm
80
- mode="edit"
81
- @cancel="editDialog = false"
82
- @success="successUpdate()"
83
- :card="selectedCard"
95
+ <!-- Assign to Unit Dialog -->
96
+ <v-dialog v-model="assignDialog" width="650" persistent>
97
+ <AccessCardAssignToUnitForm
98
+ :site-id="siteId"
99
+ @cancel="assignDialog = false"
100
+ @success="successAssign()"
101
+ @error="(msg: any) => showMessage(msg, 'error')"
84
102
  />
85
103
  </v-dialog>
86
104
 
@@ -90,21 +108,130 @@
90
108
  <v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
91
109
  <v-row no-gutters class="mb-4">
92
110
  <v-col cols="12">
93
- <strong>Card:</strong> {{ selectedCard?.cardNumber ?? "N/A" }}
111
+ <strong>Unit:</strong> {{ selectedCard?.name ?? "N/A" }}
94
112
  </v-col>
95
113
  <v-col cols="12">
96
- <strong>Access Type:</strong>
97
- {{ selectedCard?.accessCardType ?? "N/A" }}
114
+ <strong>Block:</strong> {{ selectedCard?.block?.name ?? "N/A" }}
98
115
  </v-col>
99
116
  <v-col cols="12">
100
- <strong>Unit:</strong>
101
- {{ selectedCard?.unit || "N/A" }}
117
+ <strong>Level:</strong> {{ selectedCard?.level?.level ?? "N/A" }}
102
118
  </v-col>
103
- <v-col cols="12">
104
- <strong>Assign:</strong> {{ selectedCard?.assign || "N/A" }}
119
+
120
+ <!-- Available Physical -->
121
+ <v-col cols="12" class="mt-3">
122
+ <strong>Available Physical</strong>
123
+ <div
124
+ v-if="selectedCard?.available?.physical?.length"
125
+ class="mt-1"
126
+ >
127
+ <v-chip
128
+ v-for="card in selectedCard.available.physical"
129
+ :key="card._id"
130
+ size="small"
131
+ class="mr-1 mb-1"
132
+ :color="
133
+ selectedCardInUnit?._id === card._id ? 'primary' : undefined
134
+ "
135
+ :variant="
136
+ selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'
137
+ "
138
+ style="cursor: pointer"
139
+ @click="
140
+ selectedCardInUnit =
141
+ selectedCardInUnit?._id === card._id ? null : card
142
+ "
143
+ >
144
+ {{ card.cardNo }}
145
+ </v-chip>
146
+ </div>
147
+ <span v-else class="text-caption text-grey ml-1">None</span>
105
148
  </v-col>
106
- <v-col cols="12">
107
- <strong>Status:</strong> {{ selectedCard?.status ?? "N/A" }}
149
+
150
+ <!-- Available Non-Physical -->
151
+ <v-col cols="12" class="mt-2">
152
+ <strong>Available Non-Physical</strong>
153
+ <div
154
+ v-if="selectedCard?.available?.non_physical?.length"
155
+ class="mt-1"
156
+ >
157
+ <v-chip
158
+ v-for="card in selectedCard.available.non_physical"
159
+ :key="card._id"
160
+ size="small"
161
+ class="mr-1 mb-1"
162
+ :color="
163
+ selectedCardInUnit?._id === card._id ? 'primary' : undefined
164
+ "
165
+ :variant="
166
+ selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'
167
+ "
168
+ style="cursor: pointer"
169
+ @click="
170
+ selectedCardInUnit =
171
+ selectedCardInUnit?._id === card._id ? null : card
172
+ "
173
+ >
174
+ {{ card.cardNo }}
175
+ </v-chip>
176
+ </div>
177
+ <span v-else class="text-caption text-grey ml-1">None</span>
178
+ </v-col>
179
+
180
+ <!-- Assigned Physical -->
181
+ <v-col cols="12" class="mt-2">
182
+ <strong>Assigned Physical</strong>
183
+ <div v-if="selectedCard?.assigned?.physical?.length" class="mt-1">
184
+ <v-chip
185
+ v-for="card in selectedCard.assigned.physical"
186
+ :key="card._id"
187
+ size="small"
188
+ class="mr-1 mb-1"
189
+ :color="
190
+ selectedCardInUnit?._id === card._id ? 'primary' : undefined
191
+ "
192
+ :variant="
193
+ selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'
194
+ "
195
+ style="cursor: pointer"
196
+ @click="
197
+ selectedCardInUnit =
198
+ selectedCardInUnit?._id === card._id ? null : card
199
+ "
200
+ >
201
+ {{ card.cardNo }}
202
+ </v-chip>
203
+ </div>
204
+ <span v-else class="text-caption text-grey ml-1">None</span>
205
+ </v-col>
206
+
207
+ <!-- Assigned Non-Physical -->
208
+ <v-col cols="12" class="mt-2">
209
+ <strong>Assigned Non-Physical</strong>
210
+ <div
211
+ v-if="selectedCard?.assigned?.non_physical?.length"
212
+ class="mt-1"
213
+ >
214
+ <v-chip
215
+ v-for="card in selectedCard.assigned.non_physical"
216
+ :key="card._id"
217
+ size="small"
218
+ class="mr-1 mb-1"
219
+ :color="
220
+ selectedCardInUnit?._id === card._id ? 'primary' : undefined
221
+ "
222
+ :variant="
223
+ selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'
224
+ "
225
+ style="cursor: pointer"
226
+ @click="
227
+ selectedCardInUnit =
228
+ selectedCardInUnit?._id === card._id ? null : card
229
+ "
230
+ >
231
+ {{ card.cardNo }}
232
+ </v-chip>
233
+ </div>
234
+ <span v-else class="text-caption text-grey ml-1">None</span>
108
235
  </v-col>
109
236
  </v-row></v-card-text
110
237
  >
@@ -139,14 +266,10 @@
139
266
  </template>
140
267
  <v-list class="pa-0">
141
268
  <v-list-item
142
- @click="openEditDialog()"
143
- v-if="canUpdateAccessCard"
269
+ :disabled="selectedCardInUnit === null"
270
+ @click="openReplaceDialog()"
271
+ v-if="canReplaceAccessCard"
144
272
  >
145
- <v-list-item-title class="text-subtitle-2">
146
- Edit Card
147
- </v-list-item-title>
148
- </v-list-item>
149
- <v-list-item @click="openReplaceDialog()" v-if="canReplaceAccessCard">
150
273
  <v-list-item-title class="text-subtitle-2">
151
274
  Replace Card
152
275
  </v-list-item-title>
@@ -154,6 +277,7 @@
154
277
  <v-list-item
155
278
  @click="openDeleteDialog()"
156
279
  class="text-red"
280
+ :disabled="selectedCardInUnit === null"
157
281
  v-if="canDeleteAccessCard"
158
282
  >
159
283
  <v-list-item-title class="text-subtitle-2">
@@ -238,18 +362,38 @@ const props = defineProps({
238
362
  type: Array as PropType<Array<Record<string, any>>>,
239
363
  default: () => [
240
364
  {
241
- title: "Card",
242
- value: "cardNumber",
365
+ title: "Unit",
366
+ value: "name",
243
367
  },
244
368
  {
245
- title: "Unit",
246
- value: "unit",
369
+ title: "Block",
370
+ value: "block.name",
247
371
  },
248
372
  {
249
- title: "Assign",
250
- value: "assign",
373
+ title: "Level",
374
+ value: "level.level",
251
375
  },
252
- { title: "Action", value: "action-table" },
376
+ {
377
+ title: "Avail. (P)",
378
+ value: "cardCounts.available.physical",
379
+ },
380
+ {
381
+ title: "Avail. (NP)",
382
+ value: "cardCounts.available.non_physical",
383
+ },
384
+ {
385
+ title: "Asgn. (P)",
386
+ value: "cardCounts.assigned.physical",
387
+ },
388
+ {
389
+ title: "Asgn. (NP)",
390
+ value: "cardCounts.assigned.non_physical",
391
+ },
392
+ {
393
+ title: "Total",
394
+ value: "totalCardCount",
395
+ },
396
+ // { title: "Action", value: "action-table" },
253
397
  ],
254
398
  },
255
399
  canCreate: {
@@ -268,15 +412,15 @@ const props = defineProps({
268
412
  type: Boolean,
269
413
  default: true,
270
414
  },
271
- canUpdateAccessCard: {
415
+ canDeleteAccessCard: {
272
416
  type: Boolean,
273
417
  default: true,
274
418
  },
275
- canDeleteAccessCard: {
419
+ canReplaceAccessCard: {
276
420
  type: Boolean,
277
421
  default: true,
278
422
  },
279
- canReplaceAccessCard: {
423
+ canAssignAccessCard: {
280
424
  type: Boolean,
281
425
  default: true,
282
426
  },
@@ -293,39 +437,31 @@ const messageColor = ref("");
293
437
 
294
438
  const items = ref<Array<Record<string, any>>>([]);
295
439
  const createDialog = ref(false);
296
- const editDialog = ref(false);
440
+ const assignDialog = ref(false);
297
441
  const previewDialog = ref(false);
298
442
  const deleteLoading = ref(false);
299
443
  const confirmDialog = ref(false);
300
444
  const searchText = ref("");
301
445
  const replaceDialog = ref(false);
302
446
 
303
- const selectedCard = ref<TCard>({
304
- _id: "",
305
- name: "",
306
- accessCardType: "",
307
- // visitorType: "",
308
- type: "",
309
- cardNumber: "",
310
- startDate: "",
311
- endDate: "",
312
- door: "",
313
- accessGroup: [],
314
- cardType: "",
315
- pinNo: "",
316
- useAsLiftCard: false,
317
- liftAccessLevel: "",
318
- isActivate: true,
319
- isAntiPassBack: false,
320
- status: "",
321
- org: "",
322
- site: "",
323
- unit: "",
324
- assign: "",
325
- });
447
+ const route = useRoute();
448
+ //@TODO
449
+ const siteId = computed(() => route.params.site as string);
450
+ // const siteId = computed(() => "66ab2f1381856008f1887971" as string);
451
+ const orgId = computed(() => route.params.org as string);
452
+
453
+ const selectedCard = ref<Record<string, any>>({});
454
+ const selectedCardInUnit = ref<Record<string, any> | null>(null);
326
455
  const selectedCardId = ref<string | null>(null);
327
456
 
328
- const { getAll: _getAllCards, deleteById: _deleteCard } = useCard();
457
+ watch(previewDialog, (val) => {
458
+ if (!val) selectedCardInUnit.value = null;
459
+ });
460
+
461
+ const { deleteById: _deleteCard } = useCard();
462
+ const { getUserTypeAccessCards } = useAccessManagement();
463
+
464
+ const statsRef = ref<{ refresh: () => void } | null>(null);
329
465
 
330
466
  const {
331
467
  data: getCardReq,
@@ -334,10 +470,12 @@ const {
334
470
  } = useLazyAsyncData(
335
471
  "get-all-cards",
336
472
  () =>
337
- _getAllCards({
473
+ getUserTypeAccessCards({
338
474
  page: page.value,
339
475
  search: searchText.value,
340
- // search: headerSearch.value,
476
+ organization: orgId.value,
477
+ site: siteId.value,
478
+ userType: "Visitor/Resident",
341
479
  }),
342
480
  {
343
481
  watch: [page, searchText],
@@ -347,19 +485,16 @@ const {
347
485
  const loading = computed(() => getAllReqStatus.value === "pending");
348
486
 
349
487
  watchEffect(() => {
350
- if (getCardReq.value) {
351
- items.value = getCardReq.value.items;
352
- pages.value = getCardReq.value.pages;
353
- pageRange.value = getCardReq.value.pageRange;
488
+ if (getCardReq.value?.data) {
489
+ items.value = getCardReq.value.data.items;
490
+ pages.value = getCardReq.value.data.pages;
491
+ pageRange.value = getCardReq.value.data.pageRange;
354
492
  }
355
493
  });
356
494
 
357
495
  function setCard({ mode = "create", dialog = true, data = {} as TCard } = {}) {
358
496
  if (mode === "create") {
359
497
  createDialog.value = dialog;
360
- } else if (mode === "edit") {
361
- editDialog.value = dialog;
362
- selectedCard.value = data;
363
498
  } else if (mode === "preview") {
364
499
  previewDialog.value = dialog;
365
500
  selectedCard.value = data;
@@ -369,14 +504,15 @@ function setCard({ mode = "create", dialog = true, data = {} as TCard } = {}) {
369
504
  function successCreate() {
370
505
  createDialog.value = false;
371
506
  getCards();
507
+ statsRef.value?.refresh();
372
508
  showMessage("Card created successfully!", "success");
373
509
  }
374
510
 
375
- function successUpdate() {
376
- editDialog.value = false;
377
- previewDialog.value = false;
511
+ function successAssign() {
512
+ assignDialog.value = false;
378
513
  getCards();
379
- showMessage("Card updated successfully!", "success");
514
+ statsRef.value?.refresh();
515
+ showMessage("Access card assigned successfully!", "success");
380
516
  }
381
517
 
382
518
  function showMessage(msg: string, color: string) {
@@ -390,10 +526,6 @@ function tableRowClickHandler(_: any, data: any) {
390
526
  previewDialog.value = true;
391
527
  }
392
528
 
393
- function openEditDialog() {
394
- editDialog.value = true;
395
- }
396
-
397
529
  function openDeleteDialog() {
398
530
  confirmDialog.value = true;
399
531
  message.value = "";
@@ -408,6 +540,7 @@ async function handleDeleteCard() {
408
540
  try {
409
541
  await _deleteCard(selectedCard.value._id ?? "");
410
542
  await getCards();
543
+ statsRef.value?.refresh();
411
544
  selectedCardId.value = null;
412
545
  confirmDialog.value = false;
413
546
  previewDialog.value = false;
@@ -0,0 +1,165 @@
1
+ <template>
2
+ <v-dialog v-model="showDialog" max-width="450">
3
+ <v-card>
4
+ <v-toolbar>
5
+ <v-row no-gutters class="fill-height px-6" align="center">
6
+ <span class="font-weight-bold text-h6 text-capitalize">
7
+ {{ prop.mode === "edit" ? "Edit Supply" : "Add New Supply" }}
8
+ </span>
9
+ </v-row>
10
+ </v-toolbar>
11
+
12
+ <v-card-text class="pa-4">
13
+ <v-form ref="formRef" v-model="valid">
14
+ <v-row no-gutters class="pa-0">
15
+ <v-col cols="12" class="pa-0 mb-2">
16
+ <InputLabel for="name" title="Name" required class="mb-1" />
17
+ <v-text-field
18
+ v-model="nameModel"
19
+ :rules="[requiredRule]"
20
+ density="comfortable"
21
+ variant="outlined"
22
+ placeholder="Enter supply name"
23
+ hide-details="auto"
24
+ class="mb-0"
25
+ />
26
+ </v-col>
27
+
28
+ <v-col cols="12" class="pa-0 mb-0">
29
+ <InputLabel
30
+ for="unitOfMeasurement"
31
+ title="Unit of Measurement"
32
+ required
33
+ class="mb-1"
34
+ />
35
+ <v-select
36
+ v-model="unitOfMeasurementModel"
37
+ :items="unitOfMeasurementOptions"
38
+ :rules="[requiredRule]"
39
+ density="comfortable"
40
+ variant="outlined"
41
+ placeholder="Select unitOfMeasurement"
42
+ hide-details="auto"
43
+ class="mb-0"
44
+ />
45
+ </v-col>
46
+ </v-row>
47
+ </v-form>
48
+ </v-card-text>
49
+
50
+ <v-toolbar class="pa-0" density="compact">
51
+ <v-row no-gutters>
52
+ <v-col cols="6" class="pa-0">
53
+ <v-btn
54
+ block
55
+ variant="text"
56
+ class="text-none"
57
+ size="large"
58
+ @click="close"
59
+ height="48"
60
+ >
61
+ Cancel
62
+ </v-btn>
63
+ </v-col>
64
+
65
+ <v-col cols="6" class="pa-0">
66
+ <v-btn
67
+ block
68
+ variant="flat"
69
+ color="black"
70
+ class="text-none font-weight-bold rounded-0"
71
+ height="48"
72
+ :loading="submitting"
73
+ @click="submit"
74
+ >
75
+ {{ prop.mode === "edit" ? "Save" : "Create" }}
76
+ </v-btn>
77
+ </v-col>
78
+ </v-row>
79
+ </v-toolbar>
80
+ </v-card>
81
+ </v-dialog>
82
+ </template>
83
+
84
+ <script setup lang="ts">
85
+ const nameModel = defineModel("name", { type: String, default: "" });
86
+ const unitOfMeasurementModel = defineModel("unitOfMeasurement", {
87
+ type: String,
88
+ default: "",
89
+ });
90
+ const showDialog = defineModel({ type: Boolean, default: false });
91
+
92
+ const prop = defineProps({
93
+ mode: {
94
+ type: String,
95
+ default: "add",
96
+ },
97
+ supplyData: {
98
+ type: Object,
99
+ default: null,
100
+ },
101
+ });
102
+
103
+ const emit = defineEmits(["saved", "close"]);
104
+
105
+ const formRef = ref<any>(null);
106
+ const valid = ref(false);
107
+ const submitting = ref(false);
108
+
109
+ const { requiredRule } = useUtils();
110
+
111
+ const unitOfMeasurementOptions = [
112
+ "Pieces",
113
+ "Boxes",
114
+ "Bottles",
115
+ "Liters",
116
+ "Kilograms",
117
+ "Grams",
118
+ "Rolls",
119
+ "Packs",
120
+ "Sets",
121
+ "Units",
122
+ ];
123
+
124
+ watchEffect(() => {
125
+ nameModel.value = prop.supplyData?.name || "";
126
+ unitOfMeasurementModel.value = prop.supplyData?.unitOfMeasurement || "";
127
+ });
128
+
129
+ function close() {
130
+ showDialog.value = false;
131
+ emit("close");
132
+ }
133
+
134
+ async function submit() {
135
+ const form = formRef.value as any;
136
+ let ok = valid.value;
137
+ if (form && typeof form.validate === "function") {
138
+ const result = await form.validate();
139
+ ok = result.valid;
140
+ }
141
+
142
+ if (!ok) return;
143
+
144
+ submitting.value = true;
145
+ try {
146
+ await new Promise((r) => setTimeout(r, 500));
147
+
148
+ emit("saved", {
149
+ name: nameModel.value,
150
+
151
+ unitOfMeasurement: unitOfMeasurementModel.value,
152
+ });
153
+
154
+ nameModel.value = "";
155
+ unitOfMeasurementModel.value = "";
156
+
157
+ showDialog.value = false;
158
+ emit("close");
159
+ } catch (e) {
160
+ console.error("Error submitting form:", e);
161
+ } finally {
162
+ submitting.value = false;
163
+ }
164
+ }
165
+ </script>