mirror of
https://github.com/towfiqi/serpbear
synced 2025-06-26 18:15:54 +00:00
- Replaces useEffet with useMemo & useLayoutEffect where necessary. - Converts some useEffects to separate hooks. - Moves the functions defined within components to utils. - Splits the Keywords renderPosition function to its own component.
176 lines
7.2 KiB
TypeScript
176 lines
7.2 KiB
TypeScript
import toast from 'react-hot-toast';
|
|
import { NextRouter } from 'next/router';
|
|
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
|
|
|
export const fetchKeywords = async (router: NextRouter) => {
|
|
if (!router.query.slug) { return []; }
|
|
const res = await fetch(`${window.location.origin}/api/keywords?domain=${router.query.slug}`, { method: 'GET' });
|
|
return res.json();
|
|
};
|
|
|
|
export function useFetchKeywords(router: NextRouter, setKeywordSPollInterval?:Function, keywordSPollInterval:undefined|number = undefined) {
|
|
const { data: keywordsData, isLoading: keywordsLoading, isError } = useQuery(
|
|
['keywords', router.query.slug],
|
|
() => fetchKeywords(router),
|
|
{
|
|
refetchInterval: keywordSPollInterval,
|
|
onSuccess: (data) => {
|
|
// If Keywords are Manually Refreshed check if the any of the keywords position are still being fetched
|
|
// If yes, then refecth the keywords every 5 seconds until all the keywords position is updated by the server
|
|
if (data.keywords && data.keywords.length > 0 && setKeywordSPollInterval) {
|
|
const hasRefreshingKeyword = data.keywords.some((x:KeywordType) => x.updating);
|
|
if (hasRefreshingKeyword) {
|
|
setKeywordSPollInterval(5000);
|
|
} else {
|
|
if (keywordSPollInterval) {
|
|
toast('Keywords Refreshed!', { icon: '✔️' });
|
|
}
|
|
setKeywordSPollInterval(undefined);
|
|
}
|
|
}
|
|
},
|
|
},
|
|
);
|
|
return { keywordsData, keywordsLoading, isError };
|
|
}
|
|
|
|
export function useAddKeywords(onSuccess:Function) {
|
|
const queryClient = useQueryClient();
|
|
return useMutation(async (keywords:KeywordAddPayload[]) => {
|
|
const headers = new Headers({ 'Content-Type': 'application/json', Accept: 'application/json' });
|
|
const fetchOpts = { method: 'POST', headers, body: JSON.stringify({ keywords }) };
|
|
const res = await fetch(`${window.location.origin}/api/keywords`, fetchOpts);
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async () => {
|
|
console.log('Keywords Added!!!');
|
|
toast('Keywords Added Successfully!', { icon: '✔️' });
|
|
onSuccess();
|
|
queryClient.invalidateQueries(['keywords']);
|
|
},
|
|
onError: () => {
|
|
console.log('Error Adding New Keywords!!!');
|
|
toast('Error Adding New Keywords', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteKeywords(onSuccess:Function) {
|
|
const queryClient = useQueryClient();
|
|
return useMutation(async (keywordIDs:number[]) => {
|
|
const keywordIds = keywordIDs.join(',');
|
|
const res = await fetch(`${window.location.origin}/api/keywords?id=${keywordIds}`, { method: 'DELETE' });
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async () => {
|
|
console.log('Removed Keyword!!!');
|
|
onSuccess();
|
|
toast('Keywords Removed Successfully!', { icon: '✔️' });
|
|
queryClient.invalidateQueries(['keywords']);
|
|
},
|
|
onError: () => {
|
|
console.log('Error Removing Keyword!!!');
|
|
toast('Error Removing the Keywords', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useFavKeywords(onSuccess:Function) {
|
|
const queryClient = useQueryClient();
|
|
return useMutation(async ({ keywordID, sticky }:{keywordID:number, sticky:boolean}) => {
|
|
const headers = new Headers({ 'Content-Type': 'application/json', Accept: 'application/json' });
|
|
const fetchOpts = { method: 'PUT', headers, body: JSON.stringify({ sticky }) };
|
|
const res = await fetch(`${window.location.origin}/api/keywords?id=${keywordID}`, fetchOpts);
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async (data) => {
|
|
onSuccess();
|
|
const isSticky = data.keywords[0] && data.keywords[0].sticky;
|
|
toast(isSticky ? 'Keywords Made Favorite!' : 'Keywords Unfavorited!', { icon: '✔️' });
|
|
queryClient.invalidateQueries(['keywords']);
|
|
},
|
|
onError: () => {
|
|
console.log('Error Changing Favorite Status!!!');
|
|
toast('Error Changing Favorite Status.', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdateKeywordTags(onSuccess:Function) {
|
|
const queryClient = useQueryClient();
|
|
return useMutation(async ({ tags }:{tags:{ [ID:number]: string[] }}) => {
|
|
const keywordIds = Object.keys(tags).join(',');
|
|
const headers = new Headers({ 'Content-Type': 'application/json', Accept: 'application/json' });
|
|
const fetchOpts = { method: 'PUT', headers, body: JSON.stringify({ tags }) };
|
|
const res = await fetch(`${window.location.origin}/api/keywords?id=${keywordIds}`, fetchOpts);
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async () => {
|
|
onSuccess();
|
|
toast('Keyword Tags Updated!', { icon: '✔️' });
|
|
queryClient.invalidateQueries(['keywords']);
|
|
},
|
|
onError: () => {
|
|
console.log('Error Updating Keyword Tags!!!');
|
|
toast('Error Updating Keyword Tags.', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRefreshKeywords(onSuccess:Function) {
|
|
const queryClient = useQueryClient();
|
|
return useMutation(async ({ ids = [], domain = '' } : {ids?: number[], domain?: string}) => {
|
|
const keywordIds = ids.join(',');
|
|
console.log(keywordIds);
|
|
const query = ids.length === 0 && domain ? `?id=all&domain=${domain}` : `?id=${keywordIds}`;
|
|
const res = await fetch(`${window.location.origin}/api/refresh${query}`, { method: 'POST' });
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async () => {
|
|
console.log('Keywords Added to Refresh Queue!!!');
|
|
onSuccess();
|
|
toast('Keywords Added to Refresh Queue', { icon: '🔄' });
|
|
queryClient.invalidateQueries(['keywords']);
|
|
},
|
|
onError: () => {
|
|
console.log('Error Refreshing Keywords!!!');
|
|
toast('Error Refreshing Keywords.', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useFetchSingleKeyword(keywordID:number) {
|
|
return useQuery(['keyword', keywordID], async () => {
|
|
try {
|
|
const fetchURL = `${window.location.origin}/api/keyword?id=${keywordID}`;
|
|
const res = await fetch(fetchURL, { method: 'GET' }).then((result) => result.json());
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return { history: res.keyword.history || [], searchResult: res.keyword.lastResult || [] };
|
|
} catch (error) {
|
|
throw new Error('Error Loading Keyword Details');
|
|
}
|
|
}, {
|
|
onError: () => {
|
|
console.log('Error Loading Keyword Data!!!');
|
|
toast('Error Loading Keyword Details.', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|