diff --git a/eslint.config.js b/eslint.config.js index ca3e08bb..fbf9b8b2 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -48,6 +48,7 @@ export default typescriptEslint.config( rules: { 'vue/require-default-prop': 'off', 'vue/attribute-hyphenation': 'off', + 'vue/v-on-event-hyphenation': 'off', 'vue/multi-word-component-names': 'off', 'vue/block-lang': 'off', '@typescript-eslint/no-explicit-any': 'off', diff --git a/resources/js/Composables/useLazyDataTable.ts b/resources/js/Composables/useLazyDataTable.ts index c709d9cd..6786bc12 100644 --- a/resources/js/Composables/useLazyDataTable.ts +++ b/resources/js/Composables/useLazyDataTable.ts @@ -1,14 +1,17 @@ import { usePaginatedData } from './usePaginatedData'; -import * as PrimeVue from '@/types/primevue'; +import cloneDeep from 'lodash-es/cloneDeep'; +import { + DataTableFilterMetaData, + DataTableFilterEvent, + DataTableSortEvent, +} from 'primevue'; +import { PrimeVueDataFilters } from '@/types'; export function useLazyDataTable( - initialFilters: PrimeVue.PaginatedDataFilters = {}, + initialFilters: PrimeVueDataFilters = {}, only: string[] = ['request'], initialsRows: number = 20 ) { - const defaultFilters = initialFilters; - const defaultRows = initialsRows; - const { processing, filters, @@ -36,19 +39,29 @@ export function useLazyDataTable( * "Override" parent composable function * Event driven filtering rather than reactive state */ - function filter(event: { filters: PrimeVue.PaginatedDataFilters }) { + function filter(event: DataTableFilterEvent) { pagination.value.page = 1; - filters.value = { ...event.filters }; + const newFilters: PrimeVueDataFilters = {}; + Object.entries(event.filters).forEach(([key, rawFilter]) => { + if ( + rawFilter && + typeof rawFilter === 'object' && + 'matchMode' in rawFilter + ) { + newFilters[key] = rawFilter as DataTableFilterMetaData; + } + }); + filters.value = newFilters; parseEventFilterValues(); fetchData().then(() => { scrollToTop(); }); } - function sort(event: PrimeVue.SortEvent) { + function sort(event: DataTableSortEvent) { pagination.value.page = 1; - sorting.value.field = event.sortField; - sorting.value.order = event.sortOrder; + sorting.value.field = String(event.sortField); + sorting.value.order = event.sortOrder || 1; fetchData().then(() => { scrollToTop(); }); @@ -59,6 +72,7 @@ export function useLazyDataTable( * usePaginatedData() resets sorting.value state as a new object, this will not work for DataTable's */ function reset() { + const defaultFilters = cloneDeep(initialFilters); Object.keys(defaultFilters).forEach((key) => { filters.value[key].value = defaultFilters[key].value; }); @@ -66,7 +80,7 @@ export function useLazyDataTable( sorting.value.order = 1; pagination.value = { page: 1, - rows: defaultRows, + rows: initialsRows, }; fetchData().then(() => { window.history.replaceState(null, '', window.location.pathname); diff --git a/resources/js/Composables/usePaginatedData.ts b/resources/js/Composables/usePaginatedData.ts index f2c3ce5c..5da6bf13 100644 --- a/resources/js/Composables/usePaginatedData.ts +++ b/resources/js/Composables/usePaginatedData.ts @@ -2,39 +2,39 @@ import { ref, computed, onMounted } from 'vue'; import { router, usePage } from '@inertiajs/vue3'; import { FilterMatchMode } from '@primevue/core/api'; import debounce from 'lodash-es/debounce'; -import * as PrimeVue from '@/types/primevue'; - -interface PageStateEvent { - first: number; - rows: number; - page: number; - pageCount: number; +import cloneDeep from 'lodash-es/cloneDeep'; +import { PageState, DataTablePageEvent } from 'primevue'; +import { PrimeVueDataFilters } from '@/types'; + +interface PaginatedFilteredSortedQueryParams { + filters?: PrimeVueDataFilters; + page?: string; + rows?: string; + sortField?: string; + sortOrder?: string; } interface PaginationState { page: number; rows: number; } interface SortState { - field: undefined | string; - order: undefined | null | 0 | 1 | -1; + field: string; + order: number; } export function usePaginatedData( - initialFilters: PrimeVue.PaginatedDataFilters = {}, + initialFilters: PrimeVueDataFilters = {}, only: string[] = ['request'], initialsRows: number = 20 ) { - const defaultFilters = initialFilters; - const defaultRows = initialsRows; - const page = usePage<{ request: { - urlParams: PrimeVue.PaginatedDataUrlParams; + urlParams: PaginatedFilteredSortedQueryParams; }; }>(); const processing = ref(false); - const filters = ref(initialFilters); + const filters = ref(cloneDeep(initialFilters)); const sorting = ref({ field: '', order: 1, @@ -76,7 +76,7 @@ export function usePaginatedData( router.reload({ only: ['request', ...new Set(only)], data: { - filters: filters.value, + filters: filters.value as any, ...pagination.value, sortField: sorting.value.field, sortOrder: sorting.value.order, @@ -95,9 +95,9 @@ export function usePaginatedData( }); } - function paginate(pageStateEvent: PageStateEvent) { - pagination.value.page = pageStateEvent.page + 1; - pagination.value.rows = pageStateEvent.rows; + function paginate(event: PageState | DataTablePageEvent) { + pagination.value.page = event.page + 1; + pagination.value.rows = event.rows; fetchData().then(() => { scrollToTop(); }); @@ -114,6 +114,7 @@ export function usePaginatedData( // Alternatively just use: router.get(window.location.pathname); // Caveat to the above approach, we would lose state from our page not related to pagination/filtering/sorting + const defaultFilters = cloneDeep(initialFilters); Object.keys(defaultFilters).forEach((key) => { filters.value[key].value = defaultFilters[key].value; }); @@ -123,7 +124,7 @@ export function usePaginatedData( }; pagination.value = { page: 1, - rows: defaultRows, + rows: initialsRows, }; fetchData().then(() => { window.history.replaceState(null, '', window.location.pathname); @@ -167,9 +168,9 @@ export function usePaginatedData( }); } - function parseUrlParams(urlParams: PrimeVue.PaginatedDataUrlParams) { + function parseUrlParams(urlParams: PaginatedFilteredSortedQueryParams) { filters.value = { - ...defaultFilters, + ...cloneDeep(initialFilters), ...urlParams?.filters, }; parseUrlFilterValues(); @@ -177,8 +178,7 @@ export function usePaginatedData( sorting.value.field = urlParams.sortField; } if (urlParams?.sortOrder) { - sorting.value.order = - (parseInt(urlParams.sortOrder) as 0 | 1 | -1) || null; + sorting.value.order = parseInt(urlParams.sortOrder); } if (urlParams?.page) { pagination.value.page = parseInt(urlParams.page); diff --git a/resources/js/Layouts/AuthenticatedLayout.vue b/resources/js/Layouts/AuthenticatedLayout.vue index c7048f3c..8701cc15 100644 --- a/resources/js/Layouts/AuthenticatedLayout.vue +++ b/resources/js/Layouts/AuthenticatedLayout.vue @@ -2,7 +2,6 @@ import { ref, useTemplateRef, onMounted, onUnmounted, watchEffect } from 'vue'; import { useForm } from '@inertiajs/vue3'; import ApplicationLogo from '@/Components/ApplicationLogo.vue'; -import Container from '@/Components/Container.vue'; import LinksMenu from '@/Components/PrimeVue/LinksMenu.vue'; import LinksMenuBar from '@/Components/PrimeVue/LinksMenuBar.vue'; import LinksPanelMenu from '@/Components/PrimeVue/LinksPanelMenu.vue'; diff --git a/resources/js/Pages/Dashboard.vue b/resources/js/Pages/Dashboard.vue index 3ed0473a..71546c79 100644 --- a/resources/js/Pages/Dashboard.vue +++ b/resources/js/Pages/Dashboard.vue @@ -1,6 +1,4 @@ diff --git a/resources/js/Pages/Profile/Edit.vue b/resources/js/Pages/Profile/Edit.vue index 5b827e81..ade5b94b 100644 --- a/resources/js/Pages/Profile/Edit.vue +++ b/resources/js/Pages/Profile/Edit.vue @@ -1,13 +1,10 @@