* fix(style): formatting inconsistencies across codebase - Remove trailing semicolons from TypeScript imports - Fix Vue template indentation and line breaks - Standardize component attribute formatting - Remove unnecessary empty lines - Reorder import statements for consistency * chore: update import path and add editorconfig Update SidebarNavLink import path to match new component structure and add standard editorconfig for consistent code formatting
72 lines
2.5 KiB
Vue
72 lines
2.5 KiB
Vue
<script setup lang="ts">
|
|
import type { DataTableLoader } from './type'
|
|
import { Info } from 'lucide-vue-next'
|
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '~/components/pub/ui/table'
|
|
|
|
defineProps<{
|
|
rows: unknown[]
|
|
cols: any[]
|
|
header: any[]
|
|
keys: string[]
|
|
funcParsed: Record<string, (row: any) => any>
|
|
funcHtml: Record<string, (row: any) => string>
|
|
funcComponent: Record<string, (row: any, idx: number) => any>
|
|
}>()
|
|
|
|
const loader = inject('table_data_loader') as DataTableLoader
|
|
</script>
|
|
|
|
<template>
|
|
<Table>
|
|
<TableHeader class="bg-gray-50">
|
|
<TableRow>
|
|
<TableHead
|
|
v-for="(h, idx) in header[0]" :key="`head-${idx}`" class="border"
|
|
:style="{ width: cols[idx]?.width ? `${cols[idx].width}px` : undefined }"
|
|
>
|
|
{{ h.label }}
|
|
</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
|
|
<TableBody v-if="loader.isTableLoading">
|
|
<!-- Loading state with 5 skeleton rows -->
|
|
<TableRow v-for="n in 5" :key="`skeleton-${n}`">
|
|
<TableCell v-for="(key, cellIndex) in keys" :key="`cell-skel-${n}-${cellIndex}`" class="border">
|
|
<Skeleton class="bg-gray-100 animate-pulse text-muted-foreground w-full h-6" />
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableBody>
|
|
<TableBody v-else-if="rows.length === 0">
|
|
<TableRow>
|
|
<TableCell :colspan="keys.length" class="text-center py-8">
|
|
<div class="flex items-center justify-center">
|
|
<Info class="size-5 text-muted-foreground" />
|
|
<span class="ml-2">Tidak ada data tersedia</span>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableBody>
|
|
<TableBody v-else>
|
|
<TableRow v-for="(row, rowIndex) in rows" :key="`row-${rowIndex}`">
|
|
<TableCell v-for="(key, cellIndex) in keys" :key="`cell-${rowIndex}-${cellIndex}`" class="border">
|
|
<!-- If funcComponent has a renderer -->
|
|
<component
|
|
:is="funcComponent[key](row, rowIndex).component" v-if="funcComponent[key]"
|
|
v-bind="funcComponent[key](row, rowIndex)"
|
|
/>
|
|
<!-- If funcParsed or funcHtml returns a value -->
|
|
<template v-else>
|
|
<!-- Use v-html for funcHtml to render HTML content -->
|
|
<div v-if="funcHtml[key]" v-html="funcHtml[key]?.(row)"></div>
|
|
<!-- Use normal interpolation for funcParsed and regular data -->
|
|
<template v-else>
|
|
{{ funcParsed[key]?.(row) ?? (row as any)[key] }}
|
|
</template>
|
|
</template>
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableBody>
|
|
</Table>
|
|
</template>
|