()
| 17 | } |
| 18 | |
| 19 | export function useUpdatePreference() { |
| 20 | const [isPending, setIsPending] = useState(false) |
| 21 | |
| 22 | const mutate = useCallback(async (params: UpdatePreferenceParams) => { |
| 23 | const queryKey = subscriptionQueryKeys.current() |
| 24 | |
| 25 | // Snapshot the previous value for rollback |
| 26 | const previousData = getActivityQueryData<SubscriptionResponse>(queryKey) |
| 27 | |
| 28 | // Optimistically update to the new value |
| 29 | if (previousData && params.fallbackToALaCarte !== undefined) { |
| 30 | setActivityQueryData<SubscriptionResponse>(queryKey, { |
| 31 | ...previousData, |
| 32 | fallbackToALaCarte: params.fallbackToALaCarte, |
| 33 | }) |
| 34 | } |
| 35 | |
| 36 | setIsPending(true) |
| 37 | |
| 38 | try { |
| 39 | const client = getApiClient() |
| 40 | const response = await client.patch<{ success: boolean; error?: string }>( |
| 41 | '/api/user/preferences', |
| 42 | params as Record<string, unknown>, |
| 43 | { includeCookie: true }, |
| 44 | ) |
| 45 | |
| 46 | if (!response.ok) { |
| 47 | const errorMessage = response.error || 'Failed to update preference' |
| 48 | throw new Error(errorMessage) |
| 49 | } |
| 50 | |
| 51 | // Invalidate to refetch fresh data from server |
| 52 | invalidateActivityQuery(queryKey) |
| 53 | } catch (err) { |
| 54 | // Rollback to previous value on error |
| 55 | if (previousData) { |
| 56 | setActivityQueryData(queryKey, previousData) |
| 57 | } |
| 58 | logger.error({ err }, 'Failed to update preference') |
| 59 | showClipboardMessage('Failed to update preference', { durationMs: 3000 }) |
| 60 | } finally { |
| 61 | setIsPending(false) |
| 62 | } |
| 63 | }, []) |
| 64 | |
| 65 | return { mutate, isPending } |
| 66 | } |
no test coverage detected