@neutron.co.id/operasional-interfaces 1.14.1 → 1.14.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.
@@ -1,13 +1,25 @@
1
1
  import { defineStore } from "pinia";
2
- import { ref } from "vue";
2
+ import { ref, computed } from "vue";
3
3
  export const useOperasionalStore = defineStore("neu:operasional", () => {
4
4
  const isLoading = ref(false);
5
5
  const staff = ref(null);
6
6
  const accesses = ref([]);
7
+ const supervisedStaffIds = computed(() => {
8
+ if (Array.isArray(accesses.value)) {
9
+ return accesses.value.reduce(
10
+ (ids, access) => {
11
+ return ids.concat(access.supervisedStaffIds || []);
12
+ },
13
+ []
14
+ );
15
+ }
16
+ return [];
17
+ });
7
18
  return {
8
19
  isLoading,
9
20
  staff,
10
21
  accesses,
22
+ supervisedStaffIds,
11
23
  setStaff,
12
24
  getStaff,
13
25
  getAllStoreValue
@@ -18,9 +30,14 @@ export const useOperasionalStore = defineStore("neu:operasional", () => {
18
30
  function getStaff() {
19
31
  return staff.value;
20
32
  }
33
+ function getAccesses() {
34
+ return accesses.value;
35
+ }
21
36
  function getAllStoreValue() {
22
37
  return {
23
- staff: getStaff()
38
+ staff: getStaff(),
39
+ supervisedStaffIds: getAccesses(),
40
+ accesses: getAccesses()
24
41
  };
25
42
  }
26
43
  });
@@ -38,7 +38,7 @@ export const config = OfficeInterfaces.define({
38
38
  // Progress Access
39
39
  "ProgressAccessCollection",
40
40
  "ProgressAccessSingle",
41
- "ProgressSupervisor",
41
+ "ProgressAccessSupervisor",
42
42
  // Responsibility
43
43
  "ResponsibilityCollection",
44
44
  "ResponsibilitySingle",
@@ -43,21 +43,13 @@ function transformItem(item: any) {
43
43
  return {
44
44
  ...item,
45
45
  eventColor:
46
- item.type === 'dayOff'
47
- ? '#FAE3DF'
48
- : item.type === 'sick'
49
- ? '#D7E4EE'
50
- : item.type === 'permission'
51
- ? '#FAEDCC'
52
- : item.type === 'leave'
53
- ? '#DEECDC'
54
- : item.type === 'homeEarly'
55
- ? '#EEF2FF'
56
- : item.type === 'comeLate'
57
- ? '#F1F5FF'
58
- : item.type === 'homeEarly'
59
- ? '#FDF2F8'
60
- : 'base',
46
+ item.status === 'rejected'
47
+ ? 'danger'
48
+ : item.status === 'notApproved'
49
+ ? 'warning'
50
+ : item.status === 'approved'
51
+ ? 'success'
52
+ : 'base',
61
53
  }
62
54
  }
63
55
 
@@ -1,17 +1,24 @@
1
1
  <script setup lang="ts">
2
- import { NeonSingle, useSingle } from '@neon.id/context'
2
+ import { GraphUtil, NeonSingle, useSingle } from '@neon.id/context'
3
3
  import { NeonField, NeonForm } from '@neon.id/form'
4
- import { NeonAlert, NeonButton, NeonDivider } from '@neon.id/interfaces'
4
+ import {
5
+ NeonAlert,
6
+ NeonButton,
7
+ NeonDivider,
8
+ useToastStore,
9
+ } from '@neon.id/interfaces'
5
10
  import { OfficeRelation, OfficeTab, OfficeTabs } from '@neon.id/office'
6
11
  import { Query } from '@neon.id/query'
7
12
  import { computed, ref, watch } from 'vue'
8
13
  import { PromiseUtil } from '@neon.id/utils/promise'
9
- import type {
10
- TPersonaliaAttendanceModel,
11
- Schema,
14
+ import {
15
+ AttendanceModel,
16
+ type TPersonaliaAttendanceModel,
17
+ type Schema,
12
18
  } from '@neutron.co.id/personalia-models'
13
19
  import { DateUtil } from '../../../common/utils/util.date'
14
20
  import { NeonTime, useOperasional } from '../../../common'
21
+ import { useClientHandle } from '@urql/vue'
15
22
 
16
23
  const {
17
24
  fields,
@@ -30,6 +37,9 @@ const {
30
37
  } = useSingle<Schema.Attendance, TPersonaliaAttendanceModel>()
31
38
 
32
39
  const key = ref(0)
40
+ const responseState = ref()
41
+ const toast = useToastStore()
42
+
33
43
  const diff = computed(() => {
34
44
  return DateUtil.day(values.value.endedAt).diff(values.value.startedAt)
35
45
  })
@@ -129,6 +139,50 @@ const staffOptions = computed(() => {
129
139
  ],
130
140
  }
131
141
  })
142
+
143
+ //Generate Attendance
144
+ const { client } = useClientHandle()
145
+
146
+ function getNotified() {
147
+ if (responseState.value === 'attendanceGenerated') {
148
+ toast.push({
149
+ id: 'generate:attendance',
150
+ content: 'Successfully generated attendance.',
151
+ color: 'success',
152
+ })
153
+ }
154
+ }
155
+
156
+ async function generateAttendance() {
157
+ const responseGenerateAttendance = await client
158
+ .mutation(GraphUtil.executeOne(AttendanceModel, {}), {
159
+ action: 'generateAttendance',
160
+ input: {
161
+ attendanceId: values.value.id,
162
+ // Attendance input.
163
+ status: values.value.status,
164
+ submitStaffId: values.value.submitStaffId,
165
+ type: values.value.type,
166
+ decideStaffId: values.value.decideStaffId,
167
+ notes: values.value.notes,
168
+ submittedAt: values.value.submittedAt,
169
+ startedAt: values.value.startedAt,
170
+ endedAt: values.value.endedAt,
171
+ },
172
+ })
173
+ .toPromise()
174
+
175
+ const wrapper = responseGenerateAttendance.data?.executeAttendance
176
+ responseState.value = wrapper?.info?.state
177
+ }
178
+
179
+ console.log('decideStaffId', values.value.decideStaffId)
180
+
181
+ async function generate() {
182
+ await generateAttendance()
183
+ await getNotified()
184
+ await syncOne()
185
+ }
132
186
  </script>
133
187
 
134
188
  <template>
@@ -151,7 +205,6 @@ const staffOptions = computed(() => {
151
205
  description="Untuk hari ini kamu sudah ada absensi yang diajukan, silahkan cari absensi yang telah diajukan dan ajukan kembali untuk pergantiannya."
152
206
  color="#F7CF6D"
153
207
  />
154
-
155
208
  <div v-if="!isNew && conflictAtt == false" class="flex flex-wrap">
156
209
  <div class="mt-2">
157
210
  <NeonField>
@@ -189,7 +242,6 @@ const staffOptions = computed(() => {
189
242
  </NeonField>
190
243
  </div>
191
244
  </div>
192
-
193
245
  <OfficeRelation
194
246
  v-model="values"
195
247
  :field="fields.submitStaff"
@@ -215,6 +267,40 @@ const staffOptions = computed(() => {
215
267
  "
216
268
  @update:model-value="onStartedAtUpdate"
217
269
  />
270
+ <NeonDivider
271
+ is-dashed
272
+ label="Tanggal ini digunakan hanya untuk Generate Absensi"
273
+ class="divider"
274
+ />
275
+ <NeonFields md="grid-cols-3">
276
+ <NeonField
277
+ v-model="values.startedAt"
278
+ v-bind="fields.startedAt"
279
+ :is-disabled="
280
+ values.status == 'approved' || values.isGenerate === true
281
+ "
282
+ />
283
+ <NeonField
284
+ v-model="values.endedAt"
285
+ v-bind="fields.endedAt"
286
+ :is-disabled="
287
+ values.status == 'approved' || values.isGenerate === true
288
+ "
289
+ />
290
+ <NeonButton
291
+ icon-left="bolt"
292
+ label="Generate"
293
+ color="success"
294
+ class="mt-12"
295
+ size="xs"
296
+ :is-loading="isLoading"
297
+ :is-disabled="
298
+ values.status !== 'approved' || values.isGenerate === true
299
+ "
300
+ is-rounded
301
+ @click="generate"
302
+ />
303
+ </NeonFields>
218
304
 
219
305
  <NeonField
220
306
  v-model="values.type"
@@ -1,16 +1,18 @@
1
1
  <script setup lang="ts">
2
- import { NeonSingle, useSingle } from '@neon.id/context'
2
+ import { GraphUtil, NeonSingle, useSingle } from '@neon.id/context'
3
3
  import { NeonField, NeonForm } from '@neon.id/form'
4
- import { NeonButton, NeonDivider } from '@neon.id/interfaces'
4
+ import { NeonButton, NeonDivider, useToastStore } from '@neon.id/interfaces'
5
5
  import { OfficeRelation, OfficeTab, OfficeTabs } from '@neon.id/office'
6
6
  import { computed, ref, watch } from 'vue'
7
7
  import { PromiseUtil } from '@neon.id/utils/promise'
8
- import type {
9
- TPersonaliaAttendanceModel,
10
- Schema,
8
+ import {
9
+ AttendanceModel,
10
+ type TPersonaliaAttendanceModel,
11
+ type Schema,
11
12
  } from '@neutron.co.id/personalia-models'
12
13
  import { DateUtil } from '../../../common/utils'
13
14
  import { NeonTime, useOperasional } from '../../../common'
15
+ import { useClientHandle } from '@urql/vue'
14
16
 
15
17
  const {
16
18
  fields,
@@ -75,7 +77,8 @@ function onStartedAtUpdate(date: any) {
75
77
  }
76
78
 
77
79
  // OTHER
78
-
80
+ const responseState = ref()
81
+ const toast = useToastStore()
79
82
  const { staff } = useOperasional()
80
83
  const staffId = staff.value?.id || ''
81
84
 
@@ -108,6 +111,48 @@ const rejectedAbsensi = async () => {
108
111
  await executeOne('rejectedAttendance', { attendanceId: id.value })
109
112
  await syncOne()
110
113
  }
114
+
115
+ //Generate Attendance
116
+ const { client } = useClientHandle()
117
+
118
+ function getNotified() {
119
+ if (responseState.value === 'attendanceGenerated') {
120
+ toast.push({
121
+ id: 'generate:attendance',
122
+ content: 'Successfully generated attendance.',
123
+ color: 'success',
124
+ })
125
+ }
126
+ }
127
+
128
+ async function generateAttendance() {
129
+ const responseGenerateAttendance = await client
130
+ .mutation(GraphUtil.executeOne(AttendanceModel, {}), {
131
+ action: 'generateAttendance',
132
+ input: {
133
+ attendanceId: values.value.id,
134
+ // Attendance input.
135
+ status: values.value.status,
136
+ submitStaffId: values.value.submitStaffId,
137
+ type: values.value.type,
138
+ decideStaffId: values.value.decideStaffId,
139
+ notes: values.value.notes,
140
+ submittedAt: values.value.submittedAt,
141
+ startedAt: values.value.startedAt,
142
+ endedAt: values.value.endedAt,
143
+ },
144
+ })
145
+ .toPromise()
146
+
147
+ const wrapper = responseGenerateAttendance.data?.executeAttendance
148
+ responseState.value = wrapper?.info?.state
149
+ }
150
+
151
+ async function generate() {
152
+ await generateAttendance()
153
+ await getNotified()
154
+ await syncOne()
155
+ }
111
156
  </script>
112
157
 
113
158
  <template>
@@ -196,6 +241,35 @@ const rejectedAbsensi = async () => {
196
241
  "
197
242
  @update:model-value="onStartedAtUpdate"
198
243
  />
244
+ <NeonDivider
245
+ label="Tanggal ini digunakan hanya untuk Generate Absensi"
246
+ class="divider"
247
+ />
248
+ <NeonFields md="grid-cols-3">
249
+ <NeonField
250
+ v-model="values.startedAt"
251
+ v-bind="fields.startedAt"
252
+ :is-disabled="values.isGenerate === true"
253
+ />
254
+ <NeonField
255
+ v-model="values.endedAt"
256
+ v-bind="fields.endedAt"
257
+ :is-disabled="values.isGenerate === true"
258
+ />
259
+ <NeonButton
260
+ icon-left="bolt"
261
+ label="Generate"
262
+ color="success"
263
+ class="mt-12"
264
+ size="xs"
265
+ :is-loading="isLoading"
266
+ :is-disabled="
267
+ values.status !== 'approved' || values.isGenerate === true
268
+ "
269
+ is-rounded
270
+ @click="generate"
271
+ />
272
+ </NeonFields>
199
273
 
200
274
  <NeonField
201
275
  v-model="values.type"
@@ -32,16 +32,8 @@ const {
32
32
  @cancel="discardChanges"
33
33
  @submit="saveOne"
34
34
  >
35
- <OfficeRelation
36
- v-model="values"
37
- :field="fields.superviseStaff"
38
- is-disabled
39
- />
40
- <OfficeRelation
41
- v-model="values"
42
- :field="fields.supervisedStaffs"
43
- is-disabled
44
- />
35
+ <OfficeRelation v-model="values" :field="fields.superviseStaff" />
36
+ <OfficeRelation v-model="values" :field="fields.supervisedStaffs" />
45
37
  </NeonForm>
46
38
  </OfficeTab>
47
39
  </OfficeTabs>