Skip to content

Commit

Permalink
190 Forkify: Likes View (Front-End)
Browse files Browse the repository at this point in the history
- Added 7.7.17 named as "Building the Likes View (Front-End)"
  • Loading branch information
Ch-sriram committed Feb 27, 2020
1 parent b62129c commit 5245474
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 19 deletions.
53 changes: 39 additions & 14 deletions Modern-JS-ES6-NPM-Babel-Webpack/forkify_project/src/js/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
/********************************************************************************************************************
* We make the controller for the likes in here. The event for liking an item happens inside the
* .recipe class.
* Therefore, we handle the event again at the .recipe class, where we only catch the event that pertains to the
* 'click' event occurring on the like button, which is the button with .recipe__love class under the
* .recipe class generated dynamically, and this is the reason we use event delegation.
* Now we will handle the UI for the likes. Whenever the user clicks on the love button for a recipe,
* the love button has to be shown as it is a clicked love button. For that, we add logic inside the recipeView
* Module found at ./src/js/views/recipeView.js.
*
* Also, the love button should be persistent, it means that even if we reload the page, the recipe should be liked
* and that love button should show that the recipe was liked. We also implement that functionality
* by changing the recipeView module where we modify the renderRecipe() method. Note that the recipe won't be rendered
* when we reload and that's because state.likes object is not available at the time of the call of renderRecipe()
* inside the controlRecipe() controller. For that reason, we simply use a global state.likes object for testing
* purposes. We can see that global state.likes object on top of the actual Likes Controller which is controlLikes()
* controller method.
*
* Also, we don't want to show the heart icon at the top right of the webapp if there are no recipes that are liked
* by the user yet. Therefore, we will implement the functionality to hide the heart icon at the top right in the
* likesView Module.
*
* As the final step, we will render the likes into the heart icon's list when we hover over it.
* Implementation of the method related to rendering the likes can be found in the likesView Module.
*/

// Import Data Models
Expand All @@ -16,6 +29,7 @@ import Likes from './models/Likes';
import * as searchView from './views/searchView';
import * as recipeView from './views/recipeView';
import * as listView from './views/listView';
import * as likesView from './views/likesView';

// Import Common Code Base
import { elements, renderLoader, clearLoader, elementStrings } from './views/base';
Expand Down Expand Up @@ -130,7 +144,10 @@ const controlRecipe = async () => {

// Render Recipe -- console.log(state.recipe);
clearLoader();
recipeView.renderRecipe(state.recipe);
recipeView.renderRecipe(
state.recipe,
state.likes.isLikedItem(id)
);

} catch (error) {
clearLoader();
Expand Down Expand Up @@ -193,9 +210,13 @@ elements.shopping.addEventListener('click', event => {
});


// LIKE CONTROLLER

// LIKES CONTROLLER
state.likes = new Likes(); // TESTING
likesView.toggleLikeMenu(state.likes.getNumberOfLikedItems()); // TESTING

const controlLike = () => {
if (!state.likes) state.likes = new Likes();
// if (!state.likes) state.likes = new Likes();
const currentID = state.recipe.id;

// If a recipe is liked, then we have to include it in state.likes map, otherwise we don't.
Expand All @@ -207,23 +228,27 @@ const controlLike = () => {
const newLike = state.likes.addLikedItem(currentID, state.recipe.title, state.recipe.author, state.recipe.img);

// Toggle the love button

likesView.toggleLikeBtn(true);

// Add like to the UI, i.e., add the liked recipe to the liked list

console.log(state.likes); // TESTING
likesView.renderLike(newLike);
// console.log(state.likes); // TESTING

} else { // when the current recipe is liked
// Remove like from the state
state.likes.deleteLikedItem(currentID);

// Toggle the love button
likesView.toggleLikeBtn(false);

// Remove like from the UI, i.e. from the liked list


console.log(state.likes); // TESTING
likesView.deleteLike(currentID);
// console.log(state.likes); // TESTING
}

likesView.toggleLikeMenu(
state.likes.getNumberOfLikedItems()
);
};


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ export const elements = {
searchRes: document.querySelector('.results'),
searchResPages: document.querySelector('.results__pages'),
recipe: document.querySelector('.recipe'),
shopping: document.querySelector('.shopping__list')
shopping: document.querySelector('.shopping__list'),
likesMenu: document.querySelector('.likes__field'),
likesList: document.querySelector('.likes__list')
};


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { elements, elementStrings } from './base';
import { limitRecipeTitle } from './searchView';


export const toggleLikeBtn = isLiked => {
/**
* <button class="recipe__love">
<svg class="header__likes">
<use href="img/icons.svg#icon-heart-outlined"></use>
</svg>
</button>
*/

// we have to change 'icon-heart-outlined' to 'icon-heart'
const iconString = isLiked ? 'icon-heart' : 'icon-heart-outlined';

// change the href of the .recipe__love button, for which we select the use element inside the
// .recipe__love class as follows: document.querySelector('.recipe__love use') and then change the
// href attribute to the one we want.
// document.querySelector('.recipe__love use').setAttribute('href', `img/icons.svg#${iconString}`)

document.querySelector(`.${elementStrings.loveButton} use`).setAttribute('href', `img/icons.svg#${iconString}`);
};

// called inside the controlLike() method at ./src/js/index.js, which is the controller for the likes.
export const toggleLikeMenu = numLikes => {
elements.likesMenu.style.visibility = numLikes > 0 ? 'visible' : 'hidden';
};


export const renderLike = like => {
// Taken from ./src/index.html under the .likes__list class
// console.log(like); // TESTING

const markup = `
<li>
<a class="likes__link" href="#${like.id}">
<figure class="likes__fig">
<img src="${like.value.img}" alt="${like.value.title}">
</figure>
<div class="likes__data">
<h4 class="likes__name">${limitRecipeTitle(like.value.title)}</h4>
<p class="likes__author">${like.value.author}</p>
</div>
</a>
</li>
`;

elements.likesList.insertAdjacentHTML('beforeend', markup);
};


export const deleteLike = id => {
const el = document.querySelector(`.likes__link[href="#${id}"]`).parentElement;
if (el) el.parentElement.removeChild(el);
};
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const createIngredient = ingredient => `
</li>
`;

export const renderRecipe = recipe => {
export const renderRecipe = (recipe, isLiked) => {
// we get the markup under .recipe class in index.html
const markup = `
<figure class="recipe__fig">
Expand Down Expand Up @@ -91,7 +91,7 @@ export const renderRecipe = recipe => {
<button class="recipe__love">
<svg class="header__likes">
<use href="img/icons.svg#icon-heart-outlined"></use>
<use href="img/icons.svg#icon-heart${isLiked ? '': '-outlined'}"></use>
</svg>
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ export const highlightSelected = id => {
});

// highlight the selected recipe from .results__list class
document.querySelector(`a[href="#${id}"]`).classList.add('results__link--active');
document.querySelector(`.results__link[href="#${id}"]`).classList.add('results__link--active');
};


// function to limit the recipe name in the .results__list class
const limitRecipeTitle = (title, limit = 17) => { // 17 is the sweet spot for limiting the no. of letters
export const limitRecipeTitle = (title, limit = 17) => { // 17 is the sweet spot for limiting the no. of letters
let newTitle = [];
if (title.length > limit) {
title.split(' ').reduce((acc, curr) => {
Expand Down

0 comments on commit 5245474

Please sign in to comment.