@7365admin1/layer-common 1.11.16 → 1.11.18

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,17 @@
1
1
  # @iservice365/layer-common
2
2
 
3
+ ## 1.11.18
4
+
5
+ ### Patch Changes
6
+
7
+ - 5e21af9: updates and fixes
8
+
9
+ ## 1.11.17
10
+
11
+ ### Patch Changes
12
+
13
+ - 785495f: Update layer-common
14
+
3
15
  ## 1.11.16
4
16
 
5
17
  ### Patch Changes
@@ -26,7 +26,11 @@ const prop = defineProps({
26
26
  member: {
27
27
  type: Object as PropType<TMemberInfo>,
28
28
  required: true
29
- }
29
+ },
30
+ visitorPassItems: {
31
+ type: Array as PropType<TPassKey[]>,
32
+ default: () => []
33
+ }
30
34
  })
31
35
 
32
36
  const emit = defineEmits(['remove'])
@@ -19,9 +19,9 @@
19
19
  </v-col>
20
20
 
21
21
  <v-col cols="12">
22
- <v-combobox v-model="pass" v-model:search="passInput" :hide-no-data="false" class="mt-3"
23
- @update:focused="handleFocusedPass" :items="passItems" item-value="value"
24
- @update:model-value="handleSelectPass" label="Pass (optional)" variant="outlined"
22
+ <v-autocomplete v-model="memberForm.visitorPass" v-model:search="passInput"
23
+ :hide-no-data="false" class="mt-3" :items="passItemsFilteredFinal"
24
+ item-title="prefixAndName" item-value="_id" label="Pass (optional)" variant="outlined"
25
25
  hide-details density="compact" persistent-hint small-chips>
26
26
  <template v-slot:no-data>
27
27
  <v-list-item density="compact">
@@ -33,12 +33,19 @@
33
33
  <v-list-item v-else>No data available</v-list-item>
34
34
  </v-list-item>
35
35
  </template>
36
- </v-combobox>
36
+
37
+ <template v-slot:chip="{ props, item }">
38
+ <v-chip v-if="memberForm.visitorPass" v-bind="props"
39
+ prepend-icon="mdi-card-bulleted-outline"
40
+ :text="item.raw?.prefixAndName"></v-chip>
41
+ </template>
42
+ </v-autocomplete>
37
43
  </v-col>
38
44
 
39
45
  <v-col cols="12">
40
46
  <InputLabel class="text-capitalize" title="Phone Number" required />
41
- <InputPhoneNumberV2 v-model="memberForm.contact" density="compact" hide-details/>
47
+ <InputPhoneNumberV2 v-model="memberForm.contact" density="compact" default-country="SG"
48
+ hide-details />
42
49
  </v-col>
43
50
 
44
51
  <v-row class="pt-3" justify="space-between">
@@ -56,20 +63,41 @@
56
63
  </v-card-text>
57
64
  </v-card>
58
65
  <v-divider class="my-3" />
59
- <v-row v-if="members.length > 0" no-gutters class="w-100 mt-5 ga-3">
60
- <template v-for="member, index in members" :key="member.nric">
61
- <CardMemberInfoSummary :member="member" @remove="handleRemoveMember(index)" />
66
+ <v-row v-if="committedMembers.length > 0" no-gutters class="w-100 mt-5 ga-3">
67
+ <template v-for="member, index in committedMembers" :key="member.nric">
68
+ <CardMemberInfoSummary :member="membersDisplayed[index]" @remove="handleRemoveMember(index)" />
62
69
  </template>
63
70
  </v-row>
64
71
  </v-row>
65
72
  </template>
66
73
 
67
74
  <script setup lang="ts">
75
+ import type { PropType } from 'vue'
76
+ import usePassKey from '../composables/usePassKey'
77
+ import useUtils from '../composables/useUtils'
78
+
68
79
 
69
80
  const props = defineProps({
81
+ type: {
82
+ type: String,
83
+ required: true
84
+ },
85
+ contractorType: {
86
+ type: String,
87
+ required: false
88
+ },
89
+ site: {
90
+ type: String,
91
+ required: true
92
+ },
93
+ selectedVisitorPass: {
94
+ type: Array as PropType<TPassKeyPayload[]>,
95
+ default: () => []
96
+ }
70
97
  })
71
98
 
72
99
  const { requiredRule } = useUtils()
100
+ const { getPassKeysByPageSearch } = usePassKey()
73
101
 
74
102
 
75
103
  const memberForm = reactive<TMemberInfo>({
@@ -85,33 +113,77 @@ const processing = ref(false);
85
113
  const errorMessage = ref('')
86
114
 
87
115
  // pass
88
- const pass = ref()
89
116
  const passInput = ref('')
90
- const passItems = ref(['Test'])
117
+ const passItems = ref<TPassKey[]>([])
118
+
119
+ const members = defineModel<TMemberInfo[]>({ required: true, default: [] })
120
+ const committedMembers = ref<TMemberInfo[]>([])
121
+
122
+ // Always keep the model in sync: committed members + current form draft
123
+ watch(() => memberForm, (newForm) => {
124
+ if (memberForm.name && memberForm.nric && memberForm.contact) {
125
+ members.value = [...committedMembers.value, { ...newForm }]
126
+ } else {
127
+ members.value = [...committedMembers.value]
128
+ }
129
+ }, { deep: true })
130
+
131
+
132
+ const passTypesComputed = computed(() => {
133
+ if (props.type === 'contractor') {
134
+ if (props.contractorType === 'property-agent') {
135
+ return ["agent-pass"]
136
+ } else {
137
+ return ["contractor-pass"]
138
+ }
139
+ } else {
140
+ return ["visitor-pass"]
141
+ }
142
+ })
91
143
 
92
- const members = defineModel<TMemberInfo[]>({required: true, default: []})
144
+ const { data: passesData, refresh: refreshPassesData, pending: fetchPassesPending } = await useLazyAsyncData('get-pass-keys', () => {
145
+ return getPassKeysByPageSearch({
146
+ search: passInput.value,
147
+ page: 1,
148
+ limit: 500,
149
+ passTypes: passTypesComputed.value,
150
+ sites: [props.site],
151
+ statuses: ["Available"]
152
+ })
153
+ })
93
154
 
155
+ watch(passesData, (data: any) => {
156
+ passItems.value = Array.isArray(data?.items) ? data.items : []
157
+ })
94
158
 
95
- function handleFocusedPass() {
159
+ const passItemsFilteredFinal = computed(() => {
160
+ return passItems.value.filter((item: TPassKey) => {
161
+ return !props.selectedVisitorPass.some((pass: TPassKeyPayload) => pass.keyId === item._id) && !committedMembers.value.some((member: TMemberInfo) => member.visitorPass === item._id)
162
+ })
163
+ })
164
+
165
+ const membersDisplayed = computed(() => {
166
+ return committedMembers.value.map((member: TMemberInfo) => {
167
+ return {
168
+ ...member,
169
+ visitorPass: passItems.value.find((item: TPassKey) => item._id === member.visitorPass)?.prefixAndName || ""
170
+ }
171
+ })
172
+ })
96
173
 
97
- }
98
174
 
99
- function handleSelectPass(val: any) {
100
- memberForm.visitorPass = val
101
- }
102
175
 
103
176
  function handleClearForm() {
104
177
  formRef.value?.reset()
105
178
  }
106
179
 
107
180
  async function handleAddMember() {
108
- members.value.push({...memberForm})
181
+ committedMembers.value.push({ ...memberForm })
109
182
  handleClearForm()
110
183
  }
111
184
 
112
- function handleRemoveMember(index: number){
113
- const filtered = members.value.filter((item, qIndex) => qIndex !== index)
114
- members.value = filtered
185
+ function handleRemoveMember(index: number) {
186
+ committedMembers.value = committedMembers.value.filter((_, i) => i !== index)
115
187
  }
116
188
 
117
189
 
@@ -4,27 +4,36 @@
4
4
  <v-card-text>
5
5
  <v-btn block color="primary-button" :height="40" text="Scan QR Code" class="text-capitalize" disabled
6
6
  prepend-icon="mdi-qrcode" />
7
- <v-combobox v-model="pass" v-model:search="passInput" :hide-no-data="false" class="mt-3"
8
- @update:focused="handleFocusedPass" :items="passItems" :rules="props.passRules" item-title="prefixAndName" item-value="_id"
9
- @update:model-value="handleSelectPass" label="Pass" variant="outlined" hide-details
10
- density="compact" persistent-hint small-chips>
11
- <template v-slot:no-data>
12
- <v-list-item density="compact">
13
- <v-list-item-title v-if="passInput">
14
- No results matching "<strong>{{ passInput }}</strong>". This value will be
15
- added as new
16
- option.
17
- </v-list-item-title>
18
- <v-list-item v-else>No data available</v-list-item>
19
- </v-list-item>
7
+ <v-autocomplete v-model="selectedPass" v-model:search="passInput" :hide-no-data="false" class="mt-3"
8
+ :items="passItems" :rules="props.passRules" item-title="prefixAndName" item-value="_id" label="Pass"
9
+ variant="outlined" hide-details density="compact" persistent-hint small-chips>
10
+
11
+ <template v-slot:chip="{ props, item }">
12
+ <v-chip v-if="selectedPass" v-bind="props" prepend-icon="mdi-card-bulleted-outline"
13
+ :text="item.raw?.prefixAndName"></v-chip>
20
14
  </template>
21
- </v-combobox>
15
+ </v-autocomplete>
16
+
17
+
18
+ <template v-if="!props.hideKeys">
19
+ <v-autocomplete v-model="selectedKeys" v-model:search="keyInput" :hide-no-data="false" class="mt-3"
20
+ :items="keyItems" :rules="props.passRules" item-title="prefixAndName" item-value="_id"
21
+ label="Keys" multiple variant="outlined" hide-details density="compact" persistent-hint
22
+ small-chips>
23
+
24
+ <template v-slot:chip="{ props, item }">
25
+ <v-chip v-if="selectedKeys.length > 0" v-bind="props" prepend-icon="mdi-key"
26
+ :text="item.raw?.prefixAndName"></v-chip>
27
+ </template>
28
+ </v-autocomplete>
29
+ </template>
22
30
 
23
31
  <v-divider class="my-4 w-100" />
24
-
32
+
25
33
 
26
34
  <template v-if="selectedType">
27
- <v-number-input v-model="count" variant="outlined" :min="1" :precision="0" density="compact" :rules="countRules" />
35
+ <v-number-input v-model="count" variant="outlined" :min="1" :precision="0" density="compact"
36
+ :rules="countRules" />
28
37
  </template>
29
38
  </v-card-text>
30
39
  </v-card>
@@ -35,6 +44,7 @@
35
44
  import type { PropType } from 'vue'
36
45
  import type { ValidationRule } from 'vuetify/lib/types.mjs'
37
46
  import usePassKey from '../composables/usePassKey'
47
+ import useKey from '../composables/useKey'
38
48
 
39
49
  const props = defineProps({
40
50
  passRules: {
@@ -56,12 +66,21 @@ const props = defineProps({
56
66
  contractorType: {
57
67
  type: String,
58
68
  default: ""
69
+ },
70
+ hideKeys: {
71
+ type: Boolean,
72
+ default: false
59
73
  }
60
74
  })
61
75
 
62
- const pass = ref("")
76
+ const pass = defineModel<TPassKeyPayload[]>("pass", { default: [] })
77
+ const keys = defineModel<TPassKeyPayload[]>("keys", { default: [] })
78
+ const selectedPass = ref<string>('')
79
+ const selectedKeys = ref<string[]>([])
63
80
  const passInput = ref('')
64
- const passItems = ref([])
81
+ const keyInput = ref('')
82
+ const passItems = ref<TPassKey[]>([])
83
+ const keyItems = ref<any[]>([])
65
84
  const selectedType = ref<'qr-pass' | 'nfc-card'>()
66
85
  const count = ref(1)
67
86
 
@@ -79,15 +98,15 @@ const typeItems = [
79
98
  ]
80
99
 
81
100
  const passTypesComputed = computed(() => {
82
- if(props.type === 'contractor'){
83
- if(props.contractorType === 'property-agent'){
84
- return ["agent-pass"]
101
+ if (props.type === 'contractor') {
102
+ if (props.contractorType === 'property-agent') {
103
+ return ["agent-pass"]
104
+ } else {
105
+ return ["contractor-pass"]
106
+ }
85
107
  } else {
86
- return ["contractor-pass"]
108
+ return ["visitor-pass"]
87
109
  }
88
- } else {
89
- return ["visitor-pass"]
90
- }
91
110
  })
92
111
 
93
112
  const { data: passesData, refresh: refreshPassesData, pending: fetchPassesPending } = await useLazyAsyncData('get-pass-keys', () => {
@@ -105,22 +124,48 @@ watch(passesData, (data: any) => {
105
124
  passItems.value = data?.items || []
106
125
  })
107
126
 
127
+ const { data: keysData, refresh: refreshKeysData, pending: fetchKeysPending } = await useLazyAsyncData('get-keys', () => {
128
+ return getPassKeysByPageSearch({
129
+ search: keyInput.value,
130
+ statuses: ["Available"],
131
+ passTypes: ['pass-key'],
132
+ page: 1,
133
+ limit: 500,
134
+ sites: [props.site],
135
+ })
136
+ })
137
+
138
+ watch(keysData, (data: any) => {
139
+ keyItems.value = data?.items || []
140
+ })
108
141
 
109
- function handleFocusedPass() {
142
+ watch(selectedPass, (newVal) => {
143
+ pass.value = [{ keyId: newVal }]
144
+ })
145
+
146
+ watch(selectedKeys, (newVal) => {
147
+ keys.value = newVal.map(key => ({ keyId: key }))
148
+ })
110
149
 
111
- }
112
150
 
113
- function handleSelectPass() {
114
151
 
115
- }
116
152
 
117
153
  //prevent negative value;
118
154
  watch(count, (newCount) => {
119
- if(newCount < 1){
155
+ if (newCount < 1) {
120
156
  count.value = 1
121
157
  }
122
158
  })
123
159
 
160
+ onMounted(() => {
161
+ if (pass.value.length > 0) {
162
+ selectedPass.value = pass.value[0].keyId
163
+ }
164
+ if (keys.value.length > 0) {
165
+ selectedKeys.value = keys.value.map(k => k.keyId)
166
+ }
167
+ })
168
+
124
169
  </script>
125
170
 
126
171
  <style scoped></style>
@@ -9,8 +9,8 @@
9
9
  <v-row no-gutters class="px-5 py-1 d-flex align-center justify-end ga-3">
10
10
  <v-text-field v-model="searchInput" density="compact" placeholder="Search" clearable max-width="300"
11
11
  append-inner-icon="mdi-magnify" hide-details />
12
- <v-select v-model="vehicleTypeFilter" density="compact" item-title="label" item-value="value"
13
- placeholder="Filter by Type" clearable max-width="200" hide-details :items="typeOptions" />
12
+ <!-- <v-select v-model="vehicleTypeFilter" density="compact" item-title="label" item-value="value"
13
+ placeholder="Filter by Type" clearable max-width="200" hide-details :items="typeOptions" /> -->
14
14
  </v-row>
15
15
  </template>
16
16
 
@@ -37,8 +37,8 @@
37
37
  </v-dialog>
38
38
 
39
39
  <v-dialog v-model="dialog.createVehicle" v-if="vehicleType" width="450" persistent>
40
- <VehicleForm :type="vehicleType" mode="add" :vehicle-data="selectedVehicleObject" @back="handleBackToSelection" @done="handleAddVehicleComplete"
41
- :org="org" :site="props.site" @close:all="handleCloseAll" />
40
+ <VehicleForm :type="vehicleType" mode="add" :vehicle-data="selectedVehicleObject" @back="handleBackToSelection"
41
+ @done="handleAddVehicleComplete" :org="org" :site="props.site" @close:all="handleCloseAll" />
42
42
  </v-dialog>
43
43
 
44
44
  <!-- <v-dialog v-model="dialog.updateVehicle" v-if="vehicleType" width="450" persistent>
@@ -65,10 +65,23 @@
65
65
  {{ formatVehicleStatus(value).label }}
66
66
  </v-chip>
67
67
  </template>
68
- <template #item.action="{ item }">
69
- <v-btn v-if="canDeleteVehicle && (item as TPlateNumber)?.status == 'active'" text="Delete" color="error" flat size="x-small" @click="handleDeleteVehicleAction(item as TPlateNumber)"/>
70
- <v-btn v-if="props.app === 'property_management_agency' && (item as TPlateNumber)?.status == 'pending'" text="Approve" color="success" flat size="x-small" @click="handleApproveVehicle(item as TPlateNumber)"/>
71
- <v-btn v-if=" (item as TPlateNumber)?.status == 'deleted'" text="Restore" color="orange" flat size="x-small" @click="handleRestoreVehicle(item as TPlateNumber)"/>
68
+ <template #item.action="{ item: plateNumberItem, value }">
69
+ <v-btn v-if="canDeleteVehicle && (plateNumberItem as TPlateNumber)?.status == 'active'"
70
+ text="Delete" color="error" flat size="x-small"
71
+ @click="handleDeleteVehicleAction(plateNumberItem as TPlateNumber)" />
72
+ <v-btn
73
+ v-if="props.app === 'property_management_agency' && (plateNumberItem as TPlateNumber)?.status == 'pending'"
74
+ text="Approve" color="success" flat size="x-small"
75
+ @click="handleApproveVehicle(plateNumberItem as TPlateNumber)" />
76
+ <v-btn v-if="(plateNumberItem as TPlateNumber)?.status == 'deleted'" text="Restore"
77
+ color="orange" flat size="x-small"
78
+ @click="handleRestoreVehicle(plateNumberItem as TPlateNumber)" />
79
+ <v-btn
80
+ v-if="((plateNumberItem as TPlateNumber)?.type === 'whitelist' || (plateNumberItem as TPlateNumber)?.type === 'blocklist') && plateNumberItem?.status == 'active'"
81
+ variant="outlined"
82
+ :text="(plateNumberItem as TPlateNumber)?.type === 'blocklist' ? 'Whitelist' : 'Blocklist'"
83
+ :color="(plateNumberItem as TPlateNumber)?.type === 'blocklist' ? 'primary' : 'red'" flat
84
+ size="x-small" class="ml-1" @click="handleUpdateType(plateNumberItem as TPlateNumber)" />
72
85
  </template>
73
86
  </v-data-table>
74
87
  <v-btn text="Add Vehicle Number" class="mt-6 text-capitalize" prepend-icon="mdi-plus"
@@ -81,7 +94,7 @@
81
94
  <v-col v-else-if="selectedVehicleObject[key]" cols="12">
82
95
  <span class="d-flex ga-3 align-center"><strong>{{ label }}:</strong> {{ formatValues(key,
83
96
  selectedVehicleObject[key])
84
- }}</span>
97
+ }}</span>
85
98
  </v-col>
86
99
  </template>
87
100
  </v-row>
@@ -89,16 +102,24 @@
89
102
  </DialogUpdateMoreAction>
90
103
  </v-dialog>
91
104
  <v-dialog v-model="dialog.deleteVehicle" persistent width="540">
92
- <DialogDeleteConfirmation :loading="deletingVehicle" :prompt-title="`Are you sure want to delete this vehicle - ${selectedPlateNumberObject?.plateNumber}?`"
105
+ <DialogDeleteConfirmation :loading="deletingVehicle"
106
+ :prompt-title="`Are you sure want to delete this vehicle - ${selectedPlateNumberObject?.plateNumber}?`"
93
107
  @delete="submitDelete" @close="closeDeleteDialog" />
94
108
  </v-dialog>
95
109
  <v-dialog v-model="dialog.approveVehicle" persistent width="540">
96
- <DialogReusablePrompt :loading="approvingVehicle" :prompt-title="`Are you sure want to approve this vehicle - ${selectedPlateNumberObject?.plateNumber}?`"
97
- @approve="submitApprove" @close="dialog.approveVehicle = false" />
110
+ <DialogReusablePrompt :loading="approvingVehicle"
111
+ :prompt-title="`Are you sure want to approve this vehicle - ${selectedPlateNumberObject?.plateNumber}?`"
112
+ @proceed="submitApprove" @close="dialog.approveVehicle = false" />
98
113
  </v-dialog>
99
114
  <v-dialog v-model="dialog.restoreVehicle" persistent width="540">
100
- <DialogReusablePrompt :loading="restoringVehicle" :prompt-title="`Are you sure want to restore this vehicle - ${selectedPlateNumberObject?.plateNumber}?`"
101
- @proceed="submitRestore" @close="dialog.restoreVehicle = false" />
115
+ <DialogReusablePrompt :loading="restoringVehicle"
116
+ :prompt-title="`Are you sure want to restore this vehicle - ${selectedPlateNumberObject?.plateNumber}?`"
117
+ @proceed="submitRestore" @close="dialog.restoreVehicle = false" />
118
+ </v-dialog>
119
+ <v-dialog v-model="dialog.updateVehicleType" persistent width="540">
120
+ <DialogReusablePrompt :loading="updatingType"
121
+ :prompt-title="`Are you sure want to update the type of this vehicle - ${selectedPlateNumberObject?.plateNumber}?`"
122
+ @proceed="submitUpdateType" @close="dialog.updateVehicleType = false" />
102
123
  </v-dialog>
103
124
  <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
104
125
  </v-row>
@@ -147,7 +168,7 @@ const plateHeaders = [
147
168
 
148
169
 
149
170
  const { formatCamelCaseToWords, formatDate, debounce } = useUtils();
150
- const { getVehicles, deleteVehicle, formatVehicleStatus, approveVehicle } = useVehicle();
171
+ const { getVehicles, deleteVehicle, formatVehicleStatus, approveVehicle, updateVehicle } = useVehicle();
151
172
 
152
173
  const items = ref<Array<Record<string, any>>>([]);
153
174
  const page = ref(1);
@@ -160,6 +181,7 @@ const loading = ref(false);
160
181
  const deletingVehicle = ref(false);
161
182
  const approvingVehicle = ref(false);
162
183
  const restoringVehicle = ref(false);
184
+ const updatingType = ref(false);
163
185
 
164
186
  const selectedVehicleId = ref<string | null>(null)
165
187
  const vehicleType = ref<TVehicleType | null>(null);
@@ -185,7 +207,8 @@ const dialog = reactive({
185
207
  deleteVehicle: false,
186
208
  showMoreActions: false,
187
209
  approveVehicle: false,
188
- restoreVehicle: false
210
+ restoreVehicle: false,
211
+ updateVehicleType: false
189
212
  });
190
213
 
191
214
 
@@ -280,19 +303,24 @@ function handleEditVehicleAction() {
280
303
  }
281
304
 
282
305
  function handleDeleteVehicleAction(item: TPlateNumber) {
283
- selectedPlateNumberObject.value = item || null;
306
+ selectedPlateNumberObject.value = item || null;
284
307
  dialog.deleteVehicle = true;
285
308
  }
286
309
 
287
310
  function handleApproveVehicle(item: TPlateNumber) {
288
- selectedPlateNumberObject.value = item || null;
311
+ selectedPlateNumberObject.value = item || null;
289
312
  dialog.approveVehicle = true;
290
313
  }
291
314
  function handleRestoreVehicle(item: TPlateNumber) {
292
- selectedPlateNumberObject.value = item || null;
315
+ selectedPlateNumberObject.value = item || null;
293
316
  dialog.restoreVehicle = true;
294
317
  }
295
318
 
319
+ function handleUpdateType(item: TPlateNumber) {
320
+ selectedPlateNumberObject.value = item || null;
321
+ dialog.updateVehicleType = true;
322
+ }
323
+
296
324
  function handleSelectVehicleStatus(value: TVehicleType) {
297
325
  vehicleType.value = value;
298
326
  dialog.showSelection = false;
@@ -341,6 +369,7 @@ async function submitDelete() {
341
369
 
342
370
  const plateNumberId = selectedPlateNumberObject.value?._id;
343
371
  const type = selectedPlateNumberObject.value?.type as TVehicleType;
372
+ const recNo = selectedPlateNumberObject.value?.recNo;
344
373
  if (!plateNumberId) {
345
374
  showMessage("Invalid plate number selected for deletion.", "error");
346
375
  return;
@@ -348,12 +377,11 @@ async function submitDelete() {
348
377
 
349
378
  try {
350
379
  deletingVehicle.value = true;
351
- const res = await deleteVehicle({ site: props.site, id: plateNumberId as string, recno: selectedVehicleObject.value.recno, type }
380
+ const res = await deleteVehicle({ site: props.site, recno: recNo, id: plateNumberId as string, type }
352
381
  );
353
382
  dialog.deleteVehicle = false;
354
- selectedVehicleId.value = null
355
383
  showMessage(res.message, "success");
356
- getVehiclesRefresh();
384
+ await getVehiclesRefresh();
357
385
  } catch (error: any) {
358
386
  console.error("Error deleting vehicle:", error);
359
387
  message.value = error.response._data.message;
@@ -366,24 +394,21 @@ async function submitDelete() {
366
394
 
367
395
  async function submitRestore() {
368
396
 
369
- console.log("Submitting restore for plate number ID:", selectedPlateNumberObject.value);
370
- const plateNumberId = selectedPlateNumberObject.value?._id;
371
-
397
+ const vehicleId = selectedPlateNumberObject.value?._id;
372
398
 
373
- if (!plateNumberId) {
374
- showMessage("Invalid plate number selected for restoration.", "error");
399
+ if (!vehicleId) {
400
+ showMessage("Invalid vehicle Id selected for restoration.", "error");
375
401
  return;
376
402
  }
377
403
 
378
404
  try {
379
- restoringVehicle.value = true;
405
+ restoringVehicle.value = true;
380
406
  // reactivate and restore will use the same endpoint, just with different payload
381
- const res = await approveVehicle({ site: props.site, org: props.org, id: plateNumberId as string }
407
+ const res = await approveVehicle({ site: props.site, org: props.org, id: vehicleId as string }
382
408
  );
383
409
  dialog.restoreVehicle = false;
384
- selectedVehicleId.value = null
385
410
  showMessage(res.message, "success");
386
- getVehiclesRefresh();
411
+ await getVehiclesRefresh();
387
412
  } catch (error: any) {
388
413
  console.error("Error restoring vehicle:", error);
389
414
  const errMessage = error?.response?._data?.message || "Failed to restore vehicle";
@@ -395,6 +420,55 @@ async function submitRestore() {
395
420
  }
396
421
 
397
422
 
423
+ async function submitUpdateType() {
424
+
425
+
426
+ const vehicleId = selectedPlateNumberObject.value?._id;
427
+ const type = selectedPlateNumberObject.value?.type as TVehicleType;
428
+ const recNo = selectedPlateNumberObject.value?.recNo;
429
+
430
+
431
+ if (!type) {
432
+ showMessage("Invalid vehicle type.", "error");
433
+ return;
434
+ }
435
+
436
+ // if(!recNo){
437
+ // showMessage("Invalid vehicle record number.", "error");
438
+ // return;
439
+ // }
440
+
441
+
442
+ const payload = {
443
+ site: props.site,
444
+ plateNumber: selectedPlateNumberObject.value?.plateNumber as string,
445
+ type: type === "whitelist" ? "blocklist" : "whitelist" as TVehicleType,
446
+ // recno: recNo
447
+ }
448
+
449
+
450
+ if (!vehicleId) {
451
+ showMessage("Invalid vehicle Id selected for updating type.", "error");
452
+ return;
453
+ }
454
+
455
+ try {
456
+ updatingType.value = true;
457
+ const res = await updateVehicle(vehicleId as string, payload);
458
+ dialog.updateVehicleType = false;
459
+ showMessage(res.message, "success");
460
+ await getVehiclesRefresh();
461
+ } catch (error: any) {
462
+ console.error("Error updating vehicle type:", error);
463
+ const errMessage = error?.response?._data?.message || "Failed to update vehicle type";
464
+ showMessage(errMessage, "error");
465
+ // message.value = error.response._data.message;
466
+ } finally {
467
+ updatingType.value = false;
468
+ }
469
+ }
470
+
471
+
398
472
  async function submitApprove() {
399
473
 
400
474
  const plateNumberId = selectedPlateNumberObject.value?._id;
@@ -404,14 +478,13 @@ async function submitApprove() {
404
478
  }
405
479
 
406
480
  try {
407
- approvingVehicle.value = true;
481
+ approvingVehicle.value = true;
408
482
  const res = await approveVehicle({ site: props.site, org: props.org, id: plateNumberId as string }
409
483
 
410
484
  );
411
485
  dialog.approveVehicle = false;
412
- selectedVehicleId.value = null
413
486
  showMessage(res.message, "success");
414
- getVehiclesRefresh();
487
+ await getVehiclesRefresh();
415
488
  } catch (error: any) {
416
489
  console.error("Error approving vehicle:", error);
417
490
  const errMessage = error?.response?._data?.message || "Failed to approve vehicle";