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( accountId: string, mutationFn: (variables: TVariables) => Promise, ) { 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(accountId, () => runBrowsingSimulation(accountId)); } export function usePauseGrowthMutation(accountId: string) { return useGrowthMutation(accountId, (reason?: string) => pauseGrowth(accountId, reason)); } export function useResumeGrowthMutation(accountId: string) { return useGrowthMutation(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), ); }