UserLog.vue 4.41 KB
<script setup lang="ts">
import { useKeycloakStore } from "@/@core/stores/keycloakStore";
import { onMounted, ref, watchEffect } from "vue";

// Store Keycloak
const keycloakStore = useKeycloakStore();

// Data dan state
const items = ref<any[]>([]);
const loading = ref(false);
const searchQuery = ref("");

// Fungsi ambil tanggal dari shift_start atau shift_end
const getTanggal = (waktu: string) => (waktu ? waktu.split(" ")[0] : "-");

// Fungsi ambil jam dari start_time atau end_time, kasih "-" kalau kosong
const getJam = (waktu: string) => (waktu ? waktu.split(" ")[1].slice(0, 5) : "-");

// Fungsi ambil nama hari dari tanggal
const getNamaHari = (tanggal: string) => {
  if (!tanggal || tanggal === "-") return "-";
  const date = new Date(tanggal);
  if (isNaN(date.getTime())) return "-";
  return new Intl.DateTimeFormat("id-ID", { weekday: "long" }).format(date);
};

const getJadwalShift = (start: string, end: string) => {
  const jamStart = start ? start.split(" ")[1].slice(0, 5) : "-";
  const jamEnd = end ? end.split(" ")[1].slice(0, 5) : "-";
  return `${jamStart} - ${jamEnd}`;
};

const getStatus = (start: string | undefined, end: string | undefined) => {
  if (!start && !end) return "Tidak Ada";
  if (!start || !end) return "Belum Hitung";
  return "On Time";
};

// Header tabel
const logHeaders = [
  { title: "TANGGAL", key: "tanggal" },
  { title: "NAMA HARI", key: "namaHari" },
  { title: "SHIFT", key: "shift" },
  { title: "JADWAL SHIFT", key: "jadwalShift" },
  { title: "MULAI AKTUAL", key: "start_time" },
  { title: "SELESAI AKTUAL", key: "end_time" },
  { title: "STATUS", key: "status" },
];

// Fungsi ambil data dari API
async function getData() {
  loading.value = true;
  items.value = [];

  try {
    const apiEndpoint = "https://api.ui.ac.id/my/hr/attendance";
    const response = await fetch(apiEndpoint, {
      headers: {
        Authorization: `Bearer ${keycloakStore.accessToken}`,
      },
    });

    if (!response.ok) throw new Error("Gagal mengambil data");
    const dataku = await response.json();

    // Tambahkan properti tanggal, namaHari, mulai aktual, dan selesai aktual ke setiap item
    items.value = dataku.map((item: any) => {
      const tanggal = getTanggal(item.shift_start) || getTanggal(item.shift_end);
      return {
        ...item,
        tanggal: tanggal,
        namaHari: getNamaHari(tanggal),
        jadwalShift: getJadwalShift(item.shift_start, item.shift_end),
        start_time: getJam(item.start_time),
        end_time: getJam(item.end_time),
        status: getStatus(item.start_time, item.end_time),
      };
    });
  } catch (err) {
    console.error("Gagal mengambil data:", err);
  } finally {
    loading.value = false;
  }
}

// Fetch data saat mounted
onMounted(() => {
  keycloakStore.refresh();
  getData();
});

// Auto refresh data saat token berubah
watchEffect(async () => {
  if (!keycloakStore.accessToken) return;
  await getData();
});

const filteredItems = computed(() => {
  if (!searchQuery.value) return items.value;

  const query = searchQuery.value.toLowerCase();

  return items.value.filter((item) =>
    logHeaders.some(
      (header) => item[header.key] && String(item[header.key]).toLowerCase().includes(query)
    )
  );
});

</script>

<template>
  <VCard title="Log Absen" class="recentnamaHariCard">
    <div class="search-container mb-4 pl-2 pr-2">
      <VTextField
        v-model="searchQuery"
        label="Search"
        placeholder="Search ..."
        append-inner-icon="ri-search-line"
        clearable
        single-line
        hide-details
        dense
        outlined
      />
    </div>
    <VDataTable
      :headers="logHeaders"
      :items="filteredItems"
      hide-default-footer
      fixed-header
      item-value="tanggal"
      :sort-by="['tanggal']"
      :sort-asc="[true]"
    >
  
    <template #item.namaHari="{ item }">
  <VChip
    :color="item.namaHari === 'Sabtu' || item.namaHari === 'Minggu' ? 'error' : 'default'"
    :class="`text-${item.namaHari === 'Sabtu' || item.namaHari === 'Minggu' ? 'error' : 'default'}`"
    size="small"
    class="font-weight-medium"
  >
    {{ item.namaHari }}
  </VChip>
</template>

<template #item.status="{ item }">
  <VChip
    :color="item.status === 'Tidak Ada'  ? 'error' : 'primary'"
    :class="`text-${item.status === 'Tidak Ada' ? 'error' : 'primary'}`"
    size="small"
    class="font-weight-medium"
  >
    {{ item.status }}
  </VChip>
</template>


</VDataTable>

    
  </VCard>
</template>