Unverified Commit 8ab028b4 authored by Ariela Ramdania's avatar Ariela Ramdania Committed by GitHub
Browse files

Merge branch 'main' into ariela

1 merge request!62update presensi dan setting
Showing with 208 additions and 127 deletions
+208 -127
......@@ -62,7 +62,7 @@
<div class="fw-bolder">Daily Report</div>
</router-link>
</li>
<li class="menu-item" :class="{ active: $route.path === '/ajuan/overtime' }">
<li v-if="isAuthorized('pengajuanLembur')" class="menu-item" :class="{ active: $route.path === '/ajuan/overtime' }">
<router-link to="/ajuan/overtime" class="menu-link">
<i class="menu-icon tf-icons bx bxs-hourglass"></i>
<div>Lembur</div>
......@@ -153,12 +153,18 @@ export default defineComponent({
dataProject: ['HRD', 'CTO'],
dataKaryawan: ['HRD', 'CTO'],
dataKeyResult: ['HRD'],
presensi: [ 'HRD', 'PM','Frontend','Backend', 'UI/UX'],
dailyReport: [ 'HRD', 'Frontend', 'Backend', 'UI/UX'],
pengajuanLembur: ['HRD', 'UIUX', 'Frontend', 'PM'],
presensi: ['UIUX', 'HRD', 'PM','Frontend'],
dailyReport: ['UIUX', 'HRD', 'Frontend'],
readpresensi: ['HRD', 'PM', 'CTO'],
readdailyReport: ['HRD', 'PM', 'CTO'],
lembur: ['HRD', 'CTO','Frontend'],
cuti: ['HRD', 'CTO', 'Frontend'],
lembur: ['HRD', 'CTO','PM'],
cuti: ['HRD', 'CTO', 'PM'],
kelolaAbsensi: ['HRD', 'CTO', 'PM'],
okr: ['HRD', 'PM', 'CTO'],
meeting: ['HRD', 'PM'],
......
......@@ -69,14 +69,14 @@ const formatTanggal = (tanggal: string) => {
const openModal = (mode: 'add' | 'edit', index: number = -1) => {
if (mode === 'edit') {
if (listTimeOff.value[index].details[0].status !== 'rejected') {
if (listTimeOff.value[index].status !== 'rejected') {
return;
}
}
formMode.value = mode;
if (mode === 'edit') {
editedIndex.value = index;
const selectedItem = listTimeOff.value[index].details[0];
const selectedItem = listTimeOff.value[index];
formItem.value = {
start_date: formatISO(parseISO(selectedItem.start_date), { representation: 'date' }),
end_date: formatISO(parseISO(selectedItem.end_date), { representation: 'date' }),
......@@ -151,7 +151,7 @@ const saveData = async () => {
if (formMode.value === 'add') {
await apiTimeOffStore.postTimeOff(formItem.value);
} else if (formMode.value === 'edit') {
const id = listTimeOff.value[editedIndex.value].details[0].id_time_off;
const id = listTimeOff.value[editedIndex.value].id_time_off;
await apiTimeOffStore.putTimeOff(formItem.value, id);
}
getData();
......@@ -189,7 +189,7 @@ const openDeleteModal = (index: number) => {
};
const deleteData = async () => {
const id = listTimeOff.value[deletedIndex.value].details[0].id_time_off;
const id = listTimeOff.value[deletedIndex.value].id_time_off;
await apiTimeOffStore.deleteTimeOff(id);
getData();
};
......@@ -219,7 +219,13 @@ const isImage = (url: string) => {
<div class="col-md-4 d-flex justify-content-start align-items-center">
<div class="input-group">
<span class="input-group-text"><i class="bx bx-calendar"></i></span>
<input type="month" class="form-control" v-model="searchMonthYear" placeholder="Pilih Bulan dan Tahun" @input="getData"/>
<input
type="month"
class="form-control"
v-model="searchMonthYear"
placeholder="Pilih Bulan dan Tahun"
@input="getData"
/>
</div>
</div>
<div class="col-md-8 d-flex justify-content-end align-items-center">
......@@ -257,18 +263,18 @@ const isImage = (url: string) => {
</tr>
<tr v-else v-for="(item, index) in listTimeOff" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ formatTanggal(item.details[0].start_date) }}</td>
<td>{{ formatTanggal(item.details[0].end_date) }}</td>
<td>{{ item.details[0].type }}</td>
<td>{{ formatTanggal(item.start_date) }}</td>
<td>{{ formatTanggal(item.end_date) }}</td>
<td>{{ item.type }}</td>
<td>
<span
:class="{
'badge bg-label-warning': item.details[0].status === 'pending',
'badge bg-label-success': item.details[0].status === 'approved',
'badge bg-label-danger': item.details[0].status === 'rejected'
'badge bg-label-warning': item.status === 'pending',
'badge bg-label-success': item.status === 'approved',
'badge bg-label-danger': item.status === 'rejected'
}"
>
{{ item.details[0].status }}
{{ item.status }}
</span>
</td>
<td>
......@@ -278,11 +284,11 @@ const isImage = (url: string) => {
role="button"
data-bs-toggle="modal"
data-bs-target="#viewModal"
@click="openView(item.details[0])"
@click="openView(item)"
><i class="bx bx-show-alt me-1"></i> View</span
>
<span
v-if="item.details[0].status === 'rejected'"
v-if="item.status === 'rejected'"
class="badge bg-label-warning me-1"
role="button"
@click="openModal('edit', index)"
......@@ -291,7 +297,7 @@ const isImage = (url: string) => {
><i class="bx bx-edit-alt me-1"></i> Edit
</span>
<span
v-if="item.details[0].status !== 'approved'"
v-if="item.status !== 'approved'"
class="badge bg-label-danger me-1"
role="button"
data-bs-toggle="modal"
......
<route lang="yaml">
meta:
layout: default
requiresAuth: true
</route>
meta:
layout: default
requiresAuth: true
</route>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useAuthStore } from '../stores/api/authStore';
import { useApiTimeOffStore } from '@/stores/api/ajuan/time-off';
import { useApiOvertimeStrore } from '@/stores/api/ajuan/overtime';
import { useApiMeetingStore } from '@/stores/api/meeting/meeting';
import { useApiEmployeeStore } from '@/stores/api/master/karyawan';
import { storeToRefs } from 'pinia';
import { parseISO, format, isValid } from 'date-fns';
import { id } from 'date-fns/locale';
const paramsMeeting = ref({ page: 1, pageSize: 10 });
const paramsTimeOff = ref({ page: 1, pageSize: 10 });
const auth = useAuthStore();
const lembur = useApiOvertimeStrore();
const employeeName = computed(() => auth.employee?.name);
const totalLembur = computed(() => lembur.totalData);
const apiMeetingStore = useApiMeetingStore();
const { listMeeting } = storeToRefs(apiMeetingStore);
const apiTimeOffStore = useApiTimeOffStore();
const { listTimeOff, totalData } = storeToRefs(apiTimeOffStore);
const apiEmployeeStore = useApiEmployeeStore();
const { listEmployee } = storeToRefs(apiEmployeeStore);
const getData = async () => {
await apiMeetingStore.getMeeting({ ...paramsMeeting.value });
await apiTimeOffStore.getTimeOff({ ...paramsTimeOff.value });
await apiEmployeeStore.getEmployee();
};
onMounted(() => {
getData();
});
const formatTanggal = (tanggal: string) => {
const date = parseISO(tanggal);
if (!isValid(date)) {
return 'Invalid Date';
}
return format(date, 'dd MMMM yyyy', { locale: id });
};
const getEmployeeName = (id_employee: string) => {
const employee = listEmployee.value.find((employee: { id_employee: string }) => employee.id_employee === id_employee);
return employee ? employee.name : 'Unknown';
};
</script>
<template>
<div class="container-xxl flex-grow-1 container-p-y">
<div class="row">
<div class="col-lg-8 mb-4 order-0">
<div
:class="
auth.employee?.jabatan === 'HRD' || auth.employee?.jabatan === 'PM' || auth.employee?.jabatan === 'CTO'
? 'col-lg-12 mb-4 order-0'
: 'col-lg-8 mb-4 order-0'
"
>
<div class="card">
<div class="d-flex align-items-end row">
<div class="col-sm-7">
<div class="card-body">
<h5 class="card-title text-primary">Hai Admin! 👋</h5>
<h5 class="card-title text-primary">Hai {{ employeeName }}! 👋</h5>
<p class="mb-4">
Waktunya untuk memulai hari dengan semangat! Ayo mulai hari ini dengan penuh energi dan produktivitas.
</p>
<!-- Tombol untuk melakukan presensi -->
<router-link to="/absensi/absensi">
<button type="button" class="btn btn-primary">Presensi Sekarang</button>
</router-link>
......@@ -36,16 +90,20 @@
</div>
</div>
<div class="col-4 mb-4">
<div class="card">
<div class="card-body">
<div class="d-flex flex-column align-items-center justify-content-center text-center">
<div class="card-title">
<h5 class="text-nowrap text-primary mb-2">Congratulations Admin! 🎉</h5>
<span class="badge bg-label-warning rounded-pill">Mei 2024</span>
</div>
<div class="mt-auto">
<h5 class="mb-0 display-1">92</h5>
<div
v-if="auth.employee?.jabatan !== 'HRD' && auth.employee?.jabatan !== 'PM' && auth.employee?.jabatan !== 'CTO'"
>
<div class="col-4 mb-4">
<div class="card">
<div class="card-body">
<div class="d-flex flex-column align-items-center justify-content-center text-center">
<div class="card-title">
<h5 class="text-nowrap text-primary mb-2">Congratulations {{ employeeName }}! 🎉</h5>
<span class="badge bg-label-warning rounded-pill">Juni 2024</span>
</div>
<div class="mt-auto">
<h5 class="mb-0 display-1">98</h5>
</div>
</div>
</div>
</div>
......@@ -61,7 +119,7 @@
<i class="menu-icon tf-icons bx bx-user me-4" style="font-size: 2rem; color: green"></i>
<div>
<span class="fw-semibold d-block mb-1">Karyawan</span>
<h3 class="card-title fw-bold mb-2">50</h3>
<h3 class="card-title fw-bold mb-2">8</h3>
</div>
</div>
</div>
......@@ -74,7 +132,7 @@
<i class="menu-icon tf-icons bx bxl-codepen me-4" style="font-size: 2rem; color: orange"></i>
<div>
<span class="fw-semibold d-block mb-1">Jabatan</span>
<h3 class="card-title fw-bold mb-2">15</h3>
<h3 class="card-title fw-bold mb-2">5</h3>
</div>
</div>
</div>
......@@ -87,7 +145,7 @@
<i class="menu-icon tf-icons bx bx-task me-4" style="font-size: 2rem; color: red"></i>
<div>
<span class="fw-semibold d-block mb-1">Project</span>
<h3 class="card-title fw-bold mb-2">10</h3>
<h3 class="card-title fw-bold mb-2">4</h3>
</div>
</div>
</div>
......@@ -100,7 +158,7 @@
<i class="menu-icon tf-icons bx bx-time me-4" style="font-size: 2rem; color: black"></i>
<div>
<span class="fw-semibold d-block mb-1">Presensi</span>
<h3 class="card-title fw-bold mb-2">30</h3>
<h3 class="card-title fw-bold mb-2">10</h3>
</div>
</div>
</div>
......@@ -113,7 +171,7 @@
<i class="menu-icon tf-icons bx bx-sun me-4" style="font-size: 2rem; color: yellow"></i>
<div>
<span class="fw-semibold d-block mb-1">Cuti</span>
<h3 class="card-title fw-bold mb-2">2</h3>
<h3 class="card-title fw-bold mb-2">{{ totalData }}</h3>
</div>
</div>
</div>
......@@ -126,7 +184,7 @@
<i class="menu-icon tf-icons bx bxs-hourglass me-4" style="font-size: 2rem; color: green"></i>
<div>
<span class="fw-semibold d-block mb-1">Lembur</span>
<h3 class="card-title fw-bold mb-2">0</h3>
<h3 class="card-title fw-bold mb-2">{{ totalLembur }}</h3>
</div>
</div>
</div>
......@@ -148,9 +206,14 @@
</tr>
</thead>
<tbody class="table-border-bottom-0">
<tr>
<tr v-if="listMeeting.length === 0">
<td colspan="2">Tidak ada meeting hari ini</td>
</tr>
<tr v-else v-for="(item, index) in listMeeting" :key="index">
<td>{{ formatTanggal(item.date) }}</td>
<td>{{ item.description }}</td>
</tr>
</tbody>
</table>
</div>
......@@ -168,9 +231,14 @@
</tr>
</thead>
<tbody class="table-border-bottom-0">
<tr>
<tr v-if="listTimeOff.length === 0">
<td colspan="2">Tidak ada yang Cuti selama 7 hari kedepan</td>
</tr>
<tr v-else v-for="(item, index) in listTimeOff" :key="index">
<td>{{ getEmployeeName(item.id_employee) }}</td>
<td>{{ formatTanggal(item.start_date) }} - {{ formatTanggal(item.end_date) }}</td>
</tr>
</tbody>
</table>
</div>
......
......@@ -11,6 +11,7 @@ import Pagination from '@/components/pagination/Pagination2.vue';
import { useApiOvertimeStrore } from '@/stores/api/ajuan/overtime';
import { useApiEmployeeStore } from '@/stores/api/master/karyawan';
import { storeToRefs } from 'pinia';
import { useAuthStore } from '@/stores/api/authStore';
const searchMonthYear = ref('');
const searchQuery = ref('');
......@@ -24,6 +25,7 @@ const apiOvertimeStore = useApiOvertimeStrore();
const { listOvertime, totalData } = storeToRefs(apiOvertimeStore);
const apiEmployeeStore = useApiEmployeeStore();
const { listEmployee } = storeToRefs(apiEmployeeStore);
const auth = useAuthStore();
const getData = async () => {
await apiOvertimeStore.getOvertime({ ...paramsOvertime.value, q: searchQuery.value, date: searchMonthYear.value });
......@@ -359,7 +361,7 @@ const fetchAttachment = async () => {
</div>
</div>
<div class="modal-footer justify-content-between">
<div>
<div v-if="auth.employee?.jabatan !== 'PM'&& auth.employee?.jabatan !== 'CTO'">
<button
v-if="viewItem.status === 'pending'"
type="button"
......
<route lang="yaml">
meta:
layout: default
requiresAuth: true
</route>
meta:
layout: default
requiresAuth: true
</route>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { format, isValid, parseISO } from 'date-fns';
......@@ -11,19 +11,18 @@ import Pagination from '@/components/pagination/Pagination2.vue';
import { useApiTimeOffStore } from '@/stores/api/ajuan/time-off';
import { useApiEmployeeStore } from '@/stores/api/master/karyawan';
import { storeToRefs } from 'pinia';
import { useAuthStore } from '@/stores/api/authStore';
interface TimeOff {
details: {
id_employee: string;
id_time_off: string;
start_date: string;
end_date: string;
type: string;
attachment: string;
status: string;
description: string;
}[];
jumlah_cuti: string;
id_employee: string;
id_time_off: string;
start_date: string;
end_date: string;
type: string;
attachment: string;
status: string;
description: string;
jumlah_cuti: number;
}
const selectedItem = ref<TimeOff | null>(null);
......@@ -38,6 +37,7 @@ const apiTimeOffStore = useApiTimeOffStore();
const { listTimeOff, totalData } = storeToRefs(apiTimeOffStore);
const apiEmployeeStore = useApiEmployeeStore();
const { listEmployee } = storeToRefs(apiEmployeeStore);
const auth = useAuthStore();
const getData = async () => {
await apiTimeOffStore.getTimeOff({ ...paramsTimeOff.value, q: searchQuery.value, date: searchMonthYear.value });
......@@ -49,7 +49,7 @@ onMounted(() => {
});
const getEmployeeName = (id_employee: string) => {
const employee = listEmployee.value.find((employee: { id_employee: string; }) => employee.id_employee === id_employee);
const employee = listEmployee.value.find((employee: { id_employee: string }) => employee.id_employee === id_employee);
return employee ? employee.name : 'Unknown';
};
......@@ -68,7 +68,7 @@ const openModal = (item: TimeOff | null, type: string) => {
const updateStatus = async () => {
if (selectedItem.value && actionType.value) {
const id = selectedItem.value.details[0].id_time_off;
const id = selectedItem.value.id_time_off;
const descriptionValue = description.value;
try {
......@@ -79,13 +79,13 @@ const updateStatus = async () => {
}
const newStatus = actionType.value === 'approve' ? 'approved' : 'rejected';
const index = listTimeOff.value[0].details.findIndex((item: { id_time_off: string; }) => item.id_time_off === id);
const index = listTimeOff.value.findIndex((item: { id_time_off: string }) => item.id_time_off === id);
if (index !== -1) {
listTimeOff.value[index].details[0].status = newStatus;
listTimeOff.value[index].status = newStatus;
if (newStatus === 'rejected') {
listTimeOff.value[index].details[0].description = 'Alasan penolakan: ' + descriptionValue;
listTimeOff.value[index].description = 'Alasan penolakan: ' + descriptionValue;
} else {
listTimeOff.value[index].details[0].description = '';
listTimeOff.value[index].description = '';
}
}
description.value = '';
......@@ -96,17 +96,15 @@ const updateStatus = async () => {
};
const viewItem = ref<TimeOff>({
details: [{
id_employee: '',
id_time_off: '',
start_date: '',
end_date: '',
type: '',
attachment: '',
status: '',
description: ''
}],
jumlah_cuti: ''
id_employee: '',
id_time_off: '',
start_date: '',
end_date: '',
type: '',
attachment: '',
status: '',
description: '',
jumlah_cuti: 0,
});
const openView = (item: TimeOff) => {
......@@ -130,7 +128,6 @@ const fetchAttachment = async () => {
console.error('Error fetching attachment:', error);
}
};
</script>
<template>
......@@ -140,13 +137,25 @@ const fetchAttachment = async () => {
<div class="col-md-3 d-flex justify-content-start align-items-center">
<div class="input-group">
<span class="input-group-text"><i class="bx bx-search-alt"></i></span>
<input type="text" class="form-control" v-model="searchQuery" placeholder="Search Karyawan..." @input="getData"/>
<input
type="text"
class="form-control"
v-model="searchQuery"
placeholder="Search Karyawan..."
@input="getData"
/>
</div>
</div>
<div class="col-md-3 d-flex justify-content-start align-items-center">
<div class="input-group">
<span class="input-group-text"><i class="bx bx-calendar"></i></span>
<input type="month" class="form-control" v-model="searchMonthYear" placeholder="Pilih Bulan dan Tahun" @input="getData"/>
<input
type="month"
class="form-control"
v-model="searchMonthYear"
placeholder="Pilih Bulan dan Tahun"
@input="getData"
/>
</div>
</div>
</div>
......@@ -171,18 +180,18 @@ const fetchAttachment = async () => {
</tr>
<tr v-else v-for="(item, index) in listTimeOff" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ getEmployeeName(item.details[0].id_employee) }}</td>
<td>{{ formatTanggal(item.details[0].start_date) }}</td>
<td>{{ item.details[0].type }}</td>
<td>{{ getEmployeeName(item.id_employee) }}</td>
<td>{{ formatTanggal(item.start_date) }}</td>
<td>{{ item.type }}</td>
<td>
<span
:class="{
'badge bg-label-warning': item.details[0].status === 'pending',
'badge bg-label-success': item.details[0].status === 'approved',
'badge bg-label-danger': item.details[0].status === 'rejected'
'badge bg-label-warning': item.status === 'pending',
'badge bg-label-success': item.status === 'approved',
'badge bg-label-danger': item.status === 'rejected'
}"
>
{{ item.details[0].status }}
{{ item.status }}
</span>
</td>
<td>
......@@ -220,7 +229,8 @@ const fetchAttachment = async () => {
<div class="modal-body">
<p>
Apakah Anda yakin ingin {{ actionType === 'approve' ? 'menyetujui' : 'menolak' }} pengajuan cuti oleh
<b>{{ getEmployeeName(selectedItem?.details[0].id_employee ?? '') }}</b> pada tanggal <b>{{ formatTanggal(selectedItem?.details[0].start_date ?? '') }}</b>
<b>{{ getEmployeeName(selectedItem?.id_employee ?? '') }}</b> pada tanggal
<b>{{ formatTanggal(selectedItem?.start_date ?? '') }}</b>
</p>
<!-- Input alasan penolakan -->
<div v-if="actionType === 'reject'" class="mb-3">
......@@ -255,7 +265,7 @@ const fetchAttachment = async () => {
type="text"
id="id_employee"
class="form-control"
:value="getEmployeeName(viewItem.details[0].id_employee)"
:value="getEmployeeName(viewItem.id_employee)"
disabled
/>
</div>
......@@ -267,7 +277,7 @@ const fetchAttachment = async () => {
type="text"
id="start_date"
class="form-control"
:value="formatTanggal(viewItem.details[0].start_date)"
:value="formatTanggal(viewItem.start_date)"
placeholder="DD / MM / YY"
disabled
/>
......@@ -280,7 +290,7 @@ const fetchAttachment = async () => {
type="text"
id="end_date"
class="form-control"
:value="formatTanggal(viewItem.details[0].end_date)"
:value="formatTanggal(viewItem.end_date)"
placeholder="DD / MM / YY"
disabled
/>
......@@ -293,7 +303,7 @@ const fetchAttachment = async () => {
type="text"
id="type"
class="form-control"
v-model="viewItem.details[0].type"
v-model="viewItem.type"
placeholder="DD / MM / YY"
disabled
/>
......@@ -308,10 +318,10 @@ const fetchAttachment = async () => {
<div class="row g-2">
<div class="col mt-3">
<label for="attachment" class="form-label mb-2">Attachment</label>
<div v-if="viewItem.details[0].attachment">
<template v-if="isImage(viewItem.details[0].attachment)">
<div v-if="viewItem.attachment">
<template v-if="isImage(viewItem.attachment)">
<img
:src="viewItem.details[0].attachment"
:src="viewItem.attachment"
alt="Attachment Preview"
style="max-width: 100%; max-height: 400px"
/>
......@@ -328,34 +338,34 @@ const fetchAttachment = async () => {
<label for="status" class="form-label">Status</label>
<div>
<span
:class="{
'badge bg-label-warning': viewItem.details[0].status === 'pending',
'badge bg-label-success': viewItem.details[0].status === 'approved',
'badge bg-label-danger': viewItem.details[0].status === 'rejected'
}"
>
{{ viewItem.details[0].status }}
</span>
:class="{
'badge bg-label-warning': viewItem.status === 'pending',
'badge bg-label-success': viewItem.status === 'approved',
'badge bg-label-danger': viewItem.status === 'rejected'
}"
>
{{ viewItem.status }}
</span>
</div>
</div>
</div>
<div v-if="viewItem.details[0].status === 'rejected'" class="row">
<div v-if="viewItem.status === 'rejected'" class="row">
<div class="col mt-3">
<label for="description" class="form-label">Deskripsi</label>
<textarea
class="form-control"
id="description"
rows="3"
v-model="viewItem.details[0].description"
v-model="viewItem.description"
disabled
></textarea>
</div>
</div>
</div>
<div class="modal-footer justify-content-between">
<div>
<div v-if="auth.employee?.jabatan !== 'PM' && auth.employee?.jabatan !== 'CTO'">
<button
v-if="viewItem.details[0].status === 'pending'"
v-if="viewItem.status === 'pending'"
type="button"
class="btn btn-success me-2"
@click="openModal(viewItem, 'approve')"
......@@ -366,7 +376,7 @@ const fetchAttachment = async () => {
Setujui
</button>
<button
v-if="viewItem.details[0].status === 'pending'"
v-if="viewItem.status === 'pending'"
type="button"
class="btn btn-danger"
@click="openModal(viewItem, 'reject')"
......
......@@ -7,6 +7,7 @@ import { useApiEmployeeStore } from '@/stores/api/master/karyawan';
import { useApiKeyResultStore } from '@/stores/api/master/keyResult';
import { storeToRefs } from 'pinia';
import { formatTanggal, getAvgTarget, getKeyResultName, formatType, getKeyResultTarget, formatDateForInput } from './helper/okr'
import { useAuthStore } from '@/stores/api/authStore';
const searchQuery = ref('');
const searchMonthYear = ref('');
......@@ -25,6 +26,7 @@ const apiEmployeeStore = useApiEmployeeStore();
const { selectedEmployee } = storeToRefs(apiEmployeeStore);
const apiKeyResultStore = useApiKeyResultStore();
const { listKeyResult, selectKeyResult } = storeToRefs(apiKeyResultStore);
const auth = useAuthStore();
const getData = async () => {
await apiAssessmentStore.getAssessment({ ...paramsAssessment.value, q: searchQuery.value, date: searchMonthYear.value});
......@@ -218,7 +220,7 @@ const deleteData = async () => {
<input type="month" class="form-control" v-model="searchMonthYear" placeholder="Pilih Bulan dan Tahun" @input="getData"/>
</div>
</div>
<div class="col-md-6 d-flex justify-content-end align-items-center">
<div v-if="auth.employee?.jabatan !== 'CTO'" class="col-md-6 d-flex justify-content-end align-items-center">
<button
class="btn btn-primary"
type="button"
......@@ -271,6 +273,7 @@ const deleteData = async () => {
><i class="bx bx-show-alt me-1"></i> View</span
>
<span
v-if="auth.employee?.jabatan !== 'CTO'"
class="badge bg-label-warning me-1"
role="button"
@click="openModal('edit', index)"
......@@ -279,6 +282,7 @@ const deleteData = async () => {
><i class="bx bx-edit-alt me-1"></i> Edit
</span>
<span
v-if="auth.employee?.jabatan !== 'CTO'"
class="badge bg-label-danger me-1"
role="button"
data-bs-toggle="modal"
......
......@@ -3,42 +3,27 @@ import { defineStore } from "pinia";
import httpClient from "@/services/ts/httpClient";
interface TimeOff {
id_employee: string;
id_time_off: string;
id_employee: string;
start_date: string;
end_date: string;
type: string;
attachment: string;
status: string;
description: string;
}
interface TransformedTimeOff {
details: TimeOff[];
jumlah_cuti: string;
jumlah_cuti: number;
}
export const useApiTimeOffStore = defineStore('api-time-off', () => {
const listTimeOff = ref<TransformedTimeOff[]>([]);
const listTimeOff = ref<TimeOff[]>([]);
const detailTimeOff = ref<TimeOff | null>(null);
const timeOffAttachment = ref('');
const totalData = ref(0);
const transformData = (data: any): TransformedTimeOff[] => {
return data.map((entry: any) => {
return {
details: Object.keys(entry)
.filter(key => !isNaN(Number(key)))
.map(key => entry[key]),
jumlah_cuti: entry.jumlah_cuti
};
});
};
const getTimeOff = async (params: any) => {
try {
const res = await httpClient.query('/time-off', params);
listTimeOff.value = transformData(res.data.data);
listTimeOff.value = res.data.data;
totalData.value = res.data.totalData;
} catch (error) {
throw error;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment