183 lines
5.0 KiB
Vue
183 lines
5.0 KiB
Vue
<script setup>
|
|
import { computed, ref } from "vue";
|
|
import { X, Settings2 } from "lucide-vue-next";
|
|
import { Input } from "@/Components/ui/input";
|
|
import { Button } from "@/Components/ui/button";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/Components/ui/select";
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/Components/ui/popover";
|
|
import DataTableViewOptions from "./DataTableViewOptions.vue";
|
|
|
|
/**
|
|
* DataTable Toolbar Component
|
|
* Simplified toolbar following shadcn-vue patterns for TanStack Table integration
|
|
*/
|
|
|
|
const props = defineProps({
|
|
// TanStack Table instance
|
|
table: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
// Column to filter on (e.g., 'email', 'name')
|
|
filterColumn: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
// Placeholder text for filter input
|
|
filterPlaceholder: {
|
|
type: String,
|
|
default: "Filter...",
|
|
},
|
|
// Show view options (column visibility toggle)
|
|
showViewOptions: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
// Show per-page selector
|
|
showPerPageSelector: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
// Current per page value
|
|
perPage: {
|
|
type: Number,
|
|
default: 15,
|
|
},
|
|
// Per page options
|
|
pageSizeOptions: {
|
|
type: Array,
|
|
default: () => [10, 15, 25, 50, 100],
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits(["update:perPage"]);
|
|
|
|
// Popover state
|
|
const settingsPopoverOpen = ref(false);
|
|
|
|
// Check if any filters are active
|
|
const isFiltered = computed(() => {
|
|
if (!props.filterColumn) return false;
|
|
const column = props.table.getColumn(props.filterColumn);
|
|
return column && column.getFilterValue();
|
|
});
|
|
|
|
// Get/set filter value
|
|
const filterValue = computed({
|
|
get() {
|
|
if (!props.filterColumn) return "";
|
|
const column = props.table.getColumn(props.filterColumn);
|
|
return column?.getFilterValue() ?? "";
|
|
},
|
|
set(value) {
|
|
if (!props.filterColumn) return;
|
|
const column = props.table.getColumn(props.filterColumn);
|
|
column?.setFilterValue(value);
|
|
},
|
|
});
|
|
|
|
// Reset all filters
|
|
function resetFilters() {
|
|
props.table.resetColumnFilters();
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex items-center justify-between">
|
|
<!-- Left side: Search and Filters -->
|
|
<div class="flex flex-1 items-center space-x-2">
|
|
<!-- Filter Input -->
|
|
<Input
|
|
v-if="filterColumn"
|
|
v-model="filterValue"
|
|
:placeholder="filterPlaceholder"
|
|
class="h-8 w-[150px] lg:w-[250px]"
|
|
/>
|
|
|
|
<!-- Custom filter slots -->
|
|
<slot name="filters" :table="table" />
|
|
|
|
<!-- Reset filters button -->
|
|
<Button
|
|
v-if="isFiltered"
|
|
variant="ghost"
|
|
@click="resetFilters"
|
|
class="h-8 px-2 lg:px-3"
|
|
>
|
|
Reset
|
|
<X class="ml-2 h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
|
|
<!-- Right side: Actions and View Options -->
|
|
<div class="flex items-center space-x-2">
|
|
<!-- Custom action slots -->
|
|
<slot name="actions" :table="table" />
|
|
|
|
<!-- Settings Popover (Per-page selector + View Options) -->
|
|
<Popover v-model:open="settingsPopoverOpen">
|
|
<PopoverTrigger as-child>
|
|
<Button variant="outline" size="sm" class="gap-2">
|
|
<Settings2 class="h-4 w-4" />
|
|
Pogled
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent class="w-[300px]" align="end">
|
|
<div class="space-y-4">
|
|
<div class="space-y-2">
|
|
<h4 class="font-medium text-sm">Nastavitve pogleda</h4>
|
|
</div>
|
|
|
|
<div class="space-y-3">
|
|
<!-- Per page selector -->
|
|
<div
|
|
v-if="showPerPageSelector"
|
|
class="flex items-center justify-between gap-4"
|
|
>
|
|
<label class="text-sm whitespace-nowrap">Elementov na stran</label>
|
|
<Select
|
|
:model-value="String(perPage)"
|
|
@update:model-value="
|
|
(value) => {
|
|
emit('update:perPage', Number(value));
|
|
settingsPopoverOpen = false;
|
|
}
|
|
"
|
|
>
|
|
<SelectTrigger class="h-9 w-[70px]">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent align="end">
|
|
<SelectItem
|
|
v-for="size in pageSizeOptions"
|
|
:key="size"
|
|
:value="String(size)"
|
|
>
|
|
{{ size }}
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<!-- Column visibility -->
|
|
<div v-if="showViewOptions" class="flex items-center justify-between gap-4">
|
|
<label class="text-sm whitespace-nowrap">Vidnost stolpcev</label>
|
|
<DataTableViewOptions
|
|
:table="table"
|
|
@column-toggle="settingsPopoverOpen = false"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</PopoverContent>
|
|
</Popover>
|
|
</div>
|
|
</div>
|
|
</template>
|