feat: implement skeleton loading for DataTable component in Plans and Business Types pages

This commit is contained in:
Yoga Pangestu 2026-07-25 10:30:41 +07:00
parent c62643f2ba
commit ca32004d82
4 changed files with 57 additions and 10 deletions

View File

@ -27,6 +27,7 @@ import {
TableRow,
} from '@/components/ui/table'
import { valueUpdater } from '@/lib/utils'
import { Skeleton } from '@/components/ui/skeleton'
import DataTablePagination from './DataTablePagination.vue'
import {
Empty, EmptyDescription,
@ -36,6 +37,7 @@ import {
const props = defineProps<{
columns: ColumnDef<TData, TValue>[]
data: TData[]
loading?: boolean
}>()
const sorting = ref<SortingState>([])
@ -81,6 +83,14 @@ const table = useVueTable({
},
})
function skeletonWidth(columnId: string) {
switch (columnId) {
case 'number': return 'w-6'
case 'actions': return 'w-8'
default: return 'w-full'
}
}
defineExpose({ table })
</script>
@ -99,7 +109,15 @@ defineExpose({ table })
</TableRow>
</TableHeader>
<TableBody>
<template v-if="table.getRowModel().rows?.length">
<template v-if="loading">
<TableRow v-for="i in 5" :key="i">
<TableCell v-for="col in allColumns" :key="col.id"
:class="['actions', 'number'].includes(col.id) ? 'w-0' : ''">
<Skeleton class="h-5 w-full" :class="skeletonWidth(col.id)" />
</TableCell>
</TableRow>
</template>
<template v-else-if="table.getRowModel().rows?.length">
<template v-for="row in table.getRowModel().rows" :key="row.id">
<TableRow>
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id"
@ -131,6 +149,6 @@ defineExpose({ table })
</Table>
</div>
<DataTablePagination :table="table" />
<DataTablePagination v-if="!loading" :table="table" />
</div>
</template>

View File

@ -222,10 +222,7 @@ watch(deleteOpen, (val) => {
</div>
</div>
<div class="px-4 lg:px-6">
<div v-if="status === 'pending'" class="flex items-center justify-center h-24">
<p class="text-sm text-muted-foreground">Memuat data...</p>
</div>
<DataTable v-else ref="tableRef" :columns="columns" :data="businessTypes ?? []">
<DataTable ref="tableRef" :columns="columns" :data="businessTypes ?? []" :loading="status === 'pending'">
<template #filters="{ table }">
<div class="flex items-center gap-2 py-4">
<Input class="max-w-sm" placeholder="Cari nama..."

View File

@ -228,10 +228,7 @@ watch(deleteOpen, (val) => {
</div>
</div>
<div class="px-4 lg:px-6">
<div v-if="status === 'pending'" class="flex items-center justify-center h-24">
<p class="text-sm text-muted-foreground">Memuat data...</p>
</div>
<DataTable v-else ref="tableRef" :columns="columns" :data="plans ?? []">
<DataTable ref="tableRef" :columns="columns" :data="plans ?? []" :loading="status === 'pending'">
<template #filters="{ table }">
<div class="flex items-center gap-2 py-4">
<Input class="max-w-sm" placeholder="Cari nama..."

View File

@ -0,0 +1,35 @@
# Skeleton Loading Table
**Tanggal:** 2026-07-25
**Status:** Selesai
## Tujuan
Mengganti indikator loading "Memuat data..." pada tabel di halaman Plans dan Business Types dengan skeleton loading.
## Yang Dikerjakan
### 1. Penambahan `loading` prop di DataTable.vue
- Menambahkan prop `loading` (boolean, default `false`)
- Saat `loading === true`: menampilkan 5 baris skeleton menggunakan komponen `Skeleton` dengan jumlah kolom sesuai definisi kolom
- Pagination disembunyikan saat loading
- Kolom `number` dan `actions` menggunakan lebar kecil (`w-6`, `w-8`)
### 2. Perubahan halaman Plans
- Sebelum: `v-if="status === 'pending'"` menampilkan teks "Memuat data..."
- Sesudah: DataTable selalu ditampilkan dengan `:loading="status === 'pending'"`
### 3. Perubahan halaman Business Types
- Sebelum: `v-if="status === 'pending'"` menampilkan teks "Memuat data..."
- Sesudah: DataTable selalu ditampilkan dengan `:loading="status === 'pending'"`
## File yang Diubah
| File | Aksi | Detail |
|------|------|--------|
| `app/components/data-table/DataTable.vue` | Diubah | Tambah `loading` prop, `Skeleton` import, skeleton rows, `skeletonWidth` helper |
| `app/pages/admin/plans/index.vue` | Diubah | Ganti `v-if="status === 'pending'"` dengan `:loading` prop pada DataTable |
| `app/pages/admin/business-types/index.vue` | Diubah | Ganti `v-if="status === 'pending'"` dengan `:loading` prop pada DataTable |
## Notes
- Sama seperti implementasi yang sudah diterapkan di folder `core`
- Komponen `Skeleton` tersedia di `@/components/ui/skeleton`