All files / src/hooks useFavorites.ts

41.93% Statements 13/31
50% Branches 2/4
45.45% Functions 5/11
42.85% Lines 12/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62                              22x   22x 10x 7x 7x     3x   3x       22x                                           22x       22x 1x     22x    
import { useState, useEffect, useCallback } from 'react'
import { toast } from 'sonner'
import { api, type Profile, type RecipeDetail } from '../api/client'
 
interface UseFavoritesReturn {
  favoriteRecipeIds: Set<number>
  toggleFavorite: (recipe: RecipeDetail) => Promise<void>
  isFavorite: (recipeId: number) => boolean
  clearFavorites: () => void
}
 
/**
 * Manages favorite recipe state: loading, toggling, and checking favorites.
 */
export function useFavorites(profile: Profile | null): UseFavoritesReturn {
  const [favoriteRecipeIds, setFavoriteRecipeIds] = useState<Set<number>>(new Set())
 
  useEffect(() => {
    if (!profile) {
      Promise.resolve().then(() => setFavoriteRecipeIds(new Set()))
      return
    }
 
    api.favorites
      .list()
      .then((favorites) => setFavoriteRecipeIds(new Set(favorites.map((f) => f.recipe.id))))
      .catch((error) => console.error('Failed to load favorites:', error))
  }, [profile])
 
  const toggleFavorite = useCallback(async (recipe: RecipeDetail) => {
    const isFav = favoriteRecipeIds.has(recipe.id)
    try {
      if (isFav) {
        await api.favorites.remove(recipe.id)
        setFavoriteRecipeIds((prev) => {
          const next = new Set(prev)
          next.delete(recipe.id)
          return next
        })
        toast.success('Removed from favorites')
      } else {
        await api.favorites.add(recipe.id)
        setFavoriteRecipeIds((prev) => new Set(prev).add(recipe.id))
        toast.success('Added to favorites')
      }
    } catch (error) {
      console.error('Failed to toggle favorite:', error)
      toast.error('Failed to update favorites')
    }
  }, [favoriteRecipeIds])
 
  const isFavorite = useCallback((recipeId: number) => {
    return favoriteRecipeIds.has(recipeId)
  }, [favoriteRecipeIds])
 
  const clearFavorites = useCallback(() => {
    setFavoriteRecipeIds(new Set())
  }, [])
 
  return { favoriteRecipeIds, toggleFavorite, isFavorite, clearFavorites }
}
 
← Back to Dashboard