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

// 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) => {
  if (!waktu)
    return '-'

  return waktu.length >= 5 ? waktu.slice(0, 5) : waktu
}

// 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.length >= 5 ? start.slice(0, 5) : '-'
  const jamEnd = end && end.length >= 5 ? end.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,
        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>