Skip to content

Commit

Permalink
Merge pull request #102 from kumarkrishh/KrishEditRecipeWork
Browse files Browse the repository at this point in the history
added loading for edit recipe and changed prompt for edit recipe
  • Loading branch information
kumarkrishh authored Dec 4, 2024
2 parents 575a213 + 82791f8 commit fca0db7
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 157 deletions.
144 changes: 95 additions & 49 deletions components/EditRecipeCard.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
'use client';

import { useState } from 'react';
import { useState, useCallback } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Checkbox } from '@/components/ui/checkbox';
import { X, Plus } from 'lucide-react';
import { X, Plus, Loader2 } from 'lucide-react';
import OpenAI from 'openai';
import { useCallback } from 'react';

const openaiKey = process.env.NEXT_PUBLIC_OPENAI_API_KEY;
let openai: OpenAI;
if (openaiKey) {
openai = new OpenAI({ apiKey: openaiKey, dangerouslyAllowBrowser: true });
} else {
console.warn('OpenAI API key not found. Some features may not work.');
}
let openai: OpenAI;
if (openaiKey) {
openai = new OpenAI({ apiKey: openaiKey, dangerouslyAllowBrowser: true });
} else {
console.warn('OpenAI API key not found. Some features may not work.');
}

interface EditRecipeCardProps {
recipe: any;
Expand All @@ -33,19 +31,35 @@ export default function EditRecipeCard({
...recipe,
instructions: recipe.instructions || '',
});
const [isUpdating, setIsUpdating] = useState(false);
const [isSaving, setIsSaving] = useState(false);

// Initialize ingredients with 'selected' property
const [ingredients, setIngredients] = useState(
recipe.extendedIngredients.map((ing: any) => ({
...ing,
selected: ing.selected !== undefined ? ing.selected : true,
}))
);
// Remove duplicates and initialize ingredients with 'selected' property and unique id
const uniqueIngredients = () => {
const seen = new Set();
const result = [];
for (const ing of recipe.extendedIngredients) {
const original = ing.original.trim().toLowerCase();
if (!seen.has(original)) {
seen.add(original);
result.push({
...ing,
selected: ing.selected !== undefined ? ing.selected : true,
id: Date.now() + Math.random(), // unique id for this ingredient
});
}
}
return result;
};

const [ingredients, setIngredients] = useState(uniqueIngredients());

const handleIngredientToggle = (index: number) => {
const updatedIngredients = [...ingredients];
updatedIngredients[index].selected = !updatedIngredients[index].selected;
setIngredients(updatedIngredients);
setIngredients((prevIngredients: any) => {
const updatedIngredients = [...prevIngredients];
updatedIngredients[index].selected = !updatedIngredients[index].selected;
return updatedIngredients;
});
};

const handleIngredientEdit = (index: number, newValue: string) => {
Expand All @@ -57,9 +71,9 @@ export default function EditRecipeCard({
};

const handleAddIngredient = () => {
setIngredients([
...ingredients,
{ id: Date.now(), original: '', selected: true },
setIngredients((prevIngredients: any) => [
...prevIngredients,
{ id: Date.now() + Math.random(), original: '', selected: true },
]);
};

Expand All @@ -72,31 +86,29 @@ export default function EditRecipeCard({
};

const handleUpdateRecipe = async () => {
// Your existing handleUpdateRecipe function
const selectedIngredients = ingredients.filter(
(ingredient: any) => ingredient.selected
);
setIsUpdating(true);
const selectedIngredients = ingredients.filter((ingredient: any) => ingredient.selected);
console.log('Allowed ingredients:', selectedIngredients.map((ing: any) => ing.original));

try {
const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [
{
role: 'system',
content:
'You are a culinary expert tasked with updating recipes based on ingredient changes.',
content: 'You are a culinary expert tasked with updating recipes based on a strict set of allowed ingredients.'
},
{
role: 'user',
content: `Here is the original recipe: ${editedRecipe.instructions}.
Here are the only ingredients we have: ${selectedIngredients
.map((ing: any) => ing.original)
.join(', ')}.
Edit the recipe as little as possible with these new ingredients. Make sure not to include any ingredient not in the list.
Strictly include the ingredient amount values and only use the new ingredients in the instructions.
Strictly just write out the instructions very descriptively, nothing else.`,
},
],
content: `
IGNORE PREVIOUS HISTORY. DO NOT USE INGREDIENTS OUTSIDE OF THE FOLLOWING LIST.
Update the recipe using only these ingredients: ${selectedIngredients.map((ing: any) => ing.original).join(', ')}.
- Use all allowed ingredients and maintain their amounts.
- Exclude or replace any disallowed ingredients.
- Provide concise step-by-step instructions only, without commentary or mentioning changes.
Original recipe: ${editedRecipe.instructions}`
}
],
temperature: 0.7,
max_tokens: 500,
});
Expand All @@ -111,6 +123,8 @@ export default function EditRecipeCard({
}));
} catch (error) {
console.error('Error updating recipe:', error);
} finally {
setIsUpdating(false);
}
};

Expand All @@ -123,6 +137,7 @@ export default function EditRecipeCard({
);

const handleSave = async () => {
setIsSaving(true);
const { _id, ...recipeToUpdate } = editedRecipe; // Exclude _id
const updatedRecipe = {
...recipeToUpdate,
Expand All @@ -141,15 +156,15 @@ export default function EditRecipeCard({
const data = await response.json();

if (response.ok) {
// Update successful
console.log('Recipe updated successfully:', data);
onSave(updatedRecipe); // Optionally update parent state or close modal
onSave(updatedRecipe);
} else {
// Handle error
console.error('Failed to update recipe:', data.error);
}
} catch (error) {
console.error('Error updating recipe:', error);
} finally {
setIsSaving(false);
}
};

Expand All @@ -162,12 +177,23 @@ export default function EditRecipeCard({
<div className="w-1/2 pr-4">
{/* Left side: The recipe details */}
<h3 className="text-xl font-semibold mb-2">Recipe</h3>
<div className="border-2 border-indigo-300 rounded-lg p-4 bg-indigo-50 shadow-md">
<div className="border-2 border-indigo-300 rounded-lg p-4 bg-indigo-50 shadow-md relative">
{isUpdating && (
<div className="absolute inset-0 bg-white/80 backdrop-blur-sm flex items-center justify-center rounded-lg">
<div className="text-center">
<Loader2 className="h-8 w-8 animate-spin text-indigo-600 mx-auto mb-2" />
<p className="text-indigo-600 font-medium">Updating Recipe...</p>
</div>
</div>
)}
{/* Display the updated ingredients list */}
<h4 className="font-medium text-lg mb-2">Ingredients:</h4>
<ul className="list-disc list-inside mb-4">
{ingredients.map((ingredient: any, index: number) => (
<li key={ingredient.id} className={`${!ingredient.selected ? 'line-through text-gray-400' : ''}`}>
{ingredients.map((ingredient: any) => (
<li
key={ingredient.id}
className={`${!ingredient.selected ? 'line-through text-gray-400' : ''}`}
>
{ingredient.original}
</li>
))}
Expand All @@ -177,7 +203,7 @@ export default function EditRecipeCard({
<div className="text-base leading-relaxed">
{editedRecipe.instructions
.split('\n')
.map((line: any, index: number) => (
.map((line: string, index: number) => (
<div key={index}>{line}</div>
))}
</div>
Expand Down Expand Up @@ -210,17 +236,37 @@ export default function EditRecipeCard({
<Button onClick={handleAddIngredient} className="mt-2">
<Plus className="h-4 w-4 mr-2" /> Add Ingredient
</Button>
<Button onClick={handleUpdateRecipe} className="mt-4 w-full">
Update Recipe
<Button
onClick={handleUpdateRecipe}
className="mt-4 w-full"
disabled={isUpdating}
>
{isUpdating ? (
<>
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
Updating Recipe...
</>
) : (
'Update Recipe'
)}
</Button>
</div>
</CardContent>
<div className="fixed bottom-4 right-4">
<Button onClick={onCancel} variant="outline" className="mr-2">
Cancel
</Button>
<Button onClick={handleSave}>Save Changes</Button>
<Button onClick={handleSave} disabled={isSaving}>
{isSaving ? (
<>
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
Saving...
</>
) : (
'Save Changes'
)}
</Button>
</div>
</Card>
);
}
}
108 changes: 0 additions & 108 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fca0db7

Please sign in to comment.