Files
RedditBot/apps/dashboard/src/features/growth/growth-queries.ts
T

109 lines
3.3 KiB
TypeScript

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import type {
GrowthAccountDetail,
BrowsingSettingsUpdateRequest,
GrowthSettingsUpdateRequest,
GrowthSubredditCreateRequest,
GrowthSubredditUpdateRequest,
} from '../../../../../packages/api-contracts/src/index.js';
import {
addGrowthSubreddit,
fetchGrowthAccount,
fetchGrowthOverview,
pauseGrowth,
removeGrowthSubreddit,
resumeGrowth,
runBrowsingSimulation,
updateGrowthSettings,
updateBrowsingSettings,
updateGrowthSubreddit,
} from './growth-api.js';
export const growthOverviewQueryKey = ['dashboard', 'growth'] as const;
export const growthAccountQueryKey = (accountId: string) =>
['dashboard', 'growth', accountId] as const;
export function useGrowthOverviewQuery() {
return useQuery({
queryKey: growthOverviewQueryKey,
queryFn: fetchGrowthOverview,
// Growth moves on the order of hours, so a slow refresh is plenty.
refetchInterval: 60_000,
});
}
export function useGrowthAccountQuery(accountId: string | null) {
return useQuery({
queryKey: growthAccountQueryKey(accountId ?? ''),
queryFn: () => fetchGrowthAccount(accountId as string),
enabled: accountId !== null,
refetchInterval: 60_000,
});
}
/**
* Every mutation returns the whole updated account, so the detail cache is
* written directly and the overview is invalidated. HTTP stays authoritative.
*/
function useGrowthMutation<TVariables>(
accountId: string,
mutationFn: (variables: TVariables) => Promise<GrowthAccountDetail>,
) {
const client = useQueryClient();
return useMutation({
mutationFn,
onSuccess: (account) => {
client.setQueryData(growthAccountQueryKey(accountId), account);
void client.invalidateQueries({ queryKey: growthOverviewQueryKey });
},
});
}
export function useUpdateGrowthSettingsMutation(accountId: string) {
return useGrowthMutation(
accountId,
(update: GrowthSettingsUpdateRequest) => updateGrowthSettings(accountId, update),
);
}
export function useUpdateBrowsingSettingsMutation(accountId: string) {
return useGrowthMutation(
accountId,
(update: BrowsingSettingsUpdateRequest) => updateBrowsingSettings(accountId, update),
);
}
export function useRunBrowsingSimulationMutation(accountId: string) {
return useGrowthMutation<void>(accountId, () => runBrowsingSimulation(accountId));
}
export function usePauseGrowthMutation(accountId: string) {
return useGrowthMutation(accountId, (reason?: string) => pauseGrowth(accountId, reason));
}
export function useResumeGrowthMutation(accountId: string) {
return useGrowthMutation<void>(accountId, () => resumeGrowth(accountId));
}
export function useAddGrowthSubredditMutation(accountId: string) {
return useGrowthMutation(
accountId,
(request: GrowthSubredditCreateRequest) => addGrowthSubreddit(accountId, request),
);
}
export function useUpdateGrowthSubredditMutation(accountId: string) {
return useGrowthMutation(
accountId,
({ subreddit, update }: { subreddit: string; update: GrowthSubredditUpdateRequest }) =>
updateGrowthSubreddit(accountId, subreddit, update),
);
}
export function useRemoveGrowthSubredditMutation(accountId: string) {
return useGrowthMutation(
accountId,
(subreddit: string) => removeGrowthSubreddit(accountId, subreddit),
);
}