import { supabase } from "@/services/supabase"; import { Foods, GenAIResult, LikedFood, SavedFood } from "@/types"; import { PostgrestError } from "@supabase/supabase-js"; /** * Retrieves a list of foods based on the provided filters. * * @param userId - The ID of the user to filter foods by. * @param isShared - Whether to filter foods by shared status. * @param search - The search query to filter foods by name or description. * @param limit - The maximum number of foods to retrieve. * @param offset - The offset to start retrieving foods from. * @returns A promise that resolves to an object containing the list of foods and any error that occurred. */ export const getFoods = async ( userId?: string, isShared?: boolean, search?: string, limit?: number, offset?: number ): Promise<{ data: Foods[] | null; error: PostgrestError | null }> => { let query = supabase .from("foods") .select( `id, name, description, time_to_cook_minutes, skill_level, ingredient_count, calories, image_url, is_shared, created_by, created_at` ); if (userId) { query = query.eq("created_by", userId); } if (typeof isShared === "boolean") { query = query.eq("is_shared", isShared); } if (search) { query = query.or(`name.ilike.%${search}%,description.ilike.%${search}%`); } if (typeof limit === "number") { query = query.limit(limit); } if (typeof offset === "number") { query = query.range(offset, offset + (limit ? limit - 1 : 9)); } const { data, error } = await query; return { data, error }; }; /** * Retrieves a list of foods based on the provided filters. */ export const getFoodById = async (foodId: string): Promise<{ data: Foods | null; error: PostgrestError | null }> => { const { data, error } = await supabase.from("foods") .select( `id, name, description, time_to_cook_minutes, skill_level, ingredient_count, calories, image_url, is_shared, created_by, created_at` ) .eq("id", foodId) .single(); return { data, error }; } /** * Retrieves a list of saved foods for a specific user. * * @param userId - The ID of the user to retrieve saved foods for. */ export const getSavedFoods = async (userId: string): Promise<{ data: SavedFood[] | null; error: PostgrestError | null }> => { const { data, error } = await supabase.from("food_saves") .select(` user_id, food_id, created_at `) .eq("user_id", userId) return { data, error }; } /** * Retrieves a list of liked foods for a specific user. * * @param userId - The ID of the user to retrieve liked foods for. */ export const getLikedFoods = async (userId: string): Promise<{ data: LikedFood[] | null; error: PostgrestError | null }> => { const { data, error } = await supabase.from("food_likes") .select(` user_id, food_id, created_at `) .eq("user_id", userId) return { data, error }; } interface Nutrient { food_id: string, fat_g: number, fiber_g: number, protein_g: number, carbs_g: number, created_at: string, } export const getNutrients = async (food_id: string): Promise<{ data: Nutrient | null; error: PostgrestError | null }> => { const { data, error } = await supabase.from("nutrients") .select(` food_id, fat_g, fiber_g, protein_g, carbs_g, created_at `) .eq("food_id", food_id) .limit(1) return { data: data?.[0] || null, error }; } interface Ingredient { id: string; food_id: string; name: string; emoji: string; created_at: string; } /** * Retrieves a list of ingredients for a specific food. * * @param foodId - The ID of the food to retrieve ingredients for. */ export const getIngredients = async (foodId: string): Promise<{ data: Ingredient[] | null; error: PostgrestError | null }> => { const { data, error } = await supabase.from("ingredients") .select(` id, food_id, name, emoji, created_at `) .eq("food_id", foodId) return { data, error }; }; /** * Inserts a new food into the database. * * @param genAIResult - The result from the GenAI API. * @param userId - The ID of the user who created the food. * @param imageUrl - The URL of the image of the food. * @returns A promise that resolves to an object containing the ID of the inserted food and any error that occurred. */ export const insertGenAIResult = async ( genAIResult: GenAIResult, userId: string, imageUrl: string ): Promise<{ data: string | null; error: PostgrestError | null }> => { const client = supabase; const now = new Date().toISOString(); const { foods, ingredients, nutrients, cooking_steps } = genAIResult; const { data: foodInsert, error: foodError } = await client .from("foods") .insert({ name: foods.name, description: foods.description, time_to_cook_minutes: foods.time_to_cook_minutes, skill_level: foods.skill_level, ingredient_count: foods.ingredient_count, calories: foods.calories, image_url: imageUrl, is_shared: false, created_by: userId, created_at: now, }) .select("id") .single(); if (foodError || !foodInsert) { return { data: null, error: foodError }; } const foodId = foodInsert.id; const { error: nutrientError } = await client.from("nutrients").insert({ food_id: foodId, ...nutrients, created_at: now, }); if (nutrientError) { return { data: null, error: nutrientError }; } const ingredientInsert = ingredients.map((i) => ({ food_id: foodId, name: i.name, emoji: i.emoji, created_at: now, })); const { error: ingredientError } = await client .from("ingredients") .insert(ingredientInsert); if (ingredientError) { return { data: null, error: ingredientError }; } const stepInsert = cooking_steps.map((step) => ({ food_id: foodId, step_order: step.step_order, title: step.title, description: step.description, created_at: now, })); const { error: stepError } = await client .from("cooking_steps") .insert(stepInsert); if (stepError) { return { data: null, error: stepError }; } return { data: foodId, error: null }; }; export async function updateFoodSharing(foodId: string, isShared: boolean) { return await supabase.from("foods").update({ is_shared: isShared }).eq("id", foodId) } export async function deleteFood(foodId: string) { return await supabase.from("foods").delete().eq("id", foodId) }