Skip to content
  • Unlock Pro
  • Log in with GitHub
Solution
Submitted 12 months ago

Product List with Cart using HTML CSS Javascript and SCSS

sass/scss
John Tan•140
@JohnEdgiTan
A solution to the Product list with cart challenge
View live sitePreview (opens in new tab)View codeCode (opens in new tab)

Solution retrospective


What are you most proud of, and what would you do differently next time?

Use frameworks like React or Angular

What challenges did you encounter, and how did you overcome them?

So far, the greatest challenged I faced was doing the buttons that changes when hovered.

What specific areas of your project would you like help with?

Although I have completed the challenge, I would very much appreciate any comments that can help me learn more. Specially for the part of adding contents to the order where the total quantity stays as it is instead of fading when mouse is not hovered any more on the button. Thank you.

Code
Couldn’t fetch repository

Please log in to post a comment

Log in with GitHub

Community feedback

  • ricardoychino•190
    @ricardoychino
    Posted 12 months ago

    Hello,

    Congratulations with your solution, it looks very nice. Just want to point out some things that I found:

    1 - As the quantity of the products are already initiated with 1, it is a little bit confusing in terms of usability when you click and you don't have a visual feedback on the button (we can see it showing up at the cart, sure, but it forces us to spread our range of vision where we need to focus, causing certain negative experience). I suggest:

    • starting the initial quantity with 0

    • instead of controlling which component to appear (button or quantifier) by hover, control them by classes or another atribute, only changing them if the quantity of that product is zero (shows the button 'Add to cart') or has one or more items (quantifier). When we have at least one item of that product in the cart, it is already there, so personally I think showing 'Add to cart' makes less sense than showing the quantifier. And also, I think it gives you a better visual feedback that indicates that the product is already in the cart (currently we need to hover the button to see if the quantity is greater than 1 - one more reason why it could be better to start the counter with 0 - or compare the name of the product with the name of the items in the cart)

    2 - When you remove a product directly from your cart, the quantifier of the product didn't reset. You did the splice in removeItemFromCart, but didn't alter the quantity on the product list

    3 - For the cart's data structure, personally I'd go with a Map instead of an array, here's why:

    • You wouldn't need anymore to check positionThisProductInCart in your methods. Use the ID of the product as key and the quantity as its value. For example:
    // Declare the cart
    const cart = new Map() // or Map<number, number>() if you're using TS
    
    // Add or sum up quantity
    cart.set(+productId, (cart.get(+productId) || 0) + 1)
    // - `+productId` to convert to a number in case the variable is a string
    // - The cart.get there is to get the current quantity. If it is not included, is 0
    
    // Subtract from cart
    if (cart.has(+productId)) {
      cart.set(+productId, cart.get(+productId) - 1)
    }
    
    // Remove from cart
    cart.delete(+productId)
    
    // Iterate over it
    [...cart.entries()].forEach(item => {
      // entries() gives you an iterable with the pair [key, value], so:
      // item[0] == product ID
      // item[1] == quantity
      totalQuantity = totalQuantity +  item[1]
      ...
      newItem.dataset.id = item[0];
    })
    
    • The entries are also already sorted by the order you added the item, so it is timeline-faithful (? sorry, I'm not sure if I expressed well)

    • Maps are more performant

    • for sure will save you from writing some additional code there.

    You could use a Map to store your products, too, using the product ID as a key and the object of the product as value:

    // At initApp():
    data.forEach(item => {
      product.set(item.id, item)
    })
    
    // At addDataToHTML():
    [...products.values()].forEach(product => ....)
    

    An example of performance improvement within the function addCartToHTML:

    let info = products.get(item.product_id)
    

    That single line could substitute the block:

    let positionProduct = products.findIndex((value) => value.id == item.product_id);
    let info = products[positionProduct];
    

    You don't need anymore to travel the array of products to find its info! If we have thousands of products, it could take some time to find each product in cart

    What do you think? I hope it helps. Cheers

    P.S.: The link to your repository ends up in a 404 page. Maybe it is not set as public? If we could read the code on GitHub, that certainly helps - I did this in the browser's inspector

Join our Discord community

Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!

Join our Discord

Stay up to datewith new challenges, featured solutions, selected articles, and our latest news

Frontend Mentor

  • Unlock Pro
  • Contact us
  • FAQs
  • Become a partner

Explore

  • Learning paths
  • Challenges
  • Solutions
  • Articles

Community

  • Discord
  • Guidelines

For companies

  • Hire developers
  • Train developers
© Frontend Mentor 2019 - 2025
  • Terms
  • Cookie Policy
  • Privacy Policy
  • License

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

How does the accessibility report work?

When a solution is submitted, we use axe-core to run an automated audit of your code.

This picks out common accessibility issues like not using semantic HTML and not having proper heading hierarchies, among others.

This automated audit is fairly surface level, so we encourage to you review the project and code in more detail with accessibility best practices in mind.

How does the CSS report work?

When a solution is submitted, we use stylelint to run an automated check on the CSS code.

We've added some of our own linting rules based on recommended best practices. These rules are prefixed with frontend-mentor/ which you'll see at the top of each issue in the report.

The report will audit all CSS, SCSS and Less files in your repository.

How does the HTML validation report work?

When a solution is submitted, we use html-validate to run an automated check on the HTML code.

The report picks out common HTML issues such as not using headings within section elements and incorrect nesting of elements, among others.

Note that the report can pick up “invalid” attributes, which some frameworks automatically add to the HTML. These attributes are crucial for how the frameworks function, although they’re technically not valid HTML. As such, some projects can show up with many HTML validation errors, which are benign and are a necessary part of the framework.

How does the JavaScript validation report work?

When a solution is submitted, we use eslint to run an automated check on the JavaScript code.

The report picks out common JavaScript issues such as not using semicolons and using var instead of let or const, among others.

The report will audit all JS and JSX files in your repository. We currently do not support Typescript or other frontend frameworks.

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub