Skip to content

Commit

Permalink
[Updates📢] MVP Complete
Browse files Browse the repository at this point in the history
  • Loading branch information
[esekyi] committed Sep 6, 2024
1 parent f295a62 commit 96ab7c0
Show file tree
Hide file tree
Showing 10 changed files with 401 additions and 57 deletions.
32 changes: 20 additions & 12 deletions app/routes/recipe_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from app.services.comment_service import CommentService
from flask_login import login_required, current_user
from app.models.user import User
from app.models.category import Category
from app.models.comment import Comment
import os

Expand Down Expand Up @@ -102,42 +103,49 @@ def edit_recipe(recipe_id):

if request.method == 'POST':
if recipe and recipe.user_id == current_user.id:
data = request.form.to_dict()
ingredients = request.form.getlist('ingredients[]')
instructions = request.form.getlist('instructions[]')
data = request.form.to_dict() # Ensure this is a dictionary

form_ingredients = request.form.getlist('ingredients[]')
form_instructions = request.form.getlist('instructions[]')
image = request.files.get('image')

# If they are strings instead of lists
if isinstance(ingredients, str):
ingredients = [ingredients]
if isinstance(instructions, str):
instructions = [instructions]


errors = validate_recipe_data(data)
if errors:
for error in errors:
flash(error, 'error')
return redirect(url_for('recipe_routes.add_recipe', recipe_id=recipe_id))
return redirect(url_for('recipe_routes.edit_recipe', recipe_id=recipe_id))

image_url = recipe.image_url
if image:
try:
image_url = upload_image_to_s3(image)
flash("Image updated successfully", "succes")
flash("Image updated successfully", "success")
except ValueError as e:
flash(str(e), 'error')
return redirect(url_for('recipe_routes.edit_recipe', recipe_id=recipe_id))

try:
update_recipe(recipe, data, ingredients,
instructions, image_url)
flash(
f"Recipe {recipe.title} updated successfully!", 'success')
update_recipe(recipe, data, form_ingredients, form_instructions, image_url) # Ensure data is a dict
flash(f"Recipe {recipe.title} updated successfully!", 'success')
return redirect(url_for('recipe_routes.view_recipe', recipe_id=recipe_id))

except Exception as e:
# Rollback db session in case of an error
db.session.rollback()
flash(
f"An error occurred while creating the recipe: {str(e)}", "error")
flash(f"An error occurred while updating the recipe: {str(e)}", "error")
return redirect(url_for('recipe_routes.edit_recipe', recipe_id=recipe_id))

categories = CategoryService.get_all_categories()
return render_template('recipes/createPages/edit1.html', recipe=recipe, ingredients=ingredients, instructions=instructions, categories=categories, title=f'Edit Recipe {recipe.title} | SpiceShare Inc.')
current_category = db.session.query(
Category).filter_by(id=recipe.category_id).first()
return render_template('recipes/createPages/edit.html', recipe=recipe, ingredients=ingredients, current_category=current_category, instructions=instructions, categories=categories, title=f'Edit Recipe {recipe.title} | SpiceShare Inc.')


@bp.route('/recipes/<uuid:recipe_id>/delete', methods=['POST'], strict_slashes=False)
Expand Down
55 changes: 33 additions & 22 deletions app/services/recipe_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def get_all_recipes(page=1, per_page=3):
dict: A dictionary containing paginated recipes and pagination info.
"""

recipes = Recipe.query.order_by(Recipe.created_at.desc()).all()
recipes = Recipe.query.order_by(Recipe.updated_at.desc()).all()
return paginate(recipes, page, per_page)


Expand All @@ -88,7 +88,7 @@ def update_recipe(recipe, data, ingredients, instructions, image_url):
try:
recipe.title = data.get('title', recipe.title)
recipe.description = data.get('description', recipe.description)
recipe.category_id = data.grt('category_id', recipe.category_id)
recipe.category_id = data.get('category_id', recipe.category_id)
recipe.oven_temp = int(data.get('oven_temp', recipe.oven_temp)) if data.get(
'oven_temp') else recipe.oven_temp
recipe.prep_time = int(data.get('prep_time', recipe.prep_time)) if data.get(
Expand All @@ -101,36 +101,47 @@ def update_recipe(recipe, data, ingredients, instructions, image_url):

# Update ingredients
existing_ingredients = {
ing.id: ing for ing in Ingredient.query.filter_by(recipe_id=recipe.id).all()}
for ingredient_data in ingredients:
if ingredient_data:
ingredient_id = ingredient_data.get('id')
if ingredient_id and ingredient_id in existing_ingredients:
existing_ingredients[ingredient_id].name = ingredient_data['name']
ing.id: ing for ing in Ingredient.query.filter_by(recipe_id=recipe.id).all()
}
for idx, ingredient_name in enumerate(ingredients):
if ingredient_name:
ingredient_id = list(existing_ingredients.keys())[
idx] if idx < len(existing_ingredients) else None
if ingredient_id:
# Update existing ingredient
existing_ingredients[ingredient_id].name = ingredient_name
else:
# add new ingredient
# Add new ingredient
new_ingredient = Ingredient(
name=ingredient_data['name'],
recipe_id=recipe.id
)
deb.session.add(new_ingredient)
name=ingredient_name, recipe_id=recipe.id)
db.session.add(new_ingredient)

# Remove any extra ingredients not submitted in the form
for extra_idx in range(len(ingredients), len(existing_ingredients)):
db.session.delete(list(existing_ingredients.values())[extra_idx])


# Update instructions
existing_instructions = {
instr.step_number: instr for instr in Instruction.query.filter_by(recipe_id=recipe.id).all()}
for i, instruction in enumerate(instructions):
if instruction:
if i + 1 in existing_instructions:
# update existing instructions
existing_instructions[i + 1].name = instruction
existing_instructions = {instr.step_number: instr for instr in Instruction.query.filter_by(recipe_id=recipe.id).all()}
for idx, instruction_text in enumerate(instructions):
if instruction_text:
step_number = idx + 1
if step_number in existing_instructions:
# Update existing instruction
existing_instructions[step_number].name = instruction_text
else:
# Add new instruction
new_instruction = Instruction(
step_number=i + 1,
name=instruction,
step_number=step_number,
name=instruction_text,
recipe_id=recipe.id
)
db.session.add(new_instruction)

# Remove any extra instructions not submitted in the form
for extra_idx in range(len(instructions) + 1, len(existing_instructions) + 1):
db.session.delete(existing_instructions[extra_idx])

db.session.commit()

except Exception as e:
Expand Down
1 change: 0 additions & 1 deletion app/static/css/recipe_form.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
padding: 16px;
border-radius: 8px;
background-color: #F9FAFB;
margin-bottom: 16px;
}

.dropdown-menu {
Expand Down
168 changes: 168 additions & 0 deletions app/static/js/edit_script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
document.addEventListener('DOMContentLoaded', function ()
{
const flashMessages = document.querySelectorAll('.flash-message');

flashMessages.forEach(function (flash)
{
setTimeout(function ()
{
flash.style.display = 'none';
}, 5000); // Flash message disappears after 5 seconds
});
});


// handle upload
document.addEventListener('DOMContentLoaded', function ()
{
document.getElementById('add-photo-btn').addEventListener('click', function (event)
{
event.preventDefault(); // Prevent default button action
document.getElementById('image-input').click();
});

document.getElementById('image-input').addEventListener('change', function (event)
{
const file = event.target.files[0];
if (file)
{
const reader = new FileReader();
reader.onload = function (e)
{
const imagePreview = document.getElementById('image-preview');
console.log('Image data URL:', e.target.result); // Debugging
imagePreview.src = e.target.result;
imagePreview.style.display = 'block'; // Show the image preview
};
reader.readAsDataURL(file);
}
});

});

// handle form drop down - not using select input
function toggleDropdown()
{
const dropdownMenu = document.getElementById('dropdownMenu');
dropdownMenu.classList.toggle('show');
}

function selectCategory(categoryName, categoryId)
{
const categoryInput = document.getElementById('categoryInput');
const categoryIdInput = document.getElementById('categoryIdInput');

// Set the selected category name in the visible input
categoryInput.value = categoryName;
// Set the selected category ID in the hidden input
categoryIdInput.value = categoryId;
toggleDropdown();
}

// Close dropdown if clicked outside
document.addEventListener('click', function (event)
{
const dropdownMenu = document.getElementById('dropdownMenu');
const categoryInput = document.getElementById('categoryInput');
if (!categoryInput.contains(event.target) && !dropdownMenu.contains(event.target))
{
dropdownMenu.classList.remove('show');
}
});

function updateStepNumbers()
{
const directionCards = document.querySelectorAll('.direction-card .step-number');
directionCards.forEach((step, index) =>
{
step.textContent = index + 1;
});
}

function addIngredient()
{
const ingredientCard = document.createElement('div');
ingredientCard.className = 'recipe-card';
ingredientCard.innerHTML = `
<div class="input-group ingredient-card overflow-hidden whitespace-nowrap">
<input type="text" name="ingredients[]" class="w-full overflow-ellipsis p-2 border border-gray-300 rounded"
placeholder="Add new ingredient">
<button type="button" class="text-red-500 hover:text-red-700" onclick="removeIngredient(this)">×</button>
</div>
`;
document.getElementById('ingredients-list').appendChild(ingredientCard);
}

function removeIngredient(element)
{
element.closest('.recipe-card').remove();
}

function addDirection()
{
const directionCard = document.createElement('div');
directionCard.className = 'recipe-card mb-2';
directionCard.innerHTML = `
<div class="input-group direction-card overflow-hidden whitespace-nowrap">
<span class="step-number">{{ loop.index }}</span>
<input type="text" name="instructions[]" class="w-full p-2 border border-gray-300 rounded overflow-ellipsis"
" placeholder="Add new instruction" required>
<button type="button" class="text-red-500 hover:text-red-700" onclick="removeDirection(this)">×</button>
</div>
`;
document.getElementById('directions-list').appendChild(directionCard);
updateStepNumbers()
}

function removeDirection(element)
{
element.closest('.recipe-card').remove();
updateStepNumbers()
}

function initializeSortable()
{
new Sortable(document.getElementById('ingredients-list'), {
animation: 150,
ghostClass: 'bg-yellow-100',
onEnd: function ()
{
updateStepNumbers(); // Update step numbers after sorting
}
});

new Sortable(document.getElementById('directions-list'), {
animation: 150,
ghostClass: 'bg-yellow-100'
});
}

document.addEventListener('DOMContentLoaded', function ()
{
initializeSortable()
updateStepNumbers();
// Handle form submission and log to console
document.getElementById('recipe-form').addEventListener('submit', function (event)
{
//event.preventDefault(); // Prevent form from submitting

// Get all ingredients
const ingredients = Array.from(document.querySelectorAll('.ingredient-card input')).map(
input => input.value).filter(value => value.trim() != '');

// Get all directions
const directions = Array.from(document.querySelectorAll('.direction-card input')).map(
input => input.value).filter(value => value.trim() != '');

// Log the data to the console
console.log('Ingredients:', ingredients);
console.log('Directions:', directions);

// You can remove or comment out this part when you want to submit to the backend
this.submit(); // Uncomment to submit the form to the backend after testing
});
});




4 changes: 2 additions & 2 deletions app/static/js/recipe_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function addDirection()
const directionCard = document.createElement('div');
directionCard.className = 'recipe-card';
directionCard.innerHTML = `
<div class="input-group direction-card">
<div class="input-group direction-card mt-2">
<input type="text" name="instructions[]" class="w-full p-2 border border-gray-300 rounded" placeholder="Add new Instruction">
<button type="button" class="text-red-500 hover:text-red-700" onclick="removeDirection(this)">×</button>
</div>
Expand Down Expand Up @@ -131,4 +131,4 @@ document.addEventListener('DOMContentLoaded', function ()
// You can remove or comment out this part when you want to submit to the backend
this.submit(); // Uncomment to submit the form to the backend after testing
});
});
});
6 changes: 6 additions & 0 deletions app/templates/recipes/createPages/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,9 @@ <h2 class="text-xl font-semibold text-gray-800">Instructions</h2>
</form>
{% endblock %}


{% block scripts %}
<script src="{{ url_for('static', filename='js/recipe_form.js') }}"></script>
{% endblock scripts %}


3 changes: 2 additions & 1 deletion app/templates/recipes/createPages/create_layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@
</div>
</footer>

<script src="{{ url_for('static', filename='js/recipe_form.js') }}"></script>
{% block scripts %}
<script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
{% endblock scripts %}
</body>

</html>
Loading

0 comments on commit 96ab7c0

Please sign in to comment.