feat: introduce reusable DataTableEmpty component to standardize empty state handling across tables
This commit is contained in:
parent
5986ec75a3
commit
06e313d168
@ -5,10 +5,7 @@ import { FlexRender, getCoreRowModel, useVueTable } from '@tanstack/vue-table';
|
|||||||
import { computed, provide } from 'vue';
|
import { computed, provide } from 'vue';
|
||||||
import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue';
|
import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import DataTableEmpty from './DataTableEmpty.vue';
|
||||||
Empty, EmptyDescription,
|
|
||||||
EmptyHeader, EmptyTitle
|
|
||||||
} from '@/components/ui/empty';
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -199,14 +196,7 @@ function resolveRowSpan(row: TData, columnId: string): number | undefined {
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</template>
|
</template>
|
||||||
<TableEmpty v-else :colspan="resolvedColumns.length">
|
<TableEmpty v-else :colspan="resolvedColumns.length">
|
||||||
<Empty>
|
<DataTableEmpty plain />
|
||||||
<EmptyHeader>
|
|
||||||
<EmptyTitle>Data tidak ditemukan</EmptyTitle>
|
|
||||||
<EmptyDescription>
|
|
||||||
Silakan lakukan pencarian atau filter untuk menemukan data yang Anda cari.
|
|
||||||
</EmptyDescription>
|
|
||||||
</EmptyHeader>
|
|
||||||
</Empty>
|
|
||||||
</TableEmpty>
|
</TableEmpty>
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
40
resources/js/components/data-table/DataTableEmpty.vue
Normal file
40
resources/js/components/data-table/DataTableEmpty.vue
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import {
|
||||||
|
Empty,
|
||||||
|
EmptyDescription,
|
||||||
|
EmptyHeader,
|
||||||
|
EmptyTitle,
|
||||||
|
} from '@/components/ui/empty';
|
||||||
|
|
||||||
|
withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
plain?: boolean;
|
||||||
|
class?: HTMLAttributes['class'];
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
title: 'Data tidak ditemukan',
|
||||||
|
description: 'Silakan lakukan pencarian atau filter untuk menemukan data yang Anda cari.',
|
||||||
|
plain: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :class="cn(!plain && 'rounded-md border px-6 py-10', $props.class)">
|
||||||
|
<Empty>
|
||||||
|
<EmptyHeader>
|
||||||
|
<EmptyTitle>
|
||||||
|
<slot name="title">{{ title }}</slot>
|
||||||
|
</EmptyTitle>
|
||||||
|
<EmptyDescription>
|
||||||
|
<slot name="description">{{ description }}</slot>
|
||||||
|
</EmptyDescription>
|
||||||
|
</EmptyHeader>
|
||||||
|
<slot />
|
||||||
|
</Empty>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -1,3 +1,5 @@
|
|||||||
export { default as DataTable } from './DataTable.vue';
|
export { default as DataTable } from './DataTable.vue';
|
||||||
export { default as DataTableColumnHeader } from './DataTableColumnHeader.vue';
|
export { default as DataTableColumnHeader } from './DataTableColumnHeader.vue';
|
||||||
export { default as DataTableToolbar } from './DataTableToolbar.vue';
|
export { default as DataTableToolbar } from './DataTableToolbar.vue';
|
||||||
|
export { default as DataTableEmpty } from './DataTableEmpty.vue';
|
||||||
|
|
||||||
|
|||||||
@ -6,12 +6,7 @@ import { CuttingStatus } from '@/constants/cutting-status';
|
|||||||
import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue';
|
import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import { DataTableEmpty } from '@/components/data-table';
|
||||||
Empty,
|
|
||||||
EmptyDescription,
|
|
||||||
EmptyHeader,
|
|
||||||
EmptyTitle,
|
|
||||||
} from '@/components/ui/empty';
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -299,16 +294,7 @@ function getGroupedMaterialUsage(materials: any[]): MaterialUsageGroup[] {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="rounded-md border px-6 py-10">
|
<DataTableEmpty v-else description="Silakan lakukan pencarian untuk menemukan data yang Anda cari." />
|
||||||
<Empty>
|
|
||||||
<EmptyHeader>
|
|
||||||
<EmptyTitle>Data tidak ditemukan</EmptyTitle>
|
|
||||||
<EmptyDescription>
|
|
||||||
Silakan lakukan pencarian untuk menemukan data yang Anda cari.
|
|
||||||
</EmptyDescription>
|
|
||||||
</EmptyHeader>
|
|
||||||
</Empty>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="pagination" class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
<div v-if="pagination" class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<p class="text-muted-foreground text-sm">
|
<p class="text-muted-foreground text-sm">
|
||||||
|
|||||||
@ -6,12 +6,7 @@ import { formatRupiah } from '@/lib/rupiah';
|
|||||||
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
|
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import { DataTableEmpty } from '@/components/data-table';
|
||||||
Empty,
|
|
||||||
EmptyDescription,
|
|
||||||
EmptyHeader,
|
|
||||||
EmptyTitle,
|
|
||||||
} from '@/components/ui/empty';
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -172,16 +167,7 @@ function rowNumber(index: number): number {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="rounded-md border px-6 py-10">
|
<DataTableEmpty v-else />
|
||||||
<Empty>
|
|
||||||
<EmptyHeader>
|
|
||||||
<EmptyTitle>Data tidak ditemukan</EmptyTitle>
|
|
||||||
<EmptyDescription>
|
|
||||||
Silakan lakukan pencarian atau filter untuk menemukan data yang Anda cari.
|
|
||||||
</EmptyDescription>
|
|
||||||
</EmptyHeader>
|
|
||||||
</Empty>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="pagination" class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
<div v-if="pagination" class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<p class="text-muted-foreground text-sm">
|
<p class="text-muted-foreground text-sm">
|
||||||
|
|||||||
@ -5,12 +5,7 @@ import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue';
|
|||||||
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
|
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import { DataTableEmpty } from '@/components/data-table';
|
||||||
Empty,
|
|
||||||
EmptyDescription,
|
|
||||||
EmptyHeader,
|
|
||||||
EmptyTitle,
|
|
||||||
} from '@/components/ui/empty';
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -148,16 +143,7 @@ function rowNumber(index: number): number {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="rounded-md border px-6 py-10">
|
<DataTableEmpty v-else />
|
||||||
<Empty>
|
|
||||||
<EmptyHeader>
|
|
||||||
<EmptyTitle>Data tidak ditemukan</EmptyTitle>
|
|
||||||
<EmptyDescription>
|
|
||||||
Silakan lakukan pencarian atau filter untuk menemukan data yang Anda cari.
|
|
||||||
</EmptyDescription>
|
|
||||||
</EmptyHeader>
|
|
||||||
</Empty>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="pagination" class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
<div v-if="pagination" class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<p class="text-muted-foreground text-sm">
|
<p class="text-muted-foreground text-sm">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user