All files / src/hooks useServingScale.ts

25% Statements 6/24
8.33% Branches 1/12
50% Functions 1/2
26.08% Lines 6/23

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                                              30x 30x 30x 30x   30x                                                       30x    
import { useState } from 'react'
import { toast } from 'sonner'
import { api, type RecipeDetail as RecipeDetailType, type ScaleResponse } from '../api/client'
import { handleQuotaError, extractQuotaResetsAt } from '../lib/utils'
import { useAIStatus } from '../contexts/AIStatusContext'
 
interface UseServingScaleReturn {
  servings: number | null
  scaledData: ScaleResponse | null
  scalingLoading: boolean
  setServings: (s: number | null) => void
  setScaledData: (d: ScaleResponse | null) => void
  handleServingChange: (delta: number) => Promise<void>
}
 
/**
 * Manages serving count and AI-powered ingredient scaling.
 */
export function useServingScale(
  recipe: RecipeDetailType | null,
  profileId: number | undefined,
  unitPreference: string = 'metric'
): UseServingScaleReturn {
  const { setFeatureQuotaExhausted } = useAIStatus()
  const [servings, setServings] = useState<number | null>(null)
  const [scaledData, setScaledData] = useState<ScaleResponse | null>(null)
  const [scalingLoading, setScalingLoading] = useState(false)
 
  const handleServingChange = async (delta: number) => {
    if (!servings || !recipe || !profileId) return
    const newServings = Math.max(1, servings + delta)
    setServings(newServings)
 
    if (newServings === recipe.servings) {
      setScaledData(null)
      return
    }
 
    setScalingLoading(true)
    try {
      const result = await api.ai.scale(recipe.id, newServings, profileId, unitPreference)
      setScaledData(result)
      if (result.notes.length > 0) {
        toast.info(result.notes[0])
      }
    } catch (error) {
      console.error('Failed to scale recipe:', error)
      if (handleQuotaError(error, 'Failed to scale ingredients')) {
        setFeatureQuotaExhausted('scale', extractQuotaResetsAt(error))
      }
      setServings(servings)
    } finally {
      setScalingLoading(false)
    }
  }
 
  return { servings, scaledData, scalingLoading, setServings, setScaledData, handleServingChange }
}
 
← Back to Dashboard