@7365admin1/layer-common 1.11.23 → 1.11.24

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @iservice365/layer-common
2
2
 
3
+ ## 1.11.24
4
+
5
+ ### Patch Changes
6
+
7
+ - 68d57fd: Update Enhancement in VMS
8
+
3
9
  ## 1.11.23
4
10
 
5
11
  ### Patch Changes
@@ -97,7 +97,7 @@ const props = defineProps({
97
97
  site: { type: String, required: true, default: "" },
98
98
  scheduleAreaId: { type: String, required: true, default: "" },
99
99
  type: { type: String, required: true, default: "cleaner" },
100
- scheduleRoute: { type: String, default: "cleaning-schedule" },
100
+ scheduleRoute: { type: String, default: "pest-schedule" },
101
101
  });
102
102
 
103
103
  const { formatDate, back, debounce } = useUtils();
@@ -76,6 +76,15 @@
76
76
  {{ value || "No Status" }}
77
77
  </v-chip>
78
78
  </template>
79
+ <template #item.completedAt="{ value }">
80
+ {{
81
+ formatDate
82
+ ? formatDate(value)
83
+ : value
84
+ ? new Date(value).toLocaleString()
85
+ : ""
86
+ }}
87
+ </template>
79
88
  <template #item.download="{ item }">
80
89
  <v-btn
81
90
  v-if="canDownloadSchedule"
@@ -136,7 +145,7 @@ const headers = [
136
145
  { title: "Created Date", value: "createdAt" },
137
146
  { title: "Close in", value: "closeIn" },
138
147
  { title: "Status", value: "status" },
139
- { title: "Completion Date", value: "completionDate" },
148
+ { title: "Completion Date", value: "completedAt" },
140
149
  { title: "", value: "download" },
141
150
  ];
142
151
  const remainingTime = ref({} as Record<string, string>);
@@ -441,7 +441,6 @@
441
441
 
442
442
  <script setup lang="ts">
443
443
  import useEquipmentItem from "../composables/useEquipmentItem";
444
- import { useEquipmentItemPermission } from "../composables/useEquipmentItemPermission";
445
444
  import useEquipmentManagement from "../composables/useEquipmentManagement";
446
445
  import useFile from "../composables/useFile";
447
446
  import useUtils from "../composables/useUtils";
@@ -450,9 +449,12 @@ const props = defineProps({
450
449
  orgId: { type: String, default: "" },
451
450
  site: { type: String, default: "" },
452
451
  serviceType: { type: String, default: "" },
452
+ canViewAllEquipmentItems: { type: Boolean, default: true },
453
+ canCreateEquipmentItem: { type: Boolean, default: false },
453
454
  });
454
455
 
455
- const { canCreateEquipmentItem } = useEquipmentItemPermission();
456
+ const canViewAllEquipmentItems = computed(() => props.canViewAllEquipmentItems);
457
+ const canCreateEquipmentItem = computed(() => props.canCreateEquipmentItem);
456
458
 
457
459
  const items = ref<Array<Record<string, any>>>([]);
458
460
  const siteName = ref<string>("");
@@ -247,7 +247,6 @@
247
247
  <script setup lang="ts">
248
248
  import useEquipment from "../composables/useEquipment";
249
249
  import useStock from "../composables/useStock";
250
- import { useEquipmentPermission } from "../composables/useEquipmentPermission";
251
250
  import useUtils from "../composables/useUtils";
252
251
  import useEquipmentManagement from "../composables/useEquipmentManagement";
253
252
 
@@ -255,17 +254,22 @@ const props = defineProps({
255
254
  orgId: { type: String, default: "" },
256
255
  site: { type: String, default: "" },
257
256
  serviceType: { type: String, default: "" },
257
+ canViewEquipments: { type: Boolean, default: true },
258
+ canAddEquipment: { type: Boolean, default: false },
259
+ canUpdateEquipment: { type: Boolean, default: false },
260
+ canDeleteEquipment: { type: Boolean, default: false },
261
+ canAddStock: { type: Boolean, default: false },
262
+ canViewStock: { type: Boolean, default: true },
263
+ canRequestItem: { type: Boolean, default: false },
258
264
  });
259
265
 
260
- const {
261
- canViewEquipments,
262
- canAddEquipment,
263
- canUpdateEquipment,
264
- canDeleteEquipment,
265
- canAddStock,
266
- canViewStock,
267
- canRequestItem,
268
- } = useEquipmentPermission();
266
+ const canViewEquipments = computed(() => props.canViewEquipments);
267
+ const canAddEquipment = computed(() => props.canAddEquipment);
268
+ const canUpdateEquipment = computed(() => props.canUpdateEquipment);
269
+ const canDeleteEquipment = computed(() => props.canDeleteEquipment);
270
+ const canAddStock = computed(() => props.canAddStock);
271
+ const canViewStock = computed(() => props.canViewStock);
272
+ const canRequestItem = computed(() => props.canRequestItem);
269
273
 
270
274
  const items = ref<Array<Record<string, any>>>([]);
271
275
  const siteName = ref<string>("");
@@ -17,7 +17,7 @@
17
17
  </v-col>
18
18
  </v-row>
19
19
  <TableHygiene
20
- :title="'Cleaner Checklist'"
20
+ :title="scheduleTitle"
21
21
  :headers="headers"
22
22
  :items="items"
23
23
  :item-value="'unit'"
@@ -319,6 +319,18 @@ const props = defineProps({
319
319
  const { getUnitCleanerChecklist, updateUnitChecklist } = useCleaningSchedules();
320
320
  const { getBySiteAsServiceProvider } = useCustomerSite();
321
321
  const { back } = useUtils();
322
+
323
+ const route = useRoute();
324
+ const scheduleTitle = computed(() => {
325
+ const path = route.path;
326
+ if (path.includes('cleaning-schedule')) return 'Cleaning Checklist';
327
+ if (path.includes('technician-schedule')) return 'Technician Checklist';
328
+ if (path.includes('landscape-schedule')) return 'Landscape Checklist';
329
+ if (path.includes('pool-schedule')) return 'Pool Checklist';
330
+ if (path.includes('pest-schedule')) return 'Pest Checklist';
331
+ return 'Cleaner Checklist';
332
+ });
333
+
322
334
  const canAddRemarks = computed(() => props.canAddRemarks);
323
335
  const canManageScheduleTasks = computed(() => props.canManageScheduleTasks);
324
336
 
@@ -32,7 +32,7 @@
32
32
  <!-- This is where the QR code scanner will be displayed -->
33
33
  </div>
34
34
  <!-- Show Error Messages -->
35
- <div v-if="showNotFoundMessage" class="text-error mt-4">
35
+ <div v-if="showNotFoundMessage" class="text-error mt-4 text-h5">
36
36
  <p>{{ errorMessage }}</p>
37
37
  </div>
38
38
  <!-- Switch camera button inside the reader box -->
@@ -58,6 +58,8 @@ const props = defineProps({
58
58
  },
59
59
  });
60
60
 
61
+ const { standardFormatDate } = useUtils();
62
+
61
63
  const { validateVisitorQrCode } = useVisitor();
62
64
 
63
65
  const emits = defineEmits([
@@ -109,9 +111,14 @@ const handleScanVisitorQRCode = async () => {
109
111
  console.log("validateVisitorQrCode", response);
110
112
  if (response.errorMessage) {
111
113
  showNotFoundMessage.value = true;
112
- errorMessage.value = response.errorMessage;
114
+ errorMessage.value =
115
+ response.errorMessage +
116
+ (response.scheduledDate
117
+ ? standardFormatDate(response.scheduledDate)
118
+ : "");
113
119
  showMessage(errorMessage.value, "error");
114
120
  } else {
121
+ closeDialog();
115
122
  emits("openVisitorDataFromScannedQrCodeDialog", response);
116
123
  }
117
124
  } else {
@@ -192,7 +192,6 @@ const headers = [
192
192
  { title: "Status", value: "status" },
193
193
  { title: "Type", value: "type" },
194
194
  { title: "No. of Visits", value: "set" },
195
- { title: "Created By", value: "createdByName" },
196
195
  ];
197
196
 
198
197
  const { formatDate, back } = useUtils();
@@ -28,7 +28,7 @@
28
28
  />
29
29
  </v-col>
30
30
 
31
- <v-col cols="12">
31
+ <v-col v-if="!visitorInfo.checkIn" cols="12">
32
32
  <InputLabel class="text-capitalize" title="NRIC/Passport/ID No." />
33
33
  <v-text-field
34
34
  v-if="!visitorInfo.checkIn"
@@ -46,7 +46,7 @@
46
46
  />
47
47
  </v-col>
48
48
 
49
- <v-col cols="12" class="mt-4">
49
+ <v-col v-if="!visitorInfo.checkIn" cols="12" class="mt-4">
50
50
  <InputLabel
51
51
  class="text-capitalize"
52
52
  title="Vehicle Number (Optional)"
@@ -67,7 +67,7 @@
67
67
  />
68
68
  </v-col>
69
69
 
70
- <v-col cols="12" class="mt-4">
70
+ <!-- <v-col cols="12" class="mt-4">
71
71
  <InputLabel class="text-capitalize" title="Type" />
72
72
  <v-text-field
73
73
  v-model="visitorInfo.type"
@@ -75,9 +75,9 @@
75
75
  hide-details
76
76
  readonly
77
77
  />
78
- </v-col>
78
+ </v-col> -->
79
79
 
80
- <v-col cols="12" class="mt-4">
80
+ <v-col v-if="!visitorInfo.checkIn" cols="12" class="mt-4">
81
81
  <InputLabel class="text-capitalize" title="Phone Number" />
82
82
  <InputPhoneNumberV2
83
83
  v-model="visitorInfo.contact"
@@ -87,32 +87,62 @@
87
87
  </v-col>
88
88
 
89
89
  <v-col cols="12">
90
+ <InputLabel class="text-capitalize" title="Location" />
91
+ <v-text-field v-model="location" density="comfortable" readonly />
92
+ </v-col>
93
+
94
+ <v-col v-if="!visitorInfo.checkIn" cols="12">
90
95
  <InputLabel class="text-capitalize" title="Purpose" />
91
96
  <v-textarea
92
97
  v-model="visitorInfo.purpose"
93
98
  density="comfortable"
94
- :rows="3"
99
+ :rows="2"
95
100
  no-resize
96
101
  readonly
97
102
  />
98
103
  </v-col>
99
104
 
100
- <v-col cols="12">
101
- <InputLabel class="text-capitalize" title="Location" />
102
- <v-text-field v-model="location" density="comfortable" />
105
+ <v-col v-if="!visitorInfo.checkIn" cols="12">
106
+ <InputLabel class="text-capitalize" title="Remarks" />
107
+ <v-textarea
108
+ v-model="visitorInfo.remarks"
109
+ density="comfortable"
110
+ :rows="2"
111
+ no-resize
112
+ />
103
113
  </v-col>
104
114
 
105
- <v-col cols="12">
115
+ <v-col v-if="!visitorInfo.checkIn" cols="12">
106
116
  <InputLabel class="text-capitalize" title="Visitor Pass" />
107
117
  <PassInformation
108
118
  v-model:pass="visitorInfo.visitorPass"
109
119
  :site="prop.site"
110
120
  :type="visitorInfo.type"
121
+ :hideKeys="true"
111
122
  :clearable="true"
112
123
  />
113
124
  </v-col>
114
125
 
115
- <v-col cols="12" class="mt-4">
126
+ <v-col v-else cols="12">
127
+ <v-card elevation="4" height="100%" width="100%">
128
+ <v-col cols="12" class="d-flex justify-center pb-0">
129
+ <span
130
+ class="text-h6 font-weight-bold d-flex text-center text-success"
131
+ >
132
+ {{
133
+ visitorInfo.checkIn
134
+ ? standardFormatDateTime(visitorInfo.checkIn)
135
+ : "N/A"
136
+ }}
137
+ </span>
138
+ </v-col>
139
+ <v-col cols="12" class="d-flex justify-center">
140
+ Actual Check In
141
+ </v-col>
142
+ </v-card>
143
+ </v-col>
144
+
145
+ <!-- <v-col cols="12" class="mt-4">
116
146
  <v-row no-gutters class="pt-2">
117
147
  <v-col cols="6" class="pr-1">
118
148
  <v-card elevation="3" height="100%" width="100%">
@@ -151,7 +181,7 @@
151
181
  </v-card>
152
182
  </v-col>
153
183
  </v-row>
154
- </v-col>
184
+ </v-col> -->
155
185
  </v-row>
156
186
  <!-- </v-form> -->
157
187
  </v-card-text>
@@ -177,7 +207,7 @@
177
207
  <v-btn
178
208
  v-if="visitorInfo.checkIn && !visitorInfo.checkOut"
179
209
  block
180
- text="Check Out"
210
+ text="Confirm Check Out"
181
211
  variant="flat"
182
212
  color="error"
183
213
  size="48"
@@ -229,13 +259,13 @@ const visitorPlateNumber = computed({
229
259
  set: () => {}, // readonly, do nothing on set
230
260
  });
231
261
 
232
- watchEffect(() => {
233
- if (visitorInfo.value.plateNumber) {
234
- visitorInfo.value.type = "guest";
235
- } else {
236
- visitorInfo.value.type = "walk-in";
237
- }
238
- });
262
+ // watchEffect(() => {
263
+ // if (visitorInfo.value.plateNumber) {
264
+ // visitorInfo.value.type = "guest";
265
+ // } else {
266
+ // visitorInfo.value.type = "walk-in";
267
+ // }
268
+ // });
239
269
 
240
270
  const location = computed({
241
271
  get: () => {
@@ -475,15 +475,13 @@ async function handleAddNewContractorType() {
475
475
 
476
476
  async function handleSelectCompanyName(company: string) {
477
477
  visitor.company = company
478
+ // const selected = companyAutofillDataArray.value.find(x => x.companyName?.includes(company))
479
+ // if (!selected) return
478
480
 
479
- const selected = companyAutofillDataArray.value.find(x => x.companyName?.includes(company))
480
- if (!selected) return
481
-
482
- visitor.block = selected.block || ""
483
- visitor.level = selected.level || ""
484
- visitor.unit = selected.unit || ""
485
- visitor.unitName = selected.unitName || ""
486
-
481
+ // visitor.block = selected.block || ""
482
+ // visitor.level = selected.level || ""
483
+ // visitor.unit = selected.unit || ""
484
+ // visitor.unitName = selected.unitName || ""
487
485
  }
488
486
 
489
487
  const companyCombo = ref(null)
@@ -297,6 +297,36 @@
297
297
  </v-row>
298
298
  </template>
299
299
 
300
+ <template v-slot:item.arrival-date-time="{ item }">
301
+ <v-row no-gutters class="d-flex flex-column py-2">
302
+ <span class="d-flex align-center ga-2">
303
+ <v-icon icon="mdi-calendar" size="20" />
304
+ {{ standardFormatDate(item.expectedCheckIn) || "-" }}
305
+ </span>
306
+ <span class="d-flex align-center ga-2">
307
+ <v-icon icon="mdi-clock-time-four-outline" size="20" />
308
+ {{ formatTime(item.expectedCheckIn) || "-" }}
309
+ </span>
310
+
311
+ <span v-if="!item.checkIn && canUpdateVisitor">
312
+ <span class="d-flex align-center ga-2 cursor-pointer">
313
+ <v-icon
314
+ icon="mdi-clock-time-eight-outline"
315
+ color="success"
316
+ size="20"
317
+ />
318
+ <v-btn
319
+ size="x-small"
320
+ class="text-capitalize"
321
+ color="success"
322
+ text="Checkin"
323
+ @click.stop="handleCheckIn(item)"
324
+ />
325
+ </span>
326
+ </span>
327
+ </v-row>
328
+ </template>
329
+
300
330
  <template v-slot:item.action="{ item }">
301
331
  <v-btn
302
332
  v-if="activeTab === 'unregistered' && canAddVisitor"
@@ -496,6 +526,25 @@
496
526
  <p class="text-body-2 mb-3">
497
527
  Please ensure all passes and keys are returned before checking out.
498
528
  </p>
529
+
530
+ <div>
531
+ <InputLabel class="text-capitalize" title="Full Name" />
532
+ <v-text-field
533
+ v-model="selectedVisitorObject.name"
534
+ density="comfortable"
535
+ readonly
536
+ />
537
+ </div>
538
+
539
+ <div>
540
+ <InputLabel class="text-capitalize" title="Location" />
541
+ <v-text-field
542
+ v-model="selectedVisitorObject.location"
543
+ density="comfortable"
544
+ readonly
545
+ />
546
+ </div>
547
+
499
548
  <div v-if="passReturnStatuses.length > 0" class="mb-2">
500
549
  <p class="text-caption text-medium-emphasis mb-1">Passes</p>
501
550
  <v-row
@@ -709,10 +758,16 @@ const {
709
758
  visitorSelection,
710
759
  typeFieldMap,
711
760
  updateVisitor,
712
- visitorDataFromScannedQRCodeCheckInOut,
761
+ visitorDataFromScannedQRCodeCheckIn,
713
762
  } = useVisitor();
714
- const { debounce, formatCamelCaseToWords, formatDate, UTCToLocalTIme } =
715
- useUtils();
763
+ const {
764
+ debounce,
765
+ formatCamelCaseToWords,
766
+ formatDate,
767
+ formatTime,
768
+ UTCToLocalTIme,
769
+ standardFormatDate,
770
+ } = useUtils();
716
771
  const { formatLocation } = useSecurityUtils();
717
772
  const { getFileUrlAnpr } = useFile();
718
773
  // const { status: visitorStatus, search } = useRoute().query as { status: string, search: string};
@@ -775,7 +830,9 @@ const headers = computed(() => [
775
830
  { title: "Type/Company", value: "type-company" },
776
831
  { title: "Location", value: "location" },
777
832
  { title: "Contact/Vehicle No.", value: "contact-vehicleNumber" },
778
- { title: "Check In/Out", value: "checkin-out" },
833
+ ...(activeTab.value != "guests"
834
+ ? [{ title: "Check In/Out", value: "checkin-out" }]
835
+ : [{ title: "Arrival Date / Time", value: "arrival-date-time" }]),
779
836
  ...(activeTab.value === "resident-transactions"
780
837
  ? [
781
838
  { title: "Check-in Remarks", value: "checkInRemarks" },
@@ -880,7 +937,7 @@ const {
880
937
 
881
938
  if (activeTab.value === "guests") {
882
939
  params.type = "guest";
883
- params.status = "pending";
940
+ params.status = "approved";
884
941
  } else if (activeTab.value === "resident-transactions") {
885
942
  params.status = "registered";
886
943
  params.type = "resident,tenant";
@@ -916,7 +973,9 @@ watch(getVisitorReq, (newData: any) => {
916
973
  const selectedVisitorObject = computed(() => {
917
974
  const obj = items.value.find((x: any) => x?._id === selectedVisitorId.value);
918
975
  if (!obj) return {};
976
+
919
977
  const type = obj?.type as TVisitorType | undefined;
978
+
920
979
  let includedKeys: string[] = [
921
980
  "checkIn",
922
981
  "checkOut",
@@ -925,9 +984,23 @@ const selectedVisitorObject = computed(() => {
925
984
  "snapshotExitImage",
926
985
  ];
927
986
  includedKeys.unshift(...(typeFieldMap[type] ?? []));
928
- return Object.fromEntries(
929
- Object.entries(obj).filter(([key]) => includedKeys.includes(key))
930
- );
987
+
988
+ let locationString = "N/A";
989
+
990
+ if (obj?.block || obj?.level || obj?.unitName) {
991
+ locationString = `${obj.block} / ${obj.level} / ${obj.unitName}`;
992
+ } else if (obj?.block) {
993
+ locationString = obj.block;
994
+ } else {
995
+ locationString = "N/A";
996
+ }
997
+
998
+ return {
999
+ ...Object.fromEntries(
1000
+ Object.entries(obj).filter(([key]) => includedKeys.includes(key))
1001
+ ),
1002
+ location: locationString,
1003
+ };
931
1004
  });
932
1005
 
933
1006
  function formatValues(key: string, value: any) {
@@ -947,9 +1020,20 @@ function formatValues(key: string, value: any) {
947
1020
  const visitorDataFromScannedQRCode = ref<Record<string, any>>({});
948
1021
 
949
1022
  function handleShowVisitorDataFromScannedQRCodeDialog(
950
- _visitorDataFromScannedQRCode: Record<string, any>
1023
+ scannedData: Record<string, any>
951
1024
  ) {
952
- visitorDataFromScannedQRCode.value = _visitorDataFromScannedQRCode;
1025
+ visitorDataFromScannedQRCode.value = scannedData;
1026
+
1027
+ const { checkIn, checkOut, _id, visitorPass } = scannedData;
1028
+ const hasPasses = (visitorPass?.length ?? 0) > 0;
1029
+
1030
+ // 1. If they are checked in and HAVE passes/keys, go to the Return screen
1031
+ if (checkIn && !checkOut && hasPasses) {
1032
+ handleCheckout(_id);
1033
+ return;
1034
+ }
1035
+
1036
+ // 2. Default Case: Show visitor data (Entry, already checked out, or checked in with no passes)
953
1037
  dialog.showVisitorDataFromScannedQRCode = true;
954
1038
  }
955
1039
 
@@ -961,24 +1045,31 @@ async function handleVisitorDataFromScannedQRCodeCheckInOut(
961
1045
  ) {
962
1046
  try {
963
1047
  isVisitorDataFromScannedQRCodeCheckingInOut.value = true;
964
- await visitorDataFromScannedQRCodeCheckInOut({
965
- type,
966
- filter: {
967
- _id: visitorData._id,
968
- },
969
- update: {
970
- updatedBy: currentUser.value._id,
971
- visitorPassIds: visitorData.visitorPass.map(
972
- (i: Record<string, any>) => i.keyId
973
- ),
974
- nric: visitorData.nric ?? "",
975
- plateNumber: visitorData.plateNumber ?? "",
976
- },
977
- userType: "site",
978
- });
979
-
980
- dialog.scanVisitorQRCode = false;
1048
+ if (type != "checkOut") {
1049
+ await visitorDataFromScannedQRCodeCheckIn({
1050
+ type,
1051
+ filter: {
1052
+ _id: visitorData._id,
1053
+ },
1054
+ update: {
1055
+ updatedBy: currentUser.value._id,
1056
+ visitorPass: visitorData.visitorPass.find(
1057
+ (i: Record<string, any>) => i.keyId === null
1058
+ )
1059
+ ? undefined
1060
+ : visitorData.visitorPass,
1061
+ nric: visitorData.nric ?? "",
1062
+ plateNumber: visitorData.plateNumber ?? "",
1063
+ },
1064
+ userType: "site",
1065
+ });
1066
+ showMessage("Visitor successfully checked-in!", "info");
1067
+ } else {
1068
+ selectedVisitorId.value = visitorData._id;
1069
+ await proceedCheckout();
1070
+ }
981
1071
  handleCloseVisitorDataFromScannedQRCodeDialog();
1072
+ getVisitorRefresh();
982
1073
  } catch (error) {
983
1074
  showMessage(errorConverter(error), "error");
984
1075
  } finally {
@@ -1171,6 +1262,11 @@ const canConfirmCheckout = computed(() => {
1171
1262
  });
1172
1263
  });
1173
1264
 
1265
+ async function handleCheckIn(user: Record<string, any>) {
1266
+ visitorDataFromScannedQRCode.value = user;
1267
+ dialog.showVisitorDataFromScannedQRCode = true;
1268
+ }
1269
+
1174
1270
  function handleCheckout(userId: string) {
1175
1271
  if (!userId) {
1176
1272
  showMessage("Invalid userId", "error");
@@ -174,7 +174,7 @@ export default function () {
174
174
  );
175
175
  }
176
176
 
177
- function visitorDataFromScannedQRCodeCheckInOut(payload: any) {
177
+ function visitorDataFromScannedQRCodeCheckIn(payload: any) {
178
178
  return useNuxtApp().$api<Record<string, any>>("/api/visitors/update-one", {
179
179
  method: "PUT",
180
180
  body: payload,
@@ -191,6 +191,6 @@ export default function () {
191
191
  deleteVisitor,
192
192
  validateVisitorQrCode,
193
193
  updateVisitorPassKey,
194
- visitorDataFromScannedQRCodeCheckInOut,
194
+ visitorDataFromScannedQRCodeCheckIn,
195
195
  };
196
196
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@7365admin1/layer-common",
3
3
  "license": "MIT",
4
4
  "type": "module",
5
- "version": "1.11.23",
5
+ "version": "1.11.24",
6
6
  "author": "7365admin1",
7
7
  "main": "./nuxt.config.ts",
8
8
  "publishConfig": {