106 lines
3.2 KiB
Vue
106 lines
3.2 KiB
Vue
<script lang="ts" setup>
|
|
import dayjs from 'dayjs'
|
|
import { Search } from '@lucide/vue'
|
|
import { AlertRoot, AlertTitle, AlertDescription } from '@/components/ui/alert'
|
|
import { Input } from '@/components/ui/input'
|
|
import DataTable from '@/components/ui/usage/DataTable.vue'
|
|
import type { TableHeader } from '@/components/ui/usage/DataTable.vue'
|
|
import { useActivityLogList } from '../composables/useActivityLogList'
|
|
import { formatModelType } from '../utils/activity-log.utils'
|
|
|
|
const {
|
|
activityLogs,
|
|
loading,
|
|
error,
|
|
search,
|
|
page,
|
|
itemsPerPage,
|
|
pagination,
|
|
} = useActivityLogList()
|
|
|
|
function formatDateTime(value: string | null | undefined): string {
|
|
if (!value) return '-'
|
|
return dayjs(value).format('DD MMM YYYY, HH:mm')
|
|
}
|
|
|
|
function formatCauserName(item: { causer?: { name?: string } | null }): string {
|
|
return item.causer?.name ?? '-'
|
|
}
|
|
|
|
const headers: TableHeader[] = [
|
|
{ title: 'Bil.', key: '#', sortable: false },
|
|
{
|
|
title: 'Tarikh',
|
|
key: 'created_at',
|
|
sortable: false,
|
|
exportValue: (item) => formatDateTime(item.created_at),
|
|
},
|
|
{
|
|
title: 'Pengguna',
|
|
key: 'causer.name',
|
|
sortable: false,
|
|
exportValue: (item) => formatCauserName(item),
|
|
},
|
|
{
|
|
title: 'Emel',
|
|
key: 'causer.email',
|
|
sortable: false,
|
|
exportValue: (item) => item.causer?.email ?? '-',
|
|
},
|
|
{ title: 'Keterangan', key: 'description', sortable: false },
|
|
{
|
|
title: 'Subjek',
|
|
key: 'subject_type',
|
|
sortable: false,
|
|
exportValue: (item) => formatModelType(item.subject_type),
|
|
},
|
|
{ title: 'Peristiwa', key: 'event', sortable: false },
|
|
]
|
|
</script>
|
|
|
|
<template>
|
|
<div class="w-full space-y-6">
|
|
<div>
|
|
<h2 class="text-lg font-medium">Log Aktiviti</h2>
|
|
<p class="mt-1 text-sm opacity-70">Semak rekod aktiviti pengguna dalam sistem.</p>
|
|
</div>
|
|
|
|
<AlertRoot v-if="error" variant="danger">
|
|
<AlertTitle>Error</AlertTitle>
|
|
<AlertDescription>{{ error }}</AlertDescription>
|
|
</AlertRoot>
|
|
|
|
<DataTable :headers="headers" :items="activityLogs" :loading="loading" :pagination="pagination" show-pagination
|
|
exportable export-file-name="activity-logs" v-model:page="page" v-model:items-per-page="itemsPerPage">
|
|
<template #toolbar>
|
|
<div class="relative w-full max-w-md flex-1">
|
|
<Search class="pointer-events-none absolute top-1/2 left-3 z-10 size-4 -translate-y-1/2 text-foreground/50"
|
|
aria-hidden="true" />
|
|
<Input v-model="search" type="search" placeholder="Cari keterangan, subjek, peristiwa, pengguna..."
|
|
class="w-full pl-9" aria-label="Cari log aktiviti" />
|
|
</div>
|
|
</template>
|
|
|
|
<template #item.created_at="{ item }">
|
|
{{ formatDateTime(item.created_at) }}
|
|
</template>
|
|
|
|
<template #item.causer.name="{ item }">
|
|
{{ formatCauserName(item) }}
|
|
</template>
|
|
|
|
<template #item.causer.email="{ item }">
|
|
<span class="lowercase">{{ item.causer?.email ?? '-' }}</span>
|
|
</template>
|
|
|
|
<template #item.subject_type="{ item }">
|
|
{{ formatModelType(item.subject_type) }}
|
|
</template>
|
|
|
|
<template #item.event="{ item }">
|
|
{{ item.event ?? '-' }}
|
|
</template>
|
|
</DataTable>
|
|
</div>
|
|
</template>
|