DEV Community

Cover image for Build a Dynamic Shopping Cart in React: Filters, JSON Integration, and Responsive Design
zenixtech
zenixtech

Posted on

Build a Dynamic Shopping Cart in React: Filters, JSON Integration, and Responsive Design

This project is a React Shopping Cart Application featuring product filtering by category and price range, dynamic product rendering from a JSON file, and a sleek responsive design using styled-components. It’s ideal for beginners and intermediates to learn React concepts and practical implementation.

The app includes:

  • Dynamic filtering by category and price range.
  • Responsive product grid design.
  • Interactive product cards with hover effects.
  • Integration of JSON data to mimic a product database.

Folder Structure:
Below is the folder structure for this project:

shopping-cart/
├── public/
│   ├── index.html
│   ├── favicon.ico
├── src/
│   ├── Product/
│   │   ├── Product.jsx       
│   │   └── products.json         
│   ├── App.js                
│   ├── index.js              
├── package.json
├── README.md

Enter fullscreen mode Exit fullscreen mode

How to Think About and Create the Project:
1. Define the Problem:
Create a simple yet scalable shopping cart application.
Integrate a JSON file to simulate a backend.
Provide users with filters for category and price.
2. Plan the Structure:
Design components: FilterSection, ProductSection, and ProductCard.
Use React state for filters (category and price).
Ensure responsiveness with CSS grids and styled-components.
3. JSON Data Design:
Prepare a JSON file with product details such as id, name, price, category, and image.

products.json

[
  {
    "id": 1,
    "name": "Lymio Men T-Shirt || T-Shirt for Men || Polo T Shirt || T-Shirt (Polo-34-37)",
    "category": "Men",
    "price": 500,
    "image": "abc1.png"
  },
  {
    "id": 2,
    "name": "Aero Armour Retro Chopper HOP 8-BIT T-Shirt",
    "category": "Men",
    "price": 799,
    "image": "abc2.png"
  },
  {
    "id": 3,
    "name": "Aero Armour Rafale India Edition Blueprint T-Shirt",
    "category": "Men",
    "price": 799,
    "image": "abc3.png"
  },
  {
    "id": 4,
    "name": "Rangriti Women's Viscose Classic Ankle Length Dress",
    "category": "Women",
    "price": 1200,
    "image": "abc4.png"
  },
  {
    "id": 5,
    "name": "DUPATTA BAZAAR Women's Cream Lucknowi Net Dupatta with Gold Embroidery",
    "category": "Women",
    "price": 649,
    "image": "abc5.png"
  },
  {
    "id": 6,
    "name": "HELLA FASHIONS Women's Chanderi 2.25 Meter Dupatta with Zari Embroidery and Tassels",
    "category": "Women",
    "price": 499,
    "image": "abc6.png"
  },
  {
    "id": 7,
    "name": "NEW-18 Simple Winter Jacket For Boys, Casual Jacket, Regular Winter Jacket For Boys, Hot Wear,Comfortale Jacket For Baby Boys, Kids Jacket, Jacket06.",
    "category": "Child",
    "price": 800,
    "image": "abc7.png"
  },
  {
    "id": 8,
    "name": "FUNKOOL Boys Regular Fit | Polyster |Fluffy Full Sleevs |Quilted Insulation|High Neck Stand Collar|Zipper Jacket",
    "category": "Child",
    "price": 650,
    "image": "abc8.png"
  },
  {
    "id": 9,
    "name": "ADBUCKS Unisex Cotton Hooded Sweatshirt",
    "category": "Child",
    "price": 744,
    "image": "abc9.png"
  },
  {
    "id": 10,
    "name": "Lymio Men Jeans || Men Jeans Pants || Denim Jeans || Baggy Jeans for Men (Jeans-06-07-08)",
    "category": "Men",
    "price": 900,
    "image": "abc10.png"
  },
  {
    "id": 11,
    "name": "OFF LIMITS WMN Hustle Printed RN, Half Sleeve, T- Shirt, for Women",
    "category": "Women",
    "price": 499,
    "image": "abc11.png"
  },
  {
    "id": 12,
    "name": "Yash Gallery Women's Geomatrical Printed Regular Top for Women",
    "category": "Women",
    "price": 799,
    "image": "abc12.png"
  }
]


Enter fullscreen mode Exit fullscreen mode

Product.jsx

import React, { useState } from "react";
import styled from "styled-components";
import products from "./products.json"; // Static import

// Styled Components
const Container = styled.div`
  display: flex;
  flex-direction: row;
  gap: 20px;
  padding: 20px;

  @media (max-width: 768px) {
    flex-direction: column;
  }
`;

const FilterSection = styled.div`
  flex: 1;
  background-color: #f8f8f8;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);

  @media (max-width: 768px) {
    padding: 15px;
  }
`;

const ProductSection = styled.div`
  flex: 3;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;

  @media (max-width: 768px) {
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  }
`;

const ProductCard = styled.div`
  background: #fff;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 8px;
  text-align: center;
  box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.05);
  transition: transform 0.3s ease, box-shadow 0.3s ease;

  &:hover {
    transform: translateY(-5px);
    box-shadow: 0px 6px 15px rgba(0, 0, 0, 0.1);
  }

  img {
    max-width: 100%;
    height: auto;
    border-radius: 8px;
  }

  h3 {
    margin: 10px 0;
    font-size: 18px;
    color: #333;
  }

  p {
    color: #777;
    font-size: 16px;
    margin: 5px 0;
  }

  button {
    margin-top: 10px;
    padding: 10px 15px;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 14px;
    transition: background-color 0.3s ease;

    &:hover {
      background-color: #0056b3;
    }
  }
`;

const RangeInput = styled.input`
  width: 100%;
  margin-top: 10px;
`;

const FilterLabel = styled.label`
  display: block;
  margin-top: 15px;
  font-size: 14px;
  color: #555;
`;

const NoProductsMessage = styled.p`
  text-align: center;
  font-size: 18px;
  color: #999;
`;

// Product Component
const Product = () => {
  const [category, setCategory] = useState("All");
  const [priceRange, setPriceRange] = useState(1000); // Default range max
  const [filteredProducts, setFilteredProducts] = useState(products);

  const handleFilter = (e) => {
    const selectedCategory = e.target.value;
    setCategory(selectedCategory);

    const filtered = products.filter(
      (p) =>
        (selectedCategory === "All" || p.category === selectedCategory) &&
        p.price <= priceRange
    );
    setFilteredProducts(filtered);
  };

  const handlePriceChange = (e) => {
    const maxPrice = Number(e.target.value);
    setPriceRange(maxPrice);

    const filtered = products.filter(
      (p) =>
        (category === "All" || p.category === category) && p.price <= maxPrice
    );
    setFilteredProducts(filtered);
  };

  return (
    <Container>
      <FilterSection>
        <h2>Filters</h2>
        <FilterLabel>Category</FilterLabel>
        <select value={category} onChange={handleFilter}>
          <option value="All">All</option>
          <option value="Men">Men</option>
          <option value="Women">Women</option>
          <option value="Child">Child</option>
        </select>
        <FilterLabel>Price Range: ₹0 - ₹{priceRange}</FilterLabel>
        <RangeInput
          type="range"
          min="0"
          max="10000"
          step="500"
          value={priceRange}
          onChange={handlePriceChange}
        />
        <p>Shopping Card Create by Sudhanshu Gaikwad</p>
      </FilterSection>

      <ProductSection>
        {filteredProducts.length > 0 ? (
          filteredProducts.map((product) => (
            <ProductCard key={product.id}>
              <img src={product.image} alt={product.name} />
              <h3>{product.name}</h3>
              <p>₹{product.price}</p>
              <button>Buy Now</button>
            </ProductCard>
          ))
        ) : (
          <NoProductsMessage>
            No products found within the selected filters.
          </NoProductsMessage>
        )}
      </ProductSection>
    </Container>
  );
};

export default Product;
Enter fullscreen mode Exit fullscreen mode

Output:

Image description

Key Features:

Filter Functionality
Seamlessly filter products by category and price range.
JSON Integration
Load product data dynamically from a JSON file.
Responsive Design
Adaptable layout for all device sizes.
Styled-Components
Modern CSS-in-JS for dynamic styling.

How This Project Helps You Grow?

  • React State Management: Learn to handle complex state for real-world apps.
  • Frontend-Backend Simulation: Use JSON to simulate database functionality.
  • UI/UX Skills: Design user-friendly, interactive interfaces.
  • Responsive Web Development: Master layout techniques for different screen sizes.

Top comments (0)