109 lines
3.3 KiB
TypeScript
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),
|
|
);
|
|
}
|