Typing
This commit is contained in:
@@ -1,22 +1,29 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import { Flip, toast } from 'react-toastify';
|
||||
|
||||
const url = `${import.meta.env.PROD ? import.meta.env.VITE_DOMAIN_PROD : import.meta.env.VITE_DOMAIN_DEV}/${import.meta.env.VITE_BASE_URL}`;
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': '*',
|
||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
||||
'Access-Control-Allow-Credentials': true,
|
||||
'Sec-Fetch-Mode': 'no-cors',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
};
|
||||
const callEndpoint = async (url: string) => {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`${response.status} ${response.statusText}`);
|
||||
}
|
||||
return await response.json();
|
||||
};
|
||||
export function useQueryAPI({ endpoint }: { endpoint: string }) {
|
||||
const callEndpoint = async (endpoint: string) => {
|
||||
const options: object = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': '*',
|
||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
||||
'Access-Control-Allow-Credentials': true,
|
||||
'Sec-Fetch-Mode': 'no-cors',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
},
|
||||
headers: headers,
|
||||
};
|
||||
|
||||
const response = await fetch(`${url}/${endpoint}`, options);
|
||||
@@ -44,15 +51,7 @@ export function useMutationAPI() {
|
||||
) => {
|
||||
const options: any = {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': '*',
|
||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
||||
'Access-Control-Allow-Credentials': true,
|
||||
'Sec-Fetch-Mode': 'no-cors',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
},
|
||||
headers: headers,
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
notify();
|
||||
@@ -124,7 +123,7 @@ export function useMutationAPI() {
|
||||
endpoint: string;
|
||||
body: object | undefined | null;
|
||||
}) => callEndpoint(method, endpoint, body),
|
||||
onMutate: ({ method, endpoint }) => {
|
||||
onMutate: ({ endpoint }) => {
|
||||
queryClient.refetchQueries({
|
||||
queryKey: ['GET', endpoint],
|
||||
});
|
||||
@@ -135,7 +134,7 @@ export function useMutationAPI() {
|
||||
endpoint === 'api/applicationOrder' &&
|
||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/applicationOrder'] });
|
||||
},
|
||||
onSuccess: (data, { method, endpoint }) => {
|
||||
onSuccess: (_, { endpoint }) => {
|
||||
queryClient.refetchQueries({
|
||||
queryKey: ['GET', endpoint],
|
||||
});
|
||||
@@ -180,17 +179,10 @@ export function useWeatherAPI({
|
||||
} else if (endpoint === 'stations') {
|
||||
url = `https://api.weather.gov/gridpoints/${office}/${x},${y}/stations`;
|
||||
}
|
||||
const callEndpoint = async () => {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`${response.status} ${response.statusText}`);
|
||||
}
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['GET', url],
|
||||
queryFn: () => callEndpoint(),
|
||||
queryFn: () => callEndpoint(url),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -200,16 +192,10 @@ export function useSunStateAPI({ lat, lon }: { lat: number; lon: number }) {
|
||||
date.setDate(date.getDate() + 1);
|
||||
const tomorrow = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
|
||||
const url = `https://api.sunrisesunset.io/json?lat=${lat}&lng=${lon}&date_start=${today}&date_end=${tomorrow}`;
|
||||
const callEndpoint = async () => {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`${response.status} ${response.statusText}`);
|
||||
}
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['GET', url],
|
||||
queryFn: () => callEndpoint(),
|
||||
queryFn: () => callEndpoint(url),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -238,15 +224,7 @@ export function useFileUploadAPI() {
|
||||
) => {
|
||||
const options = {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': '*',
|
||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
||||
'Access-Control-Allow-Credentials': true,
|
||||
'Sec-Fetch-Mode': 'no-cors',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
},
|
||||
headers: headers,
|
||||
body: body ?? undefined,
|
||||
};
|
||||
const response = await fetch(url, options as unknown as Body);
|
||||
@@ -300,115 +278,3 @@ export function useFileUploadAPI() {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useFetchAllRecordsAPI({ endpoint }: { endpoint: string }) {
|
||||
const pageSize = 500;
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const fetchPage = async (page: number, retryCount = 0): Promise<any> => {
|
||||
// Start building the URL
|
||||
const urlObject = new URL(`${url}/${endpoint}`);
|
||||
|
||||
// Check and append custom query parameters from the endpoint
|
||||
const customParams = new URLSearchParams(endpoint.split('?')[1]);
|
||||
for (const [key, value] of customParams) {
|
||||
if (!urlObject.searchParams.has(key)) {
|
||||
urlObject.searchParams.append(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Add 'page' and 'size' parameters
|
||||
urlObject.searchParams.set('page', page.toString()); // Use 'set' to ensure uniqueness
|
||||
urlObject.searchParams.set('size', pageSize.toString());
|
||||
|
||||
const options: any = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': '*',
|
||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
||||
'Access-Control-Allow-Credentials': true,
|
||||
'Sec-Fetch-Mode': 'no-cors',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(url.toString(), options);
|
||||
|
||||
if (!response.ok) {
|
||||
// If the response is not ok and status is 401 (not authorized), reload the page
|
||||
if (response.status === 401) {
|
||||
window.location.reload();
|
||||
}
|
||||
throw new Error(
|
||||
`Error fetching page ${page}: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
return response.json();
|
||||
} catch (err) {
|
||||
if (retryCount < 3) {
|
||||
// Retry up to 3 times with a random delay
|
||||
const delay = Math.floor(Math.random() * 3000) + 1000; // Random delay between 1 to 3 seconds
|
||||
console.error(
|
||||
`Retrying page ${page}, attempt ${retryCount + 1} after ${delay} ms`,
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
return fetchPage(page, retryCount + 1);
|
||||
}
|
||||
console.error(`Error fetching page ${page} after 3 retries:`, err);
|
||||
throw err; // Re-throw the error to handle it in the calling function
|
||||
}
|
||||
};
|
||||
|
||||
const callEndpoint = async () => {
|
||||
try {
|
||||
// Fetch the first page to get the total number of items and pages
|
||||
const firstPageData = await fetchPage(1);
|
||||
// If the first page doesn't have a 'pages' property, return the data as-is
|
||||
if (firstPageData?.pages === undefined) {
|
||||
return firstPageData;
|
||||
}
|
||||
if (firstPageData?.pages === 1) {
|
||||
return firstPageData.items;
|
||||
}
|
||||
|
||||
let totalPages = firstPageData.pages;
|
||||
const allItems = [...firstPageData.items];
|
||||
// Fetch each page sequentially
|
||||
for (let page = 2; page <= totalPages; page++) {
|
||||
try {
|
||||
const pageData = await fetchPage(page);
|
||||
allItems.push(...pageData.items);
|
||||
|
||||
// Check and update the totalPages if it has increased
|
||||
if (pageData.pages > totalPages) {
|
||||
totalPages = pageData.pages;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Final error fetching page ${page}:`, err);
|
||||
// Continue to the next page even if the current page fails
|
||||
}
|
||||
}
|
||||
|
||||
return allItems;
|
||||
} catch (error) {
|
||||
// Handling errors in fetching the first page
|
||||
console.error('Error fetching the first page:', error);
|
||||
return []; // Return empty array on error
|
||||
}
|
||||
};
|
||||
|
||||
const invalidate = useCallback(() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['GET', endpoint] });
|
||||
}, [queryClient, endpoint]);
|
||||
|
||||
return {
|
||||
...useQuery({
|
||||
queryKey: ['GET', endpoint],
|
||||
queryFn: callEndpoint,
|
||||
}),
|
||||
invalidate,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ export function useCommonHooks() {
|
||||
const { mutateAsync } = useMutationAPI();
|
||||
const isMobile = window.matchMedia('(max-width: 600px)').matches;
|
||||
const [theme, setTheme] = useAtom(appTheme);
|
||||
const [themeName, setThemeName] = useLocalStorage<any>({
|
||||
const [themeName, setThemeName] = useLocalStorage<string>({
|
||||
key: 'theme',
|
||||
defaultValue: 'blackboard',
|
||||
});
|
||||
const [appFilter, setAppFilter] = useLocalStorage<[any]>({
|
||||
const [appFilter, setAppFilter] = useLocalStorage<[string]>({
|
||||
key: 'appFilter',
|
||||
defaultValue: ['All'],
|
||||
});
|
||||
@@ -24,16 +24,16 @@ export function useCommonHooks() {
|
||||
key: 'bookmarkSort',
|
||||
defaultValue: 'A-Z',
|
||||
});
|
||||
const [bookmarkFilter, setBookmarkFilter] = useLocalStorage<[any]>({
|
||||
const [bookmarkFilter, setBookmarkFilter] = useLocalStorage<[string]>({
|
||||
key: 'bookmarkFilter',
|
||||
defaultValue: ['All'],
|
||||
});
|
||||
const [currentTheme, setCurrentTheme] = useLocalStorage<any>({
|
||||
const [currentTheme, setCurrentTheme] = useLocalStorage<string>({
|
||||
key: 'theme',
|
||||
defaultValue: 'blackboard',
|
||||
});
|
||||
|
||||
const [currentThemePlaylist, setCurrentThemePlaylist] = useLocalStorage<any>({
|
||||
const [currentThemePlaylist, setCurrentThemePlaylist] = useLocalStorage<string>({
|
||||
key: 'themePlaylist',
|
||||
defaultValue: 'All',
|
||||
});
|
||||
@@ -80,6 +80,13 @@ export function useCommonHooks() {
|
||||
'i',
|
||||
); // fragment locator
|
||||
|
||||
const reorder = (list: any, startIndex: any, endIndex: any) => {
|
||||
const result = Array.from(list);
|
||||
const [removed]: any = result.splice(startIndex, 1);
|
||||
result.splice(endIndex, 0, removed);
|
||||
return result;
|
||||
};
|
||||
|
||||
const handleThemeChange = (themes: any, save: any) => {
|
||||
const enabled = themes
|
||||
.filter((t: any) => t.randomEnabled)
|
||||
@@ -116,6 +123,7 @@ export function useCommonHooks() {
|
||||
modalStyle,
|
||||
urlPattern,
|
||||
fixDigits,
|
||||
reorder,
|
||||
handleThemeChange,
|
||||
handleDelete,
|
||||
themeName,
|
||||
|
||||
Reference in New Issue
Block a user