@iservice365/layer-common 1.2.0 → 1.3.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.
@@ -7,6 +7,8 @@
7
7
  :counter="maxlength"
8
8
  @input="onInput"
9
9
  outlined
10
+ :disabled="disabled"
11
+ :readonly="readonly"
10
12
  clearable
11
13
  />
12
14
  </template>
@@ -25,6 +27,12 @@ const props = defineProps({
25
27
  maxlength: {
26
28
  type: [Number, String],
27
29
  default: false
30
+ },
31
+ disabled: {
32
+ type: Boolean,
33
+ },
34
+ readonly: {
35
+ type: Boolean,
28
36
  }
29
37
  })
30
38
 
@@ -3,7 +3,7 @@
3
3
  <v-toolbar>
4
4
  <v-row no-gutters class="fill-height px-6" align="center">
5
5
  <span class="font-weight-bold text-h5 text-capitalize">
6
- {{ prop.mode }} {{ prop.type === 'visitor' ? 'Guest' : prop.type }}
6
+ {{ prop.mode }} {{ prop.type === 'visitor' ? 'Guest' : prop.type }}
7
7
  </span>
8
8
  </v-row>
9
9
  </v-toolbar>
@@ -34,15 +34,14 @@
34
34
  <v-row>
35
35
  <v-col cols="12">
36
36
  <InputLabel class="text-capitalize" title="NRIC/Passport/ID No." />
37
- <InputNRICNumber v-model.trim="form.nric" density="comfortable" />
37
+ <InputNRICNumber v-model.trim="form.nric" density="comfortable" />
38
38
  </v-col>
39
39
  </v-row>
40
40
  </v-col>
41
41
 
42
42
  <v-col cols="12">
43
43
  <InputLabel class="text-capitalize" title="Phone Number" required />
44
- <InputPhoneNumberV2 v-model="form.contact"
45
- density="comfortable" :rules="[requiredRule]" />
44
+ <InputPhoneNumberV2 v-model="form.contact" density="comfortable" :rules="[requiredRule]" />
46
45
  </v-col>
47
46
 
48
47
  <v-col cols="12">
@@ -65,19 +64,18 @@
65
64
 
66
65
  <v-col cols="12">
67
66
  <InputLabel class="text-capitalize" title="Unit" required />
68
- <v-select v-model="form.unit" :items="unitsArray" @update:model-value="handleUpdateUnit" density="comfortable" :disabled="!form.level"
69
- :loading="unitsStatus === 'pending'" :rules="[requiredRule]" />
67
+ <v-select v-model="form.unit" :items="unitsArray" @update:model-value="handleUpdateUnit"
68
+ density="comfortable" :disabled="!form.level" :loading="unitsStatus === 'pending'"
69
+ :rules="[requiredRule]" />
70
70
  </v-col>
71
71
 
72
72
  <v-col cols="12">
73
73
  <InputLabel class="text-capitalize" title="Start Date" required />
74
- <InputDateTimePicker v-model:utc="form.start" ref="startDateRef"
75
- :rules="[validStartDateRule]" />
74
+ <InputDateTimePicker v-model:utc="form.start" ref="startDateRef" name="start_date" :rules="[validStartDateRule]" />
76
75
  </v-col>
77
76
  <v-col cols="12">
78
77
  <InputLabel class="text-capitalize" title="End Date" required />
79
- <InputDateTimePicker v-model:utc="form.end" ref="endDateRef"
80
- :rules="[validExpiryDateRule]" />
78
+ <InputDateTimePicker v-model:utc="form.end" ref="endDateRef" name="end_date" :rules="[validExpiryDateRule]" />
81
79
  </v-col>
82
80
 
83
81
  <v-col cols="12">
@@ -144,12 +142,20 @@ const prop = defineProps({
144
142
  type: {
145
143
  type: String as PropType<TPeopleType>,
146
144
  required: true
145
+ },
146
+ activeId: {
147
+ type: String as PropType<string | null>, // id of person you are trying to update
148
+ default: null
149
+ },
150
+ people: {
151
+ type: Object as PropType<TPeople>,
152
+ required: false
147
153
  }
148
154
  });
149
155
 
150
156
  const { requiredRule, formatDateISO8601 } = useUtils();
151
157
  const { getSiteById, getSiteLevels, getSiteUnits } = useSiteSettings();
152
- const { create } = usePeople();
158
+ const { create, updateById } = usePeople();
153
159
 
154
160
  const emit = defineEmits(['back', 'select', 'done', 'done:more', 'error', 'close']);
155
161
 
@@ -164,7 +170,7 @@ const form = reactive<Partial<TPeoplePayload>>({
164
170
  unit: "",
165
171
  unitName: "",
166
172
  remarks: "",
167
- start: dateToday() || "",
173
+ start: "",
168
174
  end: "",
169
175
  type: prop.type
170
176
  })
@@ -199,21 +205,21 @@ const contractorTypes = [
199
205
 
200
206
  const { data: siteData, refresh: refreshSiteData, status: blockStatus } = useLazyAsyncData(
201
207
  `fetch-site-data-${prop.site}`,
202
- () => getSiteById(prop.site));
208
+ () => getSiteById(prop.site),);
203
209
 
204
210
  const { data: levelsData, refresh: refreshLevelsData, status: levelsStatus } = useLazyAsyncData(
205
211
  `fetch-levels-data-${prop.site}-${form.block}`,
206
212
  async () => {
207
213
  if (!form.block) return Promise.resolve(null);
208
214
  return await getSiteLevels(prop.site, { block: Number(form.block) })
209
- });
215
+ }, { watch: [() => form.block],});
210
216
 
211
217
  const { data: unitsData, refresh: refreshUnitsData, status: unitsStatus } = useLazyAsyncData(
212
218
  `fetch-units-data-${prop.site}-${form.level}`,
213
219
  async () => {
214
220
  if (!form.level) return Promise.resolve(null);
215
221
  return await getSiteUnits(prop.site, Number(form.block), form.level)
216
- });
222
+ }, { watch: [()=> form.level]});
217
223
 
218
224
  watch(
219
225
  siteData,
@@ -267,12 +273,10 @@ watch(
267
273
  function handleChangeBlock(value: any) {
268
274
  form.level = '';
269
275
  form.unit = '';
270
- refreshLevelsData();
271
276
  }
272
277
 
273
278
  function handleChangeLevel(value: any) {
274
279
  form.unit = '';
275
- refreshUnitsData();
276
280
  }
277
281
 
278
282
  function handleUpdateUnit(value: any) {
@@ -280,7 +284,7 @@ function handleUpdateUnit(value: any) {
280
284
  form.unitName = selectedUnit?.title || ''
281
285
  }
282
286
 
283
- function dateToday(){
287
+ function dateToday() {
284
288
  const today = new Date()
285
289
  return today.toISOString()
286
290
  }
@@ -362,33 +366,44 @@ async function submit() {
362
366
  errorMessage.value = '';
363
367
  processing.value = true;
364
368
 
365
- let payload: Partial<TPeoplePayload> = {
366
- org: prop.org,
367
- site: prop.site
368
- }
369
+ let payload: Partial<TPeoplePayload> = {}
369
370
 
370
371
  if (prop.mode === 'add') {
371
372
  payload = {
372
373
  ...payload,
374
+ org: prop.org,
375
+ site: prop.site,
373
376
  ...form,
374
377
  }
375
378
 
376
379
  } else if (prop.mode === 'edit') {
380
+ const { type, ...rest } = form
381
+ payload = {
382
+ ...payload,
383
+ ...rest
384
+ }
377
385
 
378
386
  }
379
387
  try {
388
+ if (prop.mode === 'add') {
389
+ await create(payload)
390
+ } else if (prop.mode === 'edit'){
391
+ const userId = prop.activeId
392
+ if(!userId) {
393
+ throw new Error('User Id prop is not defined')
394
+ }
380
395
 
381
- const res = await create(payload)
382
- if (res) {
383
- if (createMore.value) {
384
- resetForm()
385
- step.value = 1;
386
- errorMessage.value = ""
387
- emit("done:more")
388
- createMore.value = false
389
- } else emit("done")
396
+ await updateById(userId, payload)
390
397
  }
391
398
 
399
+ if (createMore.value) {
400
+ resetForm()
401
+ step.value = 1;
402
+ errorMessage.value = ""
403
+ emit("done:more")
404
+ createMore.value = false
405
+ } else emit("done")
406
+
392
407
  } catch (error: any) {
393
408
  const err = error?.data?.message
394
409
  errorMessage.value = err || `Failed to ${prop.mode === 'add' ? 'add' : 'update'} ${prop.type}. Please try again.`;
@@ -406,9 +421,27 @@ watch(() => [form.end, form.start], () => {
406
421
  (startDateRef.value as any)?.validate();
407
422
  });
408
423
 
424
+ async function mountExistingData() {
425
+ setTimeout(() => {
426
+ const people = prop.people
427
+ if (!people) return
428
+
429
+ (Object.keys(form) as (keyof typeof form)[]).forEach((key) => {
430
+ if (key in people) {
431
+ form[key] = people[key as keyof TPeople]
432
+ }
433
+ })
434
+ }, 100)
435
+ }
436
+
409
437
  onMounted(() => {
410
438
  step.value = 1;
411
439
  createMore.value = false;
440
+ if(prop.mode === 'edit'){
441
+ mountExistingData()
442
+ } else {
443
+ form.start = dateToday()
444
+ }
412
445
  })
413
446
 
414
447
  </script>
@@ -416,5 +449,4 @@ onMounted(() => {
416
449
  .button-outline-class {
417
450
  border: 1px solid rgba(var(--v-theme-primary));
418
451
  }
419
-
420
452
  </style>
@@ -43,7 +43,7 @@
43
43
  <!-- Data Table -->
44
44
  <v-data-table :headers="headers" :items="items" :item-value="itemValue" :items-per-page="itemsPerPage"
45
45
  fixed-header hide-default-footer :hide-default-header="!showHeader"
46
- @click:row="(_: any, data: any) => emits('row-click', data)" style="max-height: calc(100vh - (200px))">
46
+ @click:row="(_: any, data: any) => emits('row-click', data)" :style="`max-height: calc(100vh - (${offset}px))`">
47
47
  <template v-for="(_, slotName) in $slots" #[slotName]="slotProps">
48
48
  <slot :name="slotName" v-bind="slotProps" />
49
49
  </template>
@@ -103,6 +103,10 @@ const props = defineProps({
103
103
  extensionHeight: {
104
104
  type: Number,
105
105
  default: 50
106
+ },
107
+ offset: {
108
+ type: Number,
109
+ default: 200
106
110
  }
107
111
  });
108
112