1- <script setup lang="ts">
2- import { onMounted , ref , type Component } from ' vue' ;
1+ <script setup lang="ts" generic =" T " >
2+ import type { SortOption , TableProps } from ' @/types/types' ;
3+
4+ import { onMounted , ref } from ' vue' ;
35
46import TextInputLabelled from ' @/components/inputs/TextInputLabelled.vue' ;
57import TablePagination from ' @/components/table/TablePagination.vue' ;
@@ -12,60 +14,45 @@ import SvgSpinners90RingWithBg from '~icons/svg-spinners/90-ring-with-bg';
1214import PhSortDescendingLight from ' ~icons/ph/sort-descending-light' ;
1315import PhSortAscendingLight from ' ~icons/ph/sort-ascending-light' ;
1416
15- const props = withDefaults (
16- defineProps <{
17- useToolbar? : boolean ;
18- usePagination? : boolean ;
19- useGrid? : string ;
20- data: any [];
21- row: Component ;
22- rowAttributes? : { [key : string ]: any };
23- loading? : boolean ;
24- clickAction? : any ;
25- otherAction? : any ;
26- sortAction? : any ;
27- sortingOptions? : {
28- title: string ;
29- value: string ;
30- disabled? : boolean ;
31- }[];
32- itemsPerPage? : number ;
33- searchQuery? : any ;
34- selectedID? : any ;
35- tableStyles? : string ;
36- startAscending? : boolean ;
37- paginationClass? : string ;
38- }>(),
39- {
40- useToolbar: true ,
41- usePagination: true ,
42- itemsPerPage: 12 ,
43- selectedID: null ,
44- startAscending: true ,
45- searchQuery: ' ' ,
46- },
47- );
17+ // 👇 Generic prop types
18+
19+ const props = withDefaults (defineProps <TableProps <T >>(), {
20+ useToolbar: true ,
21+ usePagination: true ,
22+ itemsPerPage: 5 ,
23+ selectedID: null ,
24+ startAscending: true ,
25+ searchQuery: ' ' ,
26+ });
27+
28+ const emit = defineEmits <{
29+ (e : ' search' , value : string ): void ;
30+ }>();
31+
4832const tableData = useTable (props );
4933const sortAscending = ref (props .startAscending );
5034const lastSortKey = ref (' ' );
51- const emit = defineEmits ([ ' search ' ]);
35+
5236const model = defineModel <string | undefined >({
5337 required: false ,
5438 default: undefined ,
5539});
5640
57- const handleSortChange = (sortKey ? : { title? : string ; value? : string ; disabled? : boolean }) => {
41+ defineSlots <{
42+ row(props : { row: T ; index: number ; selectedID: any }): any ;
43+ }>();
44+
45+ const handleSortChange = (sortKey ? : SortOption ) => {
5846 if (sortKey ?.value ) {
5947 lastSortKey .value = sortKey .value ;
6048 }
6149
6250 if (! lastSortKey .value ) return ;
63- props .sortAction (lastSortKey .value , sortAscending .value ? 1 : - 1 );
51+ props .sortAction ?. (lastSortKey .value as keyof T , sortAscending .value ? 1 : - 1 );
6452};
6553
6654const handleSearch = (event : InputEvent ) => {
6755 const target = event .target as HTMLInputElement ;
68-
6956 const value = target .value ;
7057
7158 if (model .value !== undefined ) {
@@ -77,13 +64,13 @@ const handleSearch = (event: InputEvent) => {
7764};
7865
7966onMounted (() => {
80- if (props .useToolbar && props .sortAction ) props .sortAction (lastSortKey .value , props .startAscending ? 1 : - 1 );
67+ if (props .useToolbar && props .sortAction ) props .sortAction (lastSortKey .value as keyof T , props .startAscending ? 1 : - 1 );
8168});
8269 </script >
8370
8471<template >
8572 <!-- [&>*:not(:first-child)]:pt-4 -->
86- <section class =" flex flex-col gap-4" >
73+ <section class =" flex flex-col gap-4 w-full " >
8774 <section v-if =" props.useToolbar" class =" flex justify-center sm:justify-between flex-col sm:flex-row gap-2" >
8875 <TextInputLabelled
8976 :value =" model ?? tableData .fields .searchQuery "
@@ -94,16 +81,6 @@ onMounted(() => {
9481 title="Search Here"
9582 @input =" handleSearch "
9683 />
97- <!-- <TextInputLabelled
98- v-else
99- v-model="tableData.fields.searchQuery"
100- :text="'Search:'"
101- :placeholder="'Enter Search Query...'"
102- :id="'table-search'"
103- class="w-full sm:w-80"
104- title="Search Here"
105- @input="$emit('search', tableData.fields.searchQuery)"
106- /> -->
10784 <span class =" flex items-end gap-2 flex-wrap" >
10885 <div class =" flex gap-2 flex-col w-full sm:w-40 flex-1" >
10986 <FormInputLabel :field =" { name: ' sort' , text: ' Sort by:' } " />
@@ -142,18 +119,20 @@ onMounted(() => {
142119 <p >{{ loading ? '...Loading' : 'No Results' }}</p >
143120 <SvgSpinners90RingWithBg v-show =" loading " />
144121 </div >
145- <component
146- v-else
147- :is =" props.row"
148- v-for =" (row, index) in tableData.filteredPage"
149- :key =" row?.id ?? index"
150- :data =" row"
151- :index =" index"
152- :currentID =" props.selectedID ?? null"
153- v-bind =" rowAttributes"
154- @clickAction =" (...args: any[]) => props.clickAction?.(row?.id, ...args)"
155- @otherAction =" (...args: any[]) => props.otherAction?.(row?.id, ...args)"
156- ></component >
122+ <template v-else v-for =" (row , index ) in tableData .filteredPage " :key =" row ?.id ?? index " >
123+ <slot name =" row" :row =" row" :index =" index" :selectedID =" props.selectedID" >
124+ <component
125+ :is =" props.row"
126+ :key =" row?.id ?? index"
127+ :data =" row"
128+ :index =" index"
129+ :currentID =" props.selectedID ?? null"
130+ v-bind =" rowAttributes"
131+ @clickAction =" (...args: any[]) => props.clickAction?.(row?.id, ...args)"
132+ @otherAction =" (...args: any[]) => props.otherAction?.(row?.id, ...args)"
133+ ></component >
134+ </slot >
135+ </template >
157136 </section >
158137 <!-- <hr class="p-0" /> -->
159138 <TablePagination
0 commit comments