"use client" import { useMutation, useQueryClient } from "@tanstack/react-query" import { createSupabaseBrowserClient } from "@/lib/supabase/client" import { queryKeys } from "./query-keys" import { MUTATION_KEYS } from "@/lib/query-client" import type { TimelineEntry } from "@/lib/types/timeline" import type { InfiniteData } from "@tanstack/react-query" export function useToggleEntryReadState() { const supabaseClient = createSupabaseBrowserClient() const queryClient = useQueryClient() return useMutation({ mutationKey: MUTATION_KEYS.toggleEntryReadState, mutationFn: async ({ entryIdentifier, isRead, }: { entryIdentifier: string isRead: boolean }) => { const { data: { user }, } = await supabaseClient.auth.getUser() if (!user) throw new Error("not authenticated") const { error } = await supabaseClient .from("user_entry_states") .upsert( { user_id: user.id, entry_id: entryIdentifier, read: isRead, read_at: isRead ? new Date().toISOString() : null, }, { onConflict: "user_id,entry_id" } ) if (error) throw error }, onMutate: async ({ entryIdentifier, isRead }) => { await queryClient.cancelQueries({ queryKey: queryKeys.timeline.all }) const previousTimeline = queryClient.getQueriesData< InfiniteData >({ queryKey: queryKeys.timeline.all }) queryClient.setQueriesData>( { queryKey: queryKeys.timeline.all }, (existingData) => { if (!existingData) return existingData return { ...existingData, pages: existingData.pages.map((page) => page.map((entry) => entry.entryIdentifier === entryIdentifier ? { ...entry, isRead } : entry ) ), } } ) return { previousTimeline } }, onError: (_error, _variables, context) => { if (context?.previousTimeline) { for (const [queryKey, queryData] of context.previousTimeline) { queryClient.setQueryData(queryKey, queryData) } } }, onSettled: (_data, _error, variables) => { queryClient.invalidateQueries({ queryKey: queryKeys.timeline.all }) queryClient.invalidateQueries({ queryKey: queryKeys.unreadCounts.all }) queryClient.invalidateQueries({ queryKey: queryKeys.savedEntries.all }) queryClient.invalidateQueries({ queryKey: queryKeys.entryState.single(variables.entryIdentifier), }) }, }) } export function useToggleEntrySavedState() { const supabaseClient = createSupabaseBrowserClient() const queryClient = useQueryClient() return useMutation({ mutationKey: MUTATION_KEYS.toggleEntrySavedState, mutationFn: async ({ entryIdentifier, isSaved, }: { entryIdentifier: string isSaved: boolean }) => { const { data: { user }, } = await supabaseClient.auth.getUser() if (!user) throw new Error("not authenticated") const { error } = await supabaseClient .from("user_entry_states") .upsert( { user_id: user.id, entry_id: entryIdentifier, saved: isSaved, saved_at: isSaved ? new Date().toISOString() : null, }, { onConflict: "user_id,entry_id" } ) if (error) throw error }, onMutate: async ({ entryIdentifier, isSaved }) => { await queryClient.cancelQueries({ queryKey: queryKeys.timeline.all }) const previousTimeline = queryClient.getQueriesData< InfiniteData >({ queryKey: queryKeys.timeline.all }) queryClient.setQueriesData>( { queryKey: queryKeys.timeline.all }, (existingData) => { if (!existingData) return existingData return { ...existingData, pages: existingData.pages.map((page) => page.map((entry) => entry.entryIdentifier === entryIdentifier ? { ...entry, isSaved } : entry ) ), } } ) return { previousTimeline } }, onError: (_error, _variables, context) => { if (context?.previousTimeline) { for (const [queryKey, queryData] of context.previousTimeline) { queryClient.setQueryData(queryKey, queryData) } } }, onSettled: (_data, _error, variables) => { queryClient.invalidateQueries({ queryKey: queryKeys.timeline.all }) queryClient.invalidateQueries({ queryKey: queryKeys.savedEntries.all }) queryClient.invalidateQueries({ queryKey: queryKeys.entryState.single(variables.entryIdentifier), }) }, }) }