@neutron.co.id/operasional-interfaces 1.17.13-beta.1 → 1.17.13

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 (30) hide show
  1. package/build/@office/common/providers/api/apiUrl.d.ts +3 -0
  2. package/build/@office/common/providers/api/apiUrl.mjs +43 -0
  3. package/build/@office/common/providers/api/index.d.ts +1 -0
  4. package/build/@office/common/providers/api/index.mjs +1 -0
  5. package/build/@office/common/providers/index.d.ts +1 -0
  6. package/build/@office/common/providers/index.mjs +1 -0
  7. package/build/@office/models/personalia/attendance/AttendanceDelegate.vue +99 -14
  8. package/build/@office/models/personalia/attendance/AttendanceManager.vue +129 -15
  9. package/build/@office/models/personalia/attendance/AttendanceSingle/AttendanceSingle.vue +3 -1
  10. package/build/@office/models/personalia/attendance/AttendanceStaff.vue +184 -45
  11. package/build/@office/models/personalia/attendance/AttendanceSupervisor.vue +163 -36
  12. package/build/@office/models/personalia/leaveConflict/LeaveConflictCollection/LeaveConflictCollection.vue +1 -1
  13. package/build/@office/models/personalia/leaveConflict/LeaveConflictSingle/LeaveConflictSingle.vue +2 -2
  14. package/build/@office/models/personalia/leaveQuota/LeaveQuotaSingle/LeaveQuotaSingle.vue +27 -3
  15. package/build/@office/models/personalia/leaveStaff/LeaveStaffSingle/LeaveStaffSingle.vue +2 -2
  16. package/build/@office/models/personalia/shift/ShiftAdministrator.vue +1 -33
  17. package/build/@office/models/personalia/shift/ShiftSupervisor.vue +0 -1
  18. package/build/@office/models/personalia/shiftStaff/ShiftStaffCollectionBranch.vue +1 -1
  19. package/build/@office/models/personalia/shiftStaff/ShiftStaffCollectionStaff.vue +2 -1
  20. package/build/@office/models/personalia/shiftStaff/ShiftStaffWrapper/ShiftStaffDisplay.vue +4 -2
  21. package/build/@office/models/personalia/shiftStaff/ShiftStaffWrapper/ShiftStaffWrapper.vue +9 -13
  22. package/build/@package/@office/common/providers/api/apiUrl.d.ts +3 -0
  23. package/build/@package/@office/common/providers/api/index.d.ts +1 -0
  24. package/build/@package/@office/common/providers/index.d.ts +1 -0
  25. package/build/mock/index.cjs +1484 -1043
  26. package/build/mock/index.mjs +1484 -1043
  27. package/build/mock/style.css +16 -16
  28. package/build/module.json +1 -1
  29. package/build/nuxt.json +1 -1
  30. package/package.json +5 -5
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { GraphUtil, NeonSingle, useSingle } from '@neon.id/context'
2
+ import { GraphUtil, NeonSingle, useSingle, useAppStore } from '@neon.id/context'
3
3
  import { NeonCheck, NeonField, NeonForm } from '@neon.id/form'
4
4
  import {
5
5
  NeonAlert,
@@ -7,10 +7,11 @@ import {
7
7
  NeonDivider,
8
8
  useToastStore,
9
9
  NeonCopy,
10
+ NeonImage,
10
11
  } from '@neon.id/interfaces'
11
12
  import { OfficeRelation, OfficeTab, OfficeTabs } from '@neon.id/office'
12
13
  import { Query } from '@neon.id/query'
13
- import { computed, ref, watch } from 'vue'
14
+ import { computed, ref, watch, watchEffect } from 'vue'
14
15
  import { PromiseUtil } from '@neon.id/utils/promise'
15
16
  import {
16
17
  AttendanceModel,
@@ -18,9 +19,11 @@ import {
18
19
  type Schema,
19
20
  } from '@neutron.co.id/personalia-models'
20
21
  import { DateUtil } from '../../../common/utils/util.date'
21
- import { NeonTime, useOperasional } from '../../../common'
22
+ import { NeonTime, useOperasional, apiUrl } from '../../../common'
22
23
  import { AttendanceNoteTab } from './sections'
23
24
  import { useClientHandle } from '@urql/vue'
25
+ import { ofetch } from 'ofetch'
26
+ import { useAuthStore } from '@neon.id/identitas-interfaces'
24
27
 
25
28
  const {
26
29
  fields,
@@ -38,6 +41,14 @@ const {
38
41
  executeOne,
39
42
  } = useSingle<Schema.Attendance, TPersonaliaAttendanceModel>()
40
43
 
44
+ const appStore = useAppStore()
45
+
46
+ const officeAppUrl = computed(() => {
47
+ const url = apiUrl()
48
+ return url.action
49
+ // return 'http://127.0.0.1:7020'
50
+ })
51
+
41
52
  const key = ref(0)
42
53
  const responseState = ref()
43
54
  const toast = useToastStore()
@@ -156,6 +167,10 @@ function getNotified() {
156
167
  }
157
168
 
158
169
  async function generateAttendance() {
170
+ // console.log('show', showLeaveQuota.value)
171
+ // console.log('initial values', initialValues.value)
172
+ // console.log('values', values.value)
173
+ // console.log('leaveStffId', leaveStaffId.value)
159
174
  const responseGenerateAttendance = await client
160
175
  .mutation(GraphUtil.executeOne(AttendanceModel, {}), {
161
176
  action: 'generateAttendance',
@@ -164,7 +179,7 @@ async function generateAttendance() {
164
179
  // Attendance input.
165
180
  status: values.value.status,
166
181
  submitStaffId: values.value.submitStaffId,
167
- type: values.value.type,
182
+ typeId: values.value.type?.id,
168
183
  decideStaffId: values.value.decideStaffId,
169
184
  delegateStaffIds: values.value.delegateStaffIds,
170
185
  monitoringStaffIds: values.value.monitoringStaffIds,
@@ -173,6 +188,9 @@ async function generateAttendance() {
173
188
  startedAt: values.value.startedAt,
174
189
  endedAt: values.value.endedAt,
175
190
  delegateNotes: values.value.delegateNotes,
191
+ leaveQuota: quotaTaken.value,
192
+ isQuota: showLeaveQuota.value,
193
+ leaveStaffId: leaveStaffId.value,
176
194
  },
177
195
  })
178
196
  .toPromise()
@@ -180,6 +198,94 @@ async function generateAttendance() {
180
198
  const wrapper = responseGenerateAttendance.data?.executeAttendance
181
199
  responseState.value = wrapper?.info?.state
182
200
  }
201
+ const type = ref('')
202
+ const showLeaveQuota = ref(true)
203
+ const authStore = useAuthStore()
204
+ const createdBy = authStore.userId
205
+ const quota = ref(0)
206
+ const maxDuration = ref(0)
207
+ const quotaTaken = ref(0)
208
+ const leaveStaffId = ref('')
209
+
210
+ function checkDurationLeave() {
211
+ if (!values.value.startedAt || !values.value.endedAt) {
212
+ return true
213
+ }
214
+
215
+ const startedAt = new Date(values.value.startedAt)
216
+ const endedAt = new Date(values.value.endedAt)
217
+
218
+ const durationMilliseconds = endedAt.getTime() - startedAt.getTime()
219
+
220
+ const days = Math.floor(durationMilliseconds / (1000 * 60 * 60 * 24)) + 1
221
+ quotaTaken.value = days
222
+
223
+ if (days > maxDuration.value) return false
224
+
225
+ return true
226
+ }
227
+
228
+ watch(
229
+ () => values.value,
230
+ async (newType) => {
231
+ if (values.value.attendanceTypeId) {
232
+ checkDurationLeave()
233
+ const response = await ofetch(`${officeAppUrl.value}/getAttendanceType`, {
234
+ method: 'POST',
235
+ headers: {
236
+ 'X-Neon-Key': 'CH7JLKT6MW',
237
+ },
238
+ body: {
239
+ id: values.value.attendanceTypeId,
240
+ },
241
+ })
242
+ type.value = response.data[0].code
243
+ showLeaveQuota.value = response.data[0].showLeaveQuota
244
+ // quota.value = response.data[0].leaveQuota
245
+ maxDuration.value = response.data[0].maxDurationDays
246
+ }
247
+ },
248
+ { immediate: true },
249
+ )
250
+
251
+ const isLeaveStaff = ref(false)
252
+
253
+ watch(
254
+ () => [values.value.startedAt, values.value.endedAt],
255
+ async (newType) => {
256
+ if (values.value.startedAt && values.value.endedAt) {
257
+ const leaveStaff = await ofetch(`${officeAppUrl.value}/getLeaveQuota`, {
258
+ method: 'POST',
259
+ headers: {
260
+ 'X-Neon-Key': 'CH7JLKT6MW',
261
+ },
262
+ body: {
263
+ id: values.value.attendanceTypeId,
264
+ staffId: staffId,
265
+ startedAt: values.value.startedAt,
266
+ endedAt: values.value.endedAt,
267
+ },
268
+ })
269
+
270
+ if (leaveStaff.code !== 200) {
271
+ quota.value = 0
272
+ isLeaveStaff.value = false
273
+ return
274
+ }
275
+ // console.log('leaveStaff', leaveStaff)
276
+
277
+ quota.value = leaveStaff.data.quota
278
+ maxDuration.value = leaveStaff.data.quota
279
+ leaveStaffId.value = leaveStaff.data.leaveStaff.id
280
+
281
+ if (leaveStaff?.code === 200 && leaveStaff?.data?.quota > 0) {
282
+ isLeaveStaff.value = true
283
+ } else {
284
+ isLeaveStaff.value = false
285
+ }
286
+ }
287
+ },
288
+ )
183
289
 
184
290
  async function generate() {
185
291
  await generateAttendance()
@@ -187,6 +293,24 @@ async function generate() {
187
293
  await syncOne()
188
294
  }
189
295
 
296
+ const showDurationAlert = ref(false)
297
+ async function saveData() {
298
+ const result = await checkDurationLeave()
299
+ // console.log('showLeaveQuota', showLeaveQuota.value)
300
+
301
+ if (
302
+ (result === true && isLeaveStaff.value === true) ||
303
+ showLeaveQuota.value === false
304
+ ) {
305
+ showDurationAlert.value = false
306
+ console.log('save')
307
+ await saveOne()
308
+ } else {
309
+ showDurationAlert.value = true
310
+ console.log('error')
311
+ }
312
+ }
313
+
190
314
  //copy link for catatan
191
315
  const copy = ref({
192
316
  copyDelegate: `${window.location.origin}/penugasan/staff-attendances/?peek=neu:personalia:attendance:${id.value}:single-staff-view:s`,
@@ -204,8 +328,15 @@ const copy = ref({
204
328
  :is-changed="isChanged"
205
329
  use-unsaved
206
330
  @cancel="discardChanges"
207
- @submit="saveOne"
331
+ @submit="saveData"
208
332
  >
333
+ <NeonStat
334
+ v-if="showLeaveQuota"
335
+ class="w-36 mb-2"
336
+ label="Cuti Pribadi"
337
+ icon="person-to-door"
338
+ >{{ quota }} hari</NeonStat
339
+ >
209
340
  <NeonAlert
210
341
  v-if="conflictAtt == true"
211
342
  icon="circle-info"
@@ -213,6 +344,13 @@ const copy = ref({
213
344
  description="Untuk hari ini kamu sudah ada absensi yang diajukan, silahkan cari absensi yang telah diajukan dan ajukan kembali untuk pergantiannya."
214
345
  color="#F7CF6D"
215
346
  />
347
+ <NeonAlert
348
+ v-if="showDurationAlert == true"
349
+ icon="circle-info"
350
+ label="Durasi Melebihi Batas!."
351
+ description="Durasi cuti yang diajukan melebihi batas maksimum yang telah ditentukan. Mohon sesuaikan kembali permohonan cuti sesuai dengan ketentuan yang berlaku"
352
+ color="#F7CF6D"
353
+ />
216
354
  <div v-if="!isNew && conflictAtt == false" class="flex flex-wrap">
217
355
  <div class="mt-2">
218
356
  <NeonField>
@@ -275,7 +413,6 @@ const copy = ref({
275
413
  "
276
414
  @update:model-value="onStartedAtUpdate"
277
415
  />
278
-
279
416
  <OfficeRelation
280
417
  v-model="values"
281
418
  :field="fields.type"
@@ -284,6 +421,13 @@ const copy = ref({
284
421
  values.status == 'approved' ||
285
422
  values.status == 'rejected'
286
423
  "
424
+ :query="
425
+ Query.define({
426
+ filter: {
427
+ showAttendanceType: true,
428
+ },
429
+ })
430
+ "
287
431
  />
288
432
 
289
433
  <OfficeRelation
@@ -301,10 +445,10 @@ const copy = ref({
301
445
  <NeonFields class="flex-1"> -->
302
446
  <OfficeRelation
303
447
  v-if="
304
- values.type?.code == 'leave' ||
305
- values.type?.code == 'dayOff' ||
306
- values.type?.code == 'sick' ||
307
- values.type?.code == 'permission'
448
+ type == 'cuti' ||
449
+ type == 'dayOff' ||
450
+ type == 'sakit' ||
451
+ type == 'izin'
308
452
  "
309
453
  v-model="values"
310
454
  :field="fields.delegateStaffs"
@@ -314,15 +458,16 @@ const copy = ref({
314
458
  values.status == 'rejected'
315
459
  "
316
460
  />
461
+ <NeonField v-model="values.image" v-bind="fields.image" />
317
462
  <!-- </NeonFields>
318
463
  </div> -->
319
464
  <!-- <div class="ml-2 flex items-end pb-1">
320
465
  <NeonCopy
321
466
  v-if="
322
- values.type?.code == 'leave' ||
323
- values.type?.code == 'dayOff' ||
324
- values.type?.code == 'sick' ||
325
- values.type?.code == 'permission' ||
467
+ values.type == 'leave' ||
468
+ values.type == 'dayOff' ||
469
+ values.type == 'sick' ||
470
+ values.type == 'permission' ||
326
471
  values.isNotes == true
327
472
  "
328
473
  :size="'sm'"
@@ -332,10 +477,10 @@ const copy = ref({
332
477
  </div> -->
333
478
  <!-- <NeonField
334
479
  v-if="
335
- values.type?.code == 'leave' ||
336
- values.type?.code == 'dayOff' ||
337
- values.type?.code == 'sick' ||
338
- values.type?.code == 'permission'
480
+ values.type == 'leave' ||
481
+ values.type == 'dayOff' ||
482
+ values.type == 'sick' ||
483
+ values.type == 'permission'
339
484
  "
340
485
  v-model="values.isNotes"
341
486
  v-bind="fields.isNotes"
@@ -348,10 +493,10 @@ const copy = ref({
348
493
  <!-- <template #input>
349
494
  <NeonCheck
350
495
  v-if="
351
- values.type?.code == 'leave' ||
352
- values.type?.code == 'dayOff' ||
353
- values.type?.code == 'sick' ||
354
- values.type?.code == 'permission'
496
+ values.type == 'leave' ||
497
+ values.type == 'dayOff' ||
498
+ values.type == 'sick' ||
499
+ values.type == 'permission'
355
500
  "
356
501
  v-model="values.isNotes"
357
502
  label="Catatan"
@@ -360,7 +505,6 @@ const copy = ref({
360
505
  />
361
506
  </template> -->
362
507
  <!-- </NeonField> -->
363
-
364
508
  <NeonField
365
509
  v-if="isNew || isReady"
366
510
  v-model="values.notes"
@@ -368,35 +512,33 @@ const copy = ref({
368
512
  />
369
513
  <NeonField
370
514
  v-if="
371
- values.type?.code == 'leave' ||
372
- values.type?.code == 'dayOff' ||
373
- values.type?.code == 'sick' ||
374
- values.type?.code == 'permission'
515
+ type == 'cuti' ||
516
+ type == 'dayOff' ||
517
+ type == 'sakit' ||
518
+ type == 'izin'
375
519
  "
376
520
  v-model="values.delegateNotes"
377
521
  v-bind="fields.delegateNotes"
378
522
  />
379
523
 
380
- <NeonDivider v-if="values.type" is-dashed label="Keterangan" />
524
+ <NeonDivider
525
+ v-if="values.attendanceTypeId"
526
+ is-dashed
527
+ label="Keterangan"
528
+ />
381
529
 
382
530
  <NeonField
383
531
  v-if="
384
- values.type?.code == 'dayOff' ||
385
- values.type?.code == 'sick' ||
386
- values.type?.code == 'permission' ||
387
- values.type?.code == 'leave'
532
+ type == 'dayOff' ||
533
+ type == 'sakit' ||
534
+ type == 'izin' ||
535
+ type == 'cuti'
388
536
  "
389
537
  v-model="values.submittedAt"
390
538
  v-bind="fields.submittedAt"
391
539
  is-disabled
392
540
  />
393
- <div
394
- v-if="
395
- values.type?.code == 'sick' ||
396
- values.type?.code == 'leave' ||
397
- values.type?.code == 'permission'
398
- "
399
- >
541
+ <div v-if="type == 'sakit' || type == 'cuti' || type == 'izin'">
400
542
  <NeonDivider
401
543
  is-dashed
402
544
  label="Tanggal ini digunakan hanya untuk Generate Absensi"
@@ -435,7 +577,7 @@ const copy = ref({
435
577
 
436
578
  <!-- EARLY GO HOME -->
437
579
  <div
438
- v-if="values.type?.code == 'homeEarly'"
580
+ v-if="type == 'pulangLebihAwal'"
439
581
  class="grid gap-2 sm:grid-cols-2"
440
582
  >
441
583
  <NeonField
@@ -493,7 +635,7 @@ const copy = ref({
493
635
 
494
636
  <!-- COME TOO LATE -->
495
637
  <div
496
- v-if="values.type?.code == 'comeLate'"
638
+ v-if="type == 'datangTerlambat'"
497
639
  class="grid gap-2 sm:grid-cols-2"
498
640
  >
499
641
  <NeonField
@@ -550,10 +692,7 @@ const copy = ref({
550
692
  </div>
551
693
 
552
694
  <!-- TIMEOUT -->
553
- <div
554
- v-if="values.type?.code == 'timeout'"
555
- class="grid gap-2 sm:grid-cols-2"
556
- >
695
+ <div v-if="type == 'timeout'" class="grid gap-2 sm:grid-cols-2">
557
696
  <NeonField
558
697
  v-model="values.startedAt"
559
698
  v-bind="{