Skip to content

Commit 0985be2

Browse files
authored
Merge pull request #356 from connorabbas/admin-role-dev
Pull master
2 parents c4f6268 + 8a1d8b2 commit 0985be2

File tree

6 files changed

+61
-71
lines changed

6 files changed

+61
-71
lines changed

app/Http/Middleware/HandleInertiaRequests.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App\Http\Middleware;
44

55
use Illuminate\Http\Request;
6+
use Inertia\Inertia;
67
use Inertia\Middleware;
78
use Tighten\Ziggy\Ziggy;
89

@@ -54,6 +55,7 @@ public function share(Request $request): array
5455
'error' => fn () => $request->session()->get('flash_error'),
5556
'message' => fn () => $request->session()->get('flash_message'),
5657
],
58+
'queryParams' => Inertia::always($request->query()),
5759
];
5860
}
5961
}

package-lock.json

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"@primevue/auto-import-resolver": "^4.3.3",
1313
"@tailwindcss/vite": "^4.0.17",
1414
"@types/lodash-es": "^4.17.12",
15-
"@types/qs": "^6.9.18",
1615
"@vitejs/plugin-vue": "^5.2.3",
1716
"@vue/server-renderer": "^3.5.14",
1817
"@vueuse/core": "^13.0.0",
@@ -24,7 +23,6 @@
2423
"lodash-es": "^4.17.21",
2524
"lucide-vue-next": "^0.485.0",
2625
"primevue": "^4.3.3",
27-
"qs": "^6.14.0",
2826
"tailwind-merge": "^3.2.0",
2927
"tailwindcss": "^4.0.17",
3028
"tailwindcss-primeui": "^0.6.1",

resources/js/composables/usePaginatedData.ts

Lines changed: 41 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { ref, computed, onMounted, toRaw } from 'vue';
2-
import { router } from '@inertiajs/vue3';
2+
import { router, usePage } from '@inertiajs/vue3';
33
import type { Page, PageProps } from '@inertiajs/core';
44
import { FilterMatchMode } from '@primevue/core/api';
55
import { PageState, DataTablePageEvent } from 'primevue';
66
import debounce from 'lodash-es/debounce';
7-
import qs from 'qs';
8-
import type { PrimeVueDataFilters, InertiaRouterFetchCallbacks } from '@/types';
7+
import type { AppPageProps, PrimeVueDataFilters, InertiaRouterFetchCallbacks } from '@/types';
98

10-
interface PaginatedFilteredSortedQueryParams {
9+
interface QueryParams {
1110
filters?: PrimeVueDataFilters;
1211
page?: string;
1312
rows?: string;
1413
sortField?: string;
1514
sortOrder?: string;
15+
[key: string]: any;
1616
}
1717
interface PaginationState {
1818
page: number;
@@ -22,13 +22,16 @@ interface SortState {
2222
field: string;
2323
order: number;
2424
}
25+
type InertiaPageProps = PageProps & Omit<AppPageProps, 'queryParams'> & {
26+
queryParams: QueryParams
27+
}
2528

2629
export function usePaginatedData(
2730
propDataToFetch: string | string[],
2831
initialFilters: PrimeVueDataFilters = {},
2932
initialRows: number = 20
3033
) {
31-
const urlParams = ref<PaginatedFilteredSortedQueryParams>({});
34+
const page = usePage<InertiaPageProps>();
3235
const processing = ref<boolean>(false);
3336
const filters = ref<PrimeVueDataFilters>(structuredClone(toRaw(initialFilters)));
3437
const sorting = ref<SortState>({
@@ -43,9 +46,10 @@ export function usePaginatedData(
4346
const firstDatasetIndex = computed(() => {
4447
return (pagination.value.page - 1) * pagination.value.rows;
4548
});
49+
4650
const filteredOrSorted = computed(() => {
47-
const paramsFilters = urlParams.value?.filters || {};
48-
const sortField = urlParams.value?.sortField || null;
51+
const paramsFilters = page.props.queryParams?.filters || {};
52+
const sortField = page.props.queryParams?.sortField || null;
4953
const isFiltering = Object.values(paramsFilters).some(
5054
(filter) => filter.value !== null && filter.value !== ''
5155
);
@@ -58,21 +62,6 @@ export function usePaginatedData(
5862
filterCallback();
5963
}, 300);
6064

61-
function setUrlParams(): void {
62-
const queryString = window.location.search;
63-
const params = qs.parse(queryString, {
64-
ignoreQueryPrefix: true,
65-
strictNullHandling: true,
66-
decoder: function (str, defaultDecoder) {
67-
// set empty string values to null to match Laravel backend behavior
68-
const value = defaultDecoder(str);
69-
return value === '' ? null : value;
70-
},
71-
}) as PaginatedFilteredSortedQueryParams;
72-
73-
urlParams.value = { ...params };
74-
}
75-
7665
function scrollToTop(): void {
7766
window.scrollTo({
7867
top: 0,
@@ -85,7 +74,6 @@ export function usePaginatedData(
8574

8675
return new Promise((resolve, reject) => {
8776
processing.value = true;
88-
8977
router.visit(window.location.pathname, {
9078
method: 'get',
9179
data: {
@@ -98,7 +86,9 @@ export function usePaginatedData(
9886
preserveUrl: false,
9987
showProgress: true,
10088
replace: true,
101-
only: Array.isArray(propDataToFetch) ? propDataToFetch : [propDataToFetch],
89+
only: Array.isArray(propDataToFetch)
90+
? [...propDataToFetch, 'queryParams']
91+
: [propDataToFetch, 'queryParams'],
10292
onSuccess: (page) => {
10393
onSuccess?.(page);
10494
resolve(page);
@@ -108,7 +98,6 @@ export function usePaginatedData(
10898
reject(errors);
10999
},
110100
onFinish: () => {
111-
setUrlParams();
112101
processing.value = false;
113102
onFinish?.();
114103
},
@@ -122,7 +111,6 @@ export function usePaginatedData(
122111
} else {
123112
pagination.value.page = event.page + 1;
124113
}
125-
126114
pagination.value.rows = event.rows;
127115

128116
return fetchData({
@@ -134,8 +122,8 @@ export function usePaginatedData(
134122

135123
function filter(options: InertiaRouterFetchCallbacks = {}): Promise<Page<PageProps>> {
136124
const { onFinish: onFinishCallback, onSuccess, onError } = options;
137-
138125
pagination.value.page = 1;
126+
139127
return fetchData({
140128
onSuccess,
141129
onError,
@@ -162,22 +150,23 @@ export function usePaginatedData(
162150

163151
return new Promise((resolve, reject) => {
164152
processing.value = true;
165-
166153
router.visit(window.location.pathname, {
167154
method: 'get',
168155
preserveUrl: false,
169156
showProgress: true,
170157
replace: true,
171-
only: Array.isArray(propDataToFetch) ? propDataToFetch : [propDataToFetch],
172-
onSuccess(page) {
158+
only: Array.isArray(propDataToFetch)
159+
? [...propDataToFetch, 'queryParams']
160+
: [propDataToFetch, 'queryParams'],
161+
onSuccess: (page) => {
173162
onSuccess?.(page);
174163
resolve(page);
175164
},
176-
onError(errors) {
165+
onError: (errors) => {
177166
onError?.(errors);
178167
reject(errors);
179168
},
180-
onFinish() {
169+
onFinish: () => {
181170
processing.value = false;
182171
onFinish?.();
183172
},
@@ -188,19 +177,17 @@ export function usePaginatedData(
188177
function parseUrlFilterValues(): void {
189178
Object.keys(filters.value).forEach((key) => {
190179
const filter = filters.value[key];
191-
192180
if (!filter?.value || !filter?.matchMode) {
193181
return;
194182
}
195-
196-
if (
197-
filter.matchMode == FilterMatchMode.DATE_IS ||
198-
filter.matchMode == FilterMatchMode.DATE_IS_NOT ||
199-
filter.matchMode == FilterMatchMode.DATE_BEFORE ||
200-
filter.matchMode == FilterMatchMode.DATE_AFTER
201-
) {
183+
if ([
184+
FilterMatchMode.DATE_IS,
185+
FilterMatchMode.DATE_IS_NOT,
186+
FilterMatchMode.DATE_BEFORE,
187+
FilterMatchMode.DATE_AFTER,
188+
].includes(filter.matchMode)) {
202189
filters.value[key].value = new Date(filter.value as string);
203-
} else if (filter.matchMode == FilterMatchMode.BETWEEN) {
190+
} else if (filter.matchMode === FilterMatchMode.BETWEEN) {
204191
filter.value.forEach((value: any, index: number) => {
205192
if (typeof value === 'string') {
206193
filter.value[index] = new Date(value);
@@ -214,15 +201,14 @@ export function usePaginatedData(
214201
filters.value[key].value = Number(filter.value);
215202
} else if (
216203
Array.isArray(filter.value) ||
217-
filter.matchMode == FilterMatchMode.IN
204+
filter.matchMode === FilterMatchMode.IN
218205
) {
219206
if (filter.value.length === 0) {
220207
// empty arrays cause filtering issues, set to null instead
221208
filters.value[key].value = null;
222209
} else {
223210
// Unique array values
224211
const unique = [...new Set(filter.value)];
225-
226212
filter.value = unique;
227213
filter.value.forEach((value: any, index: number) => {
228214
if (typeof value === 'string' && !isNaN(Number(value))) {
@@ -234,34 +220,29 @@ export function usePaginatedData(
234220
});
235221
}
236222

237-
function parseUrlParams(urlParamsObj: PaginatedFilteredSortedQueryParams): void {
223+
function parseUrlParams(): void {
224+
const queryParams = page.props.queryParams || {};
238225
filters.value = {
239226
...structuredClone(toRaw(initialFilters)),
240-
...urlParamsObj?.filters,
227+
...queryParams.filters,
241228
};
242-
243229
parseUrlFilterValues();
244-
245-
if (urlParamsObj?.sortField) {
246-
sorting.value.field = urlParamsObj.sortField;
230+
if (queryParams.sortField) {
231+
sorting.value.field = queryParams.sortField;
247232
}
248-
249-
if (urlParamsObj?.sortOrder) {
250-
sorting.value.order = parseInt(urlParamsObj.sortOrder);
233+
if (queryParams.sortOrder) {
234+
sorting.value.order = parseInt(queryParams.sortOrder);
251235
}
252-
253-
if (urlParamsObj?.page) {
254-
pagination.value.page = parseInt(urlParamsObj.page);
236+
if (queryParams.page) {
237+
pagination.value.page = parseInt(queryParams.page);
255238
}
256-
257-
if (urlParamsObj?.rows) {
258-
pagination.value.rows = parseInt(urlParamsObj.rows);
239+
if (queryParams.rows) {
240+
pagination.value.rows = parseInt(queryParams.rows);
259241
}
260242
}
261243

262244
onMounted(() => {
263-
setUrlParams();
264-
parseUrlParams(urlParams.value);
245+
parseUrlParams();
265246
});
266247

267248
return {

resources/js/types/global.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { PageProps as InertiaPageProps } from '@inertiajs/core';
22
import { AxiosInstance } from 'axios';
33
import { route as ziggyRoute } from 'ziggy-js';
4-
import { PageProps as AppPageProps } from './';
4+
import { AppPageProps } from './';
55

66
declare global {
77
interface Window {

resources/js/types/index.d.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
11
import type { DataTableFilterMetaData } from 'primevue';
2-
import type { Page, PageProps, Errors } from '@inertiajs/core';
2+
import type { Page, Errors } from '@inertiajs/core';
33
import type { MenuItem as PrimeVueMenuItem } from 'primevue/menuitem';
44
import type { LucideIcon } from 'lucide-vue-next';
5+
import type { Config } from 'ziggy-js';
56

67
export interface User {
78
id: number;
89
name: string;
910
email: string;
10-
email_verified_at?: string;
11+
email_verified_at: string | null;
1112
}
1213

1314
export interface AuthProps {
15+
user: User | null;
1416
isAdmin?: boolean;
15-
user?: User;
1617
}
1718

18-
export type PageProps<
19-
T extends Record<string, unknown> = Record<string, unknown>
20-
> = T & {
19+
export interface FlashProps {
20+
success?: string | null;
21+
info?: string | null;
22+
warn?: string | null;
23+
error?: string | null;
24+
message?: string | null;
25+
}
26+
27+
export type AppPageProps<T extends Record<string, unknown> = Record<string, unknown>> = T & {
28+
colorScheme: 'auto' | 'light' | 'dark';
29+
ziggy: Config & { location: string };
2130
auth: AuthProps;
31+
flash: FlashProps;
32+
queryParams: Record<string, string | string[]>;
2233
};
2334

2435
export type PrimeVueDataFilters = {

0 commit comments

Comments
 (0)