-
Notifications
You must be signed in to change notification settings - Fork 60
Recipe library - Sandra #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow!! The code looks great! It is well structured, clean and easy to follow with all comments:) I don't know what to say except that you have done such a fantastic job! The site looks great as well, I really like the animation:D
Really well done!
| <svg | ||
| class="heart-icon" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| width="20" | ||
| height="20" | ||
| fill="red" | ||
| viewBox="0 0 24 24" | ||
| > | ||
| <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 | ||
| 4.42 3 7.5 3c1.74 0 3.41 0.81 | ||
| 4.5 2.09C13.09 3.81 14.76 3 | ||
| 16.5 3 19.58 3 22 5.42 | ||
| 22 8.5c0 3.78-3.4 6.86-8.55 | ||
| 11.54L12 21.35z" /> | ||
| </svg> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know about svg and path tags. So you made your heart icon by coding here? Great job! :D
| <button | ||
| id="clearSearchBtn" | ||
| class="btn-clear-search" | ||
| >✖</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea to have this button! This makes the search bar looks professional and it is easy to erase the keywords :)
| <div | ||
| id="loading" | ||
| class="loading" | ||
| > |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wish I could see this on the browser!
| // ---------- GLOBAL STATE ---------- | ||
| let selectedFilters = [] | ||
| let selectedSort = null | ||
| let showFavoritesOnly = false | ||
| let allRecipes = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea to have all global states and elements up here! The code looks clean:)
| const now = Date.now() | ||
|
|
||
| // Use cached recipes if last fetch was under 24 hours ago | ||
| if (lastFetch && (now - lastFetch < 24 * 60 * 60 * 1000)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Smart to use the cached data!
| // ---------- CORE RENDERING FUNCTIONS ---------- | ||
| const showRecipes = (recipesArray) => { | ||
| // Add animation: fade out and scale down before updating content | ||
| recipesContainer.style.opacity = "0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love this animation! It looks really good!
| resetFilters() | ||
| updateRecipes() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a preference, but I would prefer the filter not to reset and still show random recipes after the second click:) But this works good as well!
| } | ||
| } | ||
|
|
||
| @media (min-width: 2000px) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great that you have media query for a bigger screen:) The site looks good!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good job with this project!
Your code is well structured and easy to follow. You have implemented filters in a smart and tasteful way massaging the data when needed. I also love that you did the favorite feature. And the animations are subtle and absolutely great! Very impressed.
I saw that you've used some new concepts that we havent talked about such as Set. Make sure that you understand the concept so you can explain it to others, even if you found that solution somewhere.
Keep up the good work!
| display: none; | ||
| width: 0; | ||
| opacity: 0; | ||
| transition: width 0.3s ease, opacity 0.3s ease; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice animation!
| @keyframes spin { | ||
| 0% { | ||
| transform: rotate(0deg); | ||
| } | ||
|
|
||
| 100% { | ||
| transform: rotate(360deg); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⭐
| const resetFilters = () => { | ||
| selectedFilters = [] | ||
| selectedSort = null | ||
| showFavoritesOnly = false | ||
| favBtn.classList.remove("active") | ||
| filterButtons.forEach(btn => btn.classList.remove("selected")) | ||
| sortButtons.forEach(btn => btn.classList.remove("selected")) | ||
| randomButton.classList.remove("selected") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
smart!
| const fromInstructions = recipe.analyzedInstructions?.flatMap(instr => | ||
| instr.steps?.flatMap(step => | ||
| step.ingredients?.map(i => i.name.toLowerCase().trim()) | ||
| ) | ||
| ) || [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice to play around with flatMap
| step.ingredients?.map(i => i.name.toLowerCase().trim()) | ||
| ) | ||
| ) || [] | ||
| return [...new Set([...fromExtended, ...fromInstructions])] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and Set
| if (recipesArray.length === 0) { | ||
| recipesContainer.innerHTML = `<p class="placeholder-output">😢 No recipes match your filter, try choosing another one</p>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good with empty state
| <svg class="heart-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 24 24"> | ||
| <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 | ||
| 2 5.42 4.42 3 7.5 3c1.74 0 3.41 0.81 | ||
| 4.5 2.09C13.09 3.81 14.76 3 | ||
| 16.5 3 19.58 3 22 5.42 | ||
| 22 8.5c0 3.78-3.4 6.86-8.55 | ||
| 11.54L12 21.35z"/> | ||
| </svg> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wiie! svg! great job
| // Fade in again after new content is added | ||
| recipesContainer.style.opacity = "1" | ||
| recipesContainer.style.transform = "scale(1)" | ||
| }, 150) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is totally fine but if it starts to be too much styling going on in the js file I suggest to add/remove a css class and deal with the styling there.
| if (showFavoritesOnly === true) { | ||
| filteredRecipes = filteredRecipes.filter(recipe => recipe.isFavorite === true) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice implementation of faves
| favBtn.addEventListener("click", () => { | ||
| if (showFavoritesOnly === false) { | ||
| showFavoritesOnly = true | ||
| favBtn.classList.add("active") | ||
| } else { | ||
| showFavoritesOnly = false | ||
| favBtn.classList.remove("active") | ||
| } | ||
| updateRecipes() | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⭐
✨ Live on Netlify
Here's my current version — some changes or adjustments may be added later on.