137 lines
3.6 KiB
TypeScript
137 lines
3.6 KiB
TypeScript
import { useState, useEffect, useCallback } from "react";
|
|
import { PeopleFormData, PeopleSchema, fetchData } from "./schema";
|
|
import {
|
|
PagePagination,
|
|
RequestParams,
|
|
ResponseMetadata,
|
|
} from "@/components/validations/list/paginations";
|
|
|
|
// Custom hook for pagination and data fetching
|
|
export function usePaginatedData() {
|
|
const [data, setData] = useState<PeopleFormData[]>([]);
|
|
|
|
// Request parameters - these are controlled by the user
|
|
const [requestParams, setRequestParams] = useState<RequestParams>({
|
|
page: 1,
|
|
size: 10,
|
|
orderFields: ["createdAt"],
|
|
orderTypes: ["desc"],
|
|
query: {},
|
|
});
|
|
|
|
// Response metadata - these come from the API
|
|
const [responseMetadata, setResponseMetadata] = useState<ResponseMetadata>({
|
|
totalCount: 0,
|
|
allCount: 0,
|
|
totalPages: 0,
|
|
pageCount: 0,
|
|
});
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<Error | null>(null);
|
|
|
|
const fetchDataFromApi = useCallback(async () => {
|
|
setLoading(true);
|
|
try {
|
|
const result = await fetchData({
|
|
page: requestParams.page,
|
|
size: requestParams.size,
|
|
orderFields: requestParams.orderFields,
|
|
orderTypes: requestParams.orderTypes,
|
|
query: requestParams.query,
|
|
});
|
|
|
|
// Validate data with Zod
|
|
const validatedData = result.data
|
|
.map((item: any) => {
|
|
try {
|
|
return PeopleSchema.parse(item);
|
|
} catch (err) {
|
|
console.error("Validation error for item:", item, err);
|
|
return null;
|
|
}
|
|
})
|
|
.filter(Boolean) as PeopleFormData[];
|
|
|
|
setData(validatedData);
|
|
|
|
// Update response metadata from API response
|
|
setResponseMetadata({
|
|
totalCount: result.pagination.totalCount,
|
|
allCount: result.pagination.allCount,
|
|
totalPages: result.pagination.totalPages,
|
|
pageCount: result.pagination.pageCount,
|
|
});
|
|
|
|
setError(null);
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err : new Error("Unknown error"));
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [
|
|
requestParams.page,
|
|
requestParams.size,
|
|
requestParams.orderFields,
|
|
requestParams.orderTypes,
|
|
requestParams.query,
|
|
]);
|
|
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => {
|
|
fetchDataFromApi();
|
|
}, 300); // Debounce
|
|
|
|
return () => clearTimeout(timer);
|
|
}, [fetchDataFromApi]);
|
|
|
|
const updatePagination = (updates: Partial<RequestParams>) => {
|
|
// Transform query parameters to use __ilike with %value% format
|
|
if (updates.query) {
|
|
const transformedQuery: Record<string, any> = {};
|
|
|
|
Object.entries(updates.query).forEach(([key, value]) => {
|
|
// Only transform string values that aren't already using a special operator
|
|
if (typeof value === 'string' && !key.includes('__')) {
|
|
transformedQuery[`${key}__ilike`] = `%${value}%`;
|
|
} else {
|
|
transformedQuery[key] = value;
|
|
}
|
|
});
|
|
|
|
updates.query = transformedQuery;
|
|
}
|
|
|
|
setRequestParams((prev) => ({
|
|
...prev,
|
|
...updates,
|
|
}));
|
|
};
|
|
|
|
// Create a combined refetch object that includes the setQuery function
|
|
const setQuery = (query: Record<string, string>) => {
|
|
setRequestParams((prev) => ({
|
|
...prev,
|
|
query,
|
|
}));
|
|
};
|
|
|
|
const refetch = Object.assign(fetchDataFromApi, { setQuery });
|
|
|
|
// Combine request params and response metadata for backward compatibility
|
|
const pagination: PagePagination = {
|
|
...requestParams,
|
|
...responseMetadata,
|
|
};
|
|
|
|
return {
|
|
data,
|
|
pagination,
|
|
loading,
|
|
error,
|
|
updatePagination,
|
|
setQuery,
|
|
refetch,
|
|
};
|
|
}
|