Open In App

E-Medical Store using Next JS

Last Updated : 19 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

The project is an e-medical store application built using React with NextJS. It allows users to browse medical products, add them to the cart, and perform filtering and sorting based on price and product type.

Preview of final output: Let us have a look at how the final application will look like.

Screenshot-2024-03-13-115015

E-medical store using next.js

Prerequisites:

Approach to Create an E-Medical Store with NextJS:

  • The application fetches products from a backend API.
  • Users can view a list of medical products.
  • Users can add products to the cart and remove them from the cart.
  • Users can filter products based on price range and product type.
  • Users can sort products by price.
  • Total price and the number of items in the cart are dynamically updated.

Steps to Create the Project:

Step 1: Create a application of NextJS using the following command.

npx create-next-app my-medical-storecd 

Step 2: Navigate to project directory

cd my-medical-store

Step 3: Install the required packages in your project using the following command.

npm install @fortawesome/react-fontawesome @fortawesome/free-solid-svg-icons

Project Structure:

Screenshot-2024-03-13-112829

Step 3: Create the necessary components for your project: Create components folder inside src with following files and use the code given below

  • Header.js: Navbar component.
  • ProductItem.js: Component to display individual product details.
  • ProductList.js: Component to display a list of products.
  • App.js: Main application component.
  • create context folder insider src with ItemContext.js and use the code given below.
  • create global.css insider styles with following css code given below.
  • replace code of _app.js and index.js.

Example : Below is an example of E-Medical Store with NextJS.

CSS
/* styles/globals.css */

/* Reset some default browser styles */
body, h1, h2, h3, p, ul {
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Arial', sans-serif;
  background-color: #f4f4f4;
  color: #333;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

/* Navbar styles */
.navbar {
  background-color: #28a745;
  color: #fff;
  padding: 10px 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.navbar-brand {
  font-size: 1.5rem;
  font-weight: bold;
}

.navbar-items {
  display: flex;
  align-items: center;
}

.cart-num {
  display: flex;
  align-items: center;
  margin-left: 20px;
}

.cart-items {
  background-color: #dc3545;
  color: #fff;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-left: 5px;
}

/* Product List styles */
.prdt-list {
  margin: 20px 0;
}

.filter-btn {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}

.item-card {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
  list-style: none;
}

.product-card {
  background-color: #fff;
  border: 1px solid #ddd;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.product-image {
  width: 100%;
  height: 150px;
  object-fit: cover;
}

.product-details {
  padding: 15px;
}

.buy-now-btn {
  background-color: #007bff;
  color: #fff;
  padding: 10px;
  text-align: center;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

.buy-now-btn:hover {
  background-color: #0056b3;
}
Javascript
// src/pages/_app.js
import React from 'react';
import App from '../src/components/App';
import CustomItemContext from '../src/context/ItemContext';
import '../styles/globals.css';

const MyApp = ({ Component, pageProps }) => {
    return (
        <CustomItemContext>
            <App />
            {/* <Component {...pageProps} /> */}
        </CustomItemContext>
    );
};

export default MyApp;
Javascript
// pages/index.js
import React from 'react';
import ProductList from '../src/components/ProductList';
import Navbar from '../src/components/Header';
import CustomItemContext from '../src/context/ItemContext';

const Home = () => {
    return (
        <CustomItemContext>
            <Navbar />
            <ProductList />
        </CustomItemContext>
    );
};

export default Home;
Javascript
// src/components/App.js
import React from 'react';
import ProductList from './ProductList';
import Navbar from './Header';


const App = () => {
    return (
        <div>
            <Navbar />
            <ProductList />
        </div>
    );
};

export default App;
Javascript
// src/components/Header.js
import React, {
    useContext
} from 'react';
import {
    FontAwesomeIcon
} from '@fortawesome/react-fontawesome';
import {
    faCartShopping
} from '@fortawesome/free-solid-svg-icons';
import {
    ItemContext
} from '../context/ItemContext';

const Navbar = () => {
    const { itemsInCart, totalPrice } = useContext(ItemContext);

    return (
        <nav className="navbar">
            <div className="navbar-brand">
                <h1 className="ecom">
                    Welcome To E-Medical Store
                </h1>
            </div>
            <div className="navbar-items">
                <h3 style={{ color: 'green' }}>
                    Total Price: {totalPrice}
                </h3>
                <div className="cart-num">
                    <FontAwesomeIcon icon={faCartShopping} size="2x" />
                    <div className="cart-items">{itemsInCart}</div>
                </div>
            </div>
        </nav>
    );
};

export default Navbar;
Javascript
// src/components/ProductItem.js
import React, { useContext } from 'react';
import { ItemContext } from '../context/ItemContext';

const ProductItem = ({ product }) => {
    const { addToCart, removeFromCart } = useContext(ItemContext);

    const handleAddToCart = () => {
        addToCart(product);
    };

    const handleRemoveToCart = () => {
        removeFromCart(product);
    };

    return (
        <div className="product-card">
            <img className="product-image"
                src={product.image} alt={product.name} />
            <div className="product-details">
                <h3 style={{ fontWeight: '700' }}>
                    {product.name}
                </h3>
                <p style={{ fontWeight: '300' }}>
                    {product.description}
                </p>
                <p style={{ fontWeight: '500' }}>
                    Price: {product.price} Rs
                </p>
                <button onClick={handleAddToCart}>
                    Add to Cart
                </button>
                <button onClick={handleRemoveToCart}>-</button>
            </div>
        </div>
    );
};

export default ProductItem;
Javascript
// src/components/ProductList.js
import React, {
    useContext,
    useEffect,
    useState
} from 'react';
import ProductItem from './ProductItem';
import { ItemContext } from '../context/ItemContext';

const ProductList = () => {
    const { products } = useContext(ItemContext);
    const [sortedProducts, setSortedProducts] = useState([...products]);
    const [minPrice, setMinPrice] = useState(0);
    const [maxPrice, setMaxPrice] = useState(3000);
    const [selectedType, setSelectedType] = useState('all');

    useEffect(() => {
        setSortedProducts([...products]);
    }, [products]);

    const handleSortByPrice = () => {
        const sorted = [...sortedProducts].sort((a, b) =>
            a.price - b.price);
        setSortedProducts(sorted);
    };

    const handleFilterByPriceRange = () => {
        const filtered = products.filter(
            (product) => product.price >= minPrice
                && product.price <= maxPrice
        );
        setSortedProducts(filtered);
    };

    const handleFilterByType = () => {
        if (selectedType === 'all') {
            setSortedProducts([...products]);
        } else {
            const filtered = products.filter(
                (product) => product.type === selectedType);
            setSortedProducts(filtered);
        }
    };

    return (
        <div className="prdt-list">
            <h2>Product List</h2>
            <div className="filter-btn">
                <button onClick={handleSortByPrice}>
                    Sort by Price
                </button>
                <label>
                    Min Price:
                    <input
                        type="number"
                        value={minPrice}
                        onChange={(e) => 
                                setMinPrice(Number(e.target.value))}
                    />
                </label>
                <label>
                    Max Price:
                    <input
                        type="number"
                        value={maxPrice}
                        onChange={(e) => setMaxPrice(
                                   Number(e.target.value))}
                    />
                </label>
                <button onClick={() => handleFilterByPriceRange()}>
                    Filter by Price Range
                </button>
                <label>
                    Filter by Type:
                    <select
                        value={selectedType}
                        onChange={(e) => 
                                   setSelectedType(e.target.value)}
                    >
                        <option value="all">All</option>
                        <option value="Medication">Medication</option>
                        <option value="Medical Equipment">
                            Medical Equipment
                        </option>
                        <option value="Medical Supplies">
                            Medical Supplies
                        </option>
                        <option value="Personal Hygiene">
                            Personal Hygiene
                        </option>
                        <option value="Personal Protective Equipment">
                            Personal Protective Equipment
                        </option>
                    </select>
                </label>

                <button onClick={handleFilterByType}>
                    Filter by Type
                </button>
            </div>

            <ul className="item-card">
                {sortedProducts.map((product) => (
                    <ProductItem 
                        key={product.name} product={product} />
                ))}
            </ul>
            <div className="buy-now-btn">Buy Now</div>
        </div>
    );
};

export default ProductList;
Javascript
// src/context/ItemContext.js
import {
    createContext,
    useEffect,
    useState
} from 'react';

const ItemContext = createContext();

function CustomItemContext({ children }) {
    const [products, setProducts] = useState([]);
    const [cart, setCart] = useState([]);
    const [itemsInCart, setItemsInCart] = useState(0);
    const [totalPrice, setTotalPrice] = useState(0);

    useEffect(() => {
        // Fetch products from the backend 
        // and dispatch 'SET_PRODUCTS' action
        const fetchData = async () => {
            const response = await fetch(
                                `http://localhost:3000/api/products`);
            const products = await response.json();
            setProducts(products);
        };

        fetchData();
    }, []);

    const addToCart = (product) => {
        setTotalPrice(totalPrice + product.price);
        setCart([...cart, product]);
        setItemsInCart(itemsInCart + 1);
    };

    const removeFromCart = (product) => {
        const index = cart.findIndex(
            (prdt) => prdt.name === product.name);

        if (index !== -1) {
            const updatedCart = [...cart];
            updatedCart.splice(index, 1);
            setTotalPrice(totalPrice - cart[index].price);
            setCart(updatedCart);
            setItemsInCart(itemsInCart - 1);
        }
    };

    return (
        <ItemContext.Provider
            value={{
                products,
                addToCart,
                removeFromCart,
                itemsInCart,
                totalPrice,
            }}
        >
            {children}
        </ItemContext.Provider>
    );
}

export { ItemContext, CustomItemContext };
export default CustomItemContext;

Start your application using the following command.

npm run dev

Output: Access your application in a web browser by visiting http://localhost:3000

E-Medical Store using NextJS



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads