mirror of
https://github.com/towfiqi/serpbear
synced 2025-06-26 18:15:54 +00:00
- Adds a volume field in the keyword table. - Adds a button in the Adwords Integration screen to update all the tracked keywords. - When a new keyword is added, the volume data is automatically fetched. - Adds ability to sort keywords based on search volume.
129 lines
5.5 KiB
TypeScript
129 lines
5.5 KiB
TypeScript
import { NextRouter } from 'next/router';
|
|
import toast from 'react-hot-toast';
|
|
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
|
|
|
export function useTestAdwordsIntegration(onSuccess?: Function) {
|
|
return useMutation(async (payload:{developer_token:string, account_id:string}) => {
|
|
const headers = new Headers({ 'Content-Type': 'application/json', Accept: 'application/json' });
|
|
const fetchOpts = { method: 'POST', headers, body: JSON.stringify({ ...payload }) };
|
|
const res = await fetch(`${window.location.origin}/api/adwords`, fetchOpts);
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async (data) => {
|
|
console.log('Ideas Added:', data);
|
|
toast('Google Adwords has been integrated successfully!', { icon: '✔️' });
|
|
if (onSuccess) {
|
|
onSuccess(false);
|
|
}
|
|
},
|
|
onError: (error) => {
|
|
console.log('Error Loading Keyword Ideas!!!', error);
|
|
toast('Failed to connect to Google Adwords. Please make sure you have provided the correct API info.', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|
|
|
|
export async function fetchAdwordsKeywordIdeas(router: NextRouter, domainSlug: string) {
|
|
// if (!router.query.slug) { throw new Error('Invalid Domain Name'); }
|
|
const res = await fetch(`${window.location.origin}/api/ideas?domain=${domainSlug}`, { method: 'GET' });
|
|
if (res.status >= 400 && res.status < 600) {
|
|
if (res.status === 401) {
|
|
console.log('Unauthorized!!');
|
|
router.push('/login');
|
|
}
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}
|
|
|
|
export function useFetchKeywordIdeas(router: NextRouter, adwordsConnected = false) {
|
|
const isResearch = router.pathname === '/research';
|
|
const domainSlug = isResearch ? 'research' : (router.query.slug as string);
|
|
const enabled = !!(adwordsConnected && domainSlug);
|
|
return useQuery(`keywordIdeas-${domainSlug}`, () => domainSlug && fetchAdwordsKeywordIdeas(router, domainSlug), { enabled, retry: false });
|
|
}
|
|
|
|
export function useMutateKeywordIdeas(router:NextRouter, onSuccess?: Function) {
|
|
const queryClient = useQueryClient();
|
|
const domainSlug = router.pathname === '/research' ? 'research' : router.query.slug as string;
|
|
return useMutation(async (data:Record<string, any>) => {
|
|
const headers = new Headers({ 'Content-Type': 'application/json', Accept: 'application/json' });
|
|
const fetchOpts = { method: 'POST', headers, body: JSON.stringify({ ...data }) };
|
|
const res = await fetch(`${window.location.origin}/api/ideas`, fetchOpts);
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async (data) => {
|
|
console.log('Ideas Added:', data);
|
|
toast('Keyword Ideas Loaded Successfully!', { icon: '✔️' });
|
|
if (onSuccess) {
|
|
onSuccess(false);
|
|
}
|
|
queryClient.invalidateQueries([`keywordIdeas-${domainSlug}`]);
|
|
},
|
|
onError: (error) => {
|
|
console.log('Error Loading Keyword Ideas!!!', error);
|
|
toast('Error Loading Keyword Ideas', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useMutateFavKeywordIdeas(router:NextRouter, onSuccess?: Function) {
|
|
const queryClient = useQueryClient();
|
|
const domainSlug = router.pathname === '/research' ? 'research' : router.query.slug as string;
|
|
return useMutation(async (payload:Record<string, any>) => {
|
|
const headers = new Headers({ 'Content-Type': 'application/json', Accept: 'application/json' });
|
|
const fetchOpts = { method: 'PUT', headers, body: JSON.stringify({ ...payload }) };
|
|
const res = await fetch(`${window.location.origin}/api/ideas`, fetchOpts);
|
|
if (res.status >= 400 && res.status < 600) {
|
|
throw new Error('Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async (data) => {
|
|
console.log('Ideas Added:', data);
|
|
// toast('Keyword Updated!', { icon: '✔️' });
|
|
if (onSuccess) {
|
|
onSuccess(false);
|
|
}
|
|
queryClient.invalidateQueries([`keywordIdeas-${domainSlug}`]);
|
|
},
|
|
onError: (error) => {
|
|
console.log('Error Favorating Keywords', error);
|
|
toast('Error Favorating Keywords', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useMutateKeywordsVolume(onSuccess?: Function) {
|
|
return useMutation(async (data:Record<string, any>) => {
|
|
const headers = new Headers({ 'Content-Type': 'application/json', Accept: 'application/json' });
|
|
const fetchOpts = { method: 'POST', headers, body: JSON.stringify({ ...data }) };
|
|
const res = await fetch(`${window.location.origin}/api/volume`, fetchOpts);
|
|
if (res.status >= 400 && res.status < 600) {
|
|
const errorData = await res.json();
|
|
throw new Error(errorData?.error ? errorData.error : 'Bad response from server');
|
|
}
|
|
return res.json();
|
|
}, {
|
|
onSuccess: async (data) => {
|
|
toast('Keyword Volume Data Loaded Successfully! Reloading Page...', { icon: '✔️' });
|
|
if (onSuccess) {
|
|
onSuccess(false);
|
|
}
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 3000);
|
|
},
|
|
onError: (error) => {
|
|
console.log('Error Loading Keyword Volume Data!!!', error);
|
|
toast('Error Loading Keyword Volume Data', { icon: '⚠️' });
|
|
},
|
|
});
|
|
}
|