0% found this document useful (0 votes)
48 views30 pages

ZyCart: MERN Stack E-Commerce Project

ZyCart is a multi-vendor e-commerce web application developed using the MERN stack, designed to facilitate online shopping with features for customers, suppliers, and administrators. The platform includes functionalities such as product browsing, cart management, order tracking, and role-based access control, ensuring a secure and user-friendly experience. The project serves as a comprehensive learning tool for full-stack development, showcasing modern web application principles and best practices.

Uploaded by

Nitai das
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views30 pages

ZyCart: MERN Stack E-Commerce Project

ZyCart is a multi-vendor e-commerce web application developed using the MERN stack, designed to facilitate online shopping with features for customers, suppliers, and administrators. The platform includes functionalities such as product browsing, cart management, order tracking, and role-based access control, ensuring a secure and user-friendly experience. The project serves as a comprehensive learning tool for full-stack development, showcasing modern web application principles and best practices.

Uploaded by

Nitai das
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

BRAINWARE UNIVERSITY

398, Ramkrishnapur Road, Barasat, North 24-Parganas, Kolkata - 700124


NOVEMBER 2025

In partial fulfilment for the award of degree


Of
Bachelor of Computer Application (BCA - Hons.)
In
Department of Computational Sciences (CSS)

ZyCart: Easy Shop, Easy Life

A Project Report
Submitted by

Sujoy Kumar Mondal - BWU/BCA/23/206


BRAINWARE UNIVERSITY

398, Ramkrishnapur Road, Barasat, North 24-Parganas, Kolkata - 700124


NOVEMBER 2025

In partial fulfilment for the award of degree


Of
Bachelor of Computer Application (BCA - Hons.)
In
Department of Computational Sciences (CSS)

ZyCart: Easy Shop, Easy Life

A Project Report
Submitted by

Subhadeep Kumar Sahoo - BWU/BCA/23/211


BRAINWARE UNIVERSITY

398, Ramkrishnapur Road, Barasat, North 24-Parganas, Kolkata - 700124


NOVEMBER 2025

In partial fulfilment for the award of degree


Of
Bachelor of Computer Application (BCA - Hons.)
In
Department of Computational Sciences (CSS)

ZyCart: Easy Shop, Easy Life

A Project Report
Submitted by

Nitai Das - BWU/BCA/23/181


BRAINWARE UNIVERSITY

398, Ramkrishnapur Road, Barasat, North 24-Parganas, Kolkata - 700124


NOVEMBER 2025

In partial fulfilment for the award of degree


Of
Bachelor of Computer Application (BCA - Hons.)
In
Department of Computational Sciences (CSS)

ZyCart: Easy Shop, Easy Life

A Project Report
Submitted by

Soumik Kuila - BWU/BCA/23/222


ABSTRACT

Zycart is a multi-vendor e-commerce web application built using the MERN stack—MongoDB, [Link],
React, and [Link].
The platform allows users to browse products, add items to the cart, place orders, and track their
deliveries.

It also includes separate dashboards for admins and suppliers.


Suppliers can add and manage their own products, while admins can manage all users, orders, and
products across the system.

Zycart uses secure login, role-based access, and real-time data handling through REST APIs.
The frontend is built with React and Tailwind CSS, providing a fast, responsive, and user-friendly interface.

Overall, the system demonstrates how a modern e-commerce platform works using full-stack
development concepts such as API integration, authentication, dynamic rendering, and modular
architecture.
It is designed to be scalable, easy to extend, and suitable for real-world use cases as well as academic
learning.
INTRODUCTION

E-commerce platforms have become an important part of today’s digital world. People now prefer buying
products online because it is fast, easy, and comfortable. To support this trend, businesses need secure,
user-friendly, and well-designed online shopping systems.
Zycart is a fully functional e-commerce application built using the MERN stack (MongoDB, Express,
React, [Link]). The aim of Zycart is to provide an online store where customers can explore products,
add items to their cart, purchase them, and track the status of their orders. The system is designed to be
simple for users but powerful in features.
The platform includes three types of users:
1. Customers – can browse products, manage their cart, place orders, and see order updates.
2. Suppliers – can upload, edit, and manage their own products, and view orders only for items they
supplied.
3. Administrators – have complete control over the system, including managing users, suppliers,
products, and orders.
Zycart uses a clean and organized folder structure, modern UI with Tailwind CSS, and reusable
components to ensure smooth performance and easy maintainability. The project demonstrates key
concepts of full-stack web development such as:
• React routing and component structure
• API requests and server responses
• Authentication using JWT
• Database modeling with MongoDB
• State management with React hooks
• Role-based access control
• Clean and responsive UI design
Overall, Zycart is a complete learning project that shows how a real e-commerce system works from end
to end.
PROJECT OBJECTIVE

1. Develop a secure and scalable full-stack e-commerce platform using the MERN (MongoDB,
[Link], [Link], [Link]) stack.

2. Implement role-based authentication with three roles — User, Supplier, and Admin — each having
separate permissions and functionalities.

3. Allow users to browse products, view details, manage cart items, and place orders smoothly.

4. Provide dedicated dashboards for Users (My Orders), Suppliers (Product Management & Order
Items), and Admins (Product, User & Order Management).

5. Enable supplier-specific control over products and order items, including updating each item’s
delivery status (Packed, Shipped, Delivered, etc.).

6. Create a fully responsive and modern UI using Tailwind CSS, React Hooks, and reusable
components.

7. Build a modular and maintainable backend with clean RESTful APIs built on [Link] & [Link].

8. Support product search, filtering, and sorting for a better shopping experience.

9. Ensure data persistence and reliability using MongoDB with well-designed Mongoose schemas.

10. Implement essential e-commerce features, such as wishlist, reviews, Q&A, and address
management.
FEATURES

➢ User Features
• User registration & login
• Browse all products
• Product details page
• Add to cart / decrease / remove / clear cart
• Secure checkout
• My Orders page
• Item-level delivery status tracking

➢ Supplier Features
• Supplier registration & login
• Add, edit and delete their own products
• View orders that include their own products
• Update status of individual order items (Packed, Shipped, Delivered, etc.)

➢ Admin Features
• Manage all products
• Manage all orders
• Update order statuses
• Manage users & suppliers
• View system analytics (optional future feature)

➢ System Features
• JWT authentication
• Protected Routes
• Clean UI with Tailwind CSS
• LocalStorage-based cart persistence
• Responsive layout
• Real-time updates without page reloads
KEY PRINCIPLES USED

1. Component-Based UI
React splits UI into reusable components for modularity.

2. REST API Architecture


Server routes follow REST principles for clean, scalable endpoints.

3. Role-Based Security
Protect middleware ensures only authorized users access sensitive routes.

4. State Management with Hooks & Context API


Global state for cart and authentication using React Context.

5. Data Modelling & Relationships


MongoDB models (User, Product, Order) implement relations using ref.

6. Responsive Design
Tailwind CSS ensures layouts adapt to all screen sizes.

7. Code Reusability
Shared components (Navbar, Buttons, Modals) reduce duplication.

8. Separation of Concerns
Backend handles logic & APIs, frontend handles UI/UX separately.

9. Asynchronous Data Handling


Fetch and async/await used for smooth API communication.

10. Error Handling & Validation


Centralized error handlers and input validation ensure reliability.
METHODOLOGY

1. Requirement Analysis

Understand requirements like login system, cart, product management, etc.


Tools Used: Google Docs, [Link], WhatsApp Notes

2. System Design
• ERD for User → Product → Order

• Component hierarchy for React

• REST API structure for backend


Tools Used: Figma, [Link], Lucidchart

3. Frontend Development

• Setup React + Vite

• Tailwind configuration

• Components: Navbar, ProductCard, Cart, etc.

• Pages: Login, Register, Products, Admin Panel


Tools Used: React, Vite, Tailwind CSS, VS Code, React Router

4. Backend Development

• [Link] + Express server

• MongoDB schema creation

• JWT authentication

• CRUD API for users/products/orders


Tools Used: [Link], [Link], MongoDB, Mongoose, JWT, Postman

5. Integration

Connect frontend with backend through fetch/axios calls.


Tools Used: Fetch API, Axios, CORS, REST API

6. Testing & Debugging

• Test each route with Postman

• Check UI flow

• Validate protected routes


Tools Used: Postman, Console Logs, Browser DevTools, Nodemon
Folder Structure

server/
│ │ └── [Link]
├── [Link] │
├── [Link] ├── models/
├── .env │ ├── [Link]
│ │ ├── [Link]
├── config/ │ ├── [Link]
│ ├── [Link] │ ├── [Link]
│ └── [Link] │
│ ├── routes/
├── controllers/ │ ├── [Link]
│ ├── [Link] │ ├── [Link]
│ ├── [Link] │ ├── [Link]
│ ├── [Link] │ ├── [Link]
│ ├── [Link] │ ├── [Link]
│ ├── [Link] │ ├── [Link]
│ ├── [Link] │ └── [Link]
│ └── [Link] │
│ └── utils/
├── middleware/ └── [Link]
│ ├── [Link]
client/ │ │ │
│ │ │ ├── admin/
├── public/ │ │ │ ├── [Link]
│ └── [Link] │ │ │ ├── [Link]
│ │ │ │ ├── [Link]
├── src/ │ │ │ └── [Link]
│ ├── assets/ │ │ │
│ │ └── logo_cart.svg │ │ ├── supplier/
│ │ │ │ ├── [Link]
│ ├── components/ │ │ ├── [Link]
│ │ ├── [Link] │ │ ├── [Link]
│ │ ├── [Link] │ │ └── [Link]
│ │ ├── [Link] │ │
│ │ ├── [Link] │ ├── routes/
│ │ ├── [Link] │ │ └── [Link]
│ │ └── [Link] │ │
│ │ │ ├── utils/
│ ├── context/ │ │ └── [Link]
│ │ ├── [Link] │ │
│ │ └── [Link] │ ├── [Link]
│ │ │ ├── [Link]
│ ├── pages/ │ ├── [Link]
│ │ ├── [Link] │ └── [Link]
│ │ ├── [Link] │
│ │ ├── [Link] ├── [Link]
│ │ ├── [Link] ├── [Link]
│ │ ├── [Link] └── [Link]
│ │ ├── [Link]
│ │ ├── [Link]
│ │ ├── [Link]
[Link]
import React from "react"; {/* User Protected Routes */} <SupplierProducts />
import { Routes, Route } from "react-router-dom"; <Route path="/cart" </ProtectedRoute>
element={ }
import Navbar from "./components/[Link]"; <ProtectedRoute roles={["user"]}> />
import Footer from "./components/[Link]"; <CartPage />
</ProtectedRoute> <Route
// User Pages } path="/supplier/orders"
import Home from "./pages/[Link]"; /> element={
import ProductDetails from <Route <ProtectedRoute roles={["supplier"]}>
"./pages/[Link]"; path="/checkout" <SupplierOrders />
import CartPage from "./pages/[Link]"; element={ </ProtectedRoute>
import CheckoutPage from <ProtectedRoute roles={["user"]}> }
"./pages/[Link]"; <CheckoutPage /> />
import UserOrders from "./pages/[Link]"; </ProtectedRoute>
import UserProfile from "./pages/[Link]"; } {/* Admin Routes */}
import Login from "./pages/[Link]"; /> <Route
import Register from "./pages/[Link]"; path="/admin/dashboard"
<Route element={
// Supplier Pages path="/my-orders" <ProtectedRoute roles={["admin"]}>
import SupplierDashboard from element={ <AdminDashboard />
"./pages/supplier/[Link]"; <ProtectedRoute roles={["user"]}> </ProtectedRoute>
import SupplierProducts from <UserOrders /> }
"./pages/supplier/[Link]"; </ProtectedRoute> />
import SupplierOrders from }
"./pages/supplier/[Link]"; /> <Route
import SupplierApply from path="/admin/users"
"./pages/supplier/[Link]"; <Route element={
path="/profile" <ProtectedRoute roles={["admin"]}>
// Admin Pages element={ <AdminUsers />
import AdminDashboard from <ProtectedRoute roles={["user"]}> </ProtectedRoute>
"./pages/admin/[Link]"; <UserProfile /> }
import AdminUsers from </ProtectedRoute> />
"./pages/admin/[Link]"; }
import AdminSuppliers from /> <Route
"./pages/admin/[Link]"; path="/admin/suppliers"
import AdminOrders from {/* Supplier Apply (only logged-in users with element={
"./pages/admin/[Link]"; role 'user') */} <ProtectedRoute roles={["admin"]}>
<Route <AdminSuppliers />
// Route Guards path="/supplier/apply" </ProtectedRoute>
import ProtectedRoute from element={ }
"./routes/[Link]"; <ProtectedRoute roles={["user"]}> />
<SupplierApply />
const App = () => { </ProtectedRoute> <Route
return ( } path="/admin/orders"
<div className="min-h-screen flex flex-col bg- /> element={
gray-100"> <ProtectedRoute roles={["admin"]}>
<Navbar /> {/* Supplier Routes */} <AdminOrders />
<Route </ProtectedRoute>
<main className="grow container-main"> path="/supplier/dashboard" }
<Routes> element={ />
<ProtectedRoute roles={["supplier"]}>
{/* Public Routes */} <SupplierDashboard /> </Routes>
<Route path="/" element={<Home />} /> </ProtectedRoute> </main>
<Route path="/product/:id" }
element={<ProductDetails />} /> /> <Footer />
<Route path="/login" element={<Login />} </div>
/> <Route );
<Route path="/register" element={<Register path="/supplier/products" };
/>} /> element={
<ProtectedRoute roles={["supplier"]}> export default App;

About the Code:


1) Sets up the main React app layout with a navbar, routed pages, and a footer.
2) Imports all user, supplier, and admin page components for route mapping.
3) Uses React Router to define public, user-protected, supplier-protected, and admin-protected
routes.
4) Implements ProtectedRoute to restrict access based on user roles.
5) Provides complete navigation for users including product viewing, cart, checkout, orders, and
profile pages.
[Link]
import React, { useEffect, useState } from min-h-screen py-12 max-w-screen-2xl multi-supplier MERN marketplace.
"react"; container mx-auto px-14 </motion.p>
import axios from "../utils/[Link]"; bg-linear-to-br from-[#C3F2EC] via- </[Link]>
import ProductList from [#8FD6F6] to-[#3F51F4]
"../components/ProductList"; " {/* Latest Products */}
import Loader from "../components/Loader"; > <section>
import { toast } from "react-hot-toast"; <div className=""> <motion.h2
import { motion } from "framer-motion"; initial={{ opacity: 0, x: -20 }}
{/* HERO SECTION */} animate={{ opacity: 1, x: 0 }}
const Home = () => { <[Link] transition={{ duration: 0.5 }}
const [products, setProducts] = initial={{ opacity: 0, y: 40 }} className="text-2xl md:text-3xl
useState([]); animate={{ opacity: 1, y: 0 }} font-bold mb-6 tracking-tight text-
const [loading, setLoading] = transition={{ duration: 0.7, ease: [#1B2A41]"
useState(true); 'easeOut' }} >
className=" Latest Products
const fetchProducts = async () => { bg-white shadow-xl rounded-2xl </motion.h2>
try { p-10 md:p-14 text-center
const res = await [Link]("/products"); border border-[#8FD6F6]/40 {loading ? (
setProducts([Link] || []); " <div className="flex justify-center
} catch (error) { > items-center py-20">
[Link]("Error loading products", <motion.h1 <Loader />
error); initial={{ scale: 0.9 }} </div>
[Link]("Failed to load products!"); animate={{ scale: 1 }} ):(
} finally { transition={{ delay: 0.2 }} <[Link]
setLoading(false); className="text-4xl md:text-5xl initial={{ opacity: 0 }}
} font-extrabold tracking-tight text-[#1B2A41]" animate={{ opacity: 1 }}
}; > transition={{ duration: 0.4 }}
Welcome to ZyCart >
useEffect(() => { </motion.h1> <ProductList products={products}
fetchProducts(); />
}, []); <motion.p </[Link]>
useEffect(() => { initial={{ opacity: 0 }} )}
[Link] = "Home | ZyCart"; animate={{ opacity: 1 }} </section>
}, []); transition={{ delay: 0.4 }} </div>
className="mt-4 text-lg md:text-xl </div>
return ( max-w-2xl mx-auto leading-relaxed text- </>
<> gray-700" );
<div > };
className=" Discover a seamless shopping
experience powered by a modern export default Home;

About the Code:


1) Initializes state for products and loading while setting up the Home page component.
2) Fetches product data from the backend using Axios and handles errors with toast notifications.
3) Loads products on the initial render and updates the document title dynamically.
4) Displays a hero section with animated text using Framer Motion for a smooth UI experience.
5) Shows a loader while fetching data and renders the latest products using the ProductList
component once loaded.
[Link]
import React, { useEffect, useState } from className=" <label className="font-medium
"react"; min-h-screen flex items-center max-w- text-[#1B2A41]">Password</label>
import axios from "../utils/[Link]"; screen-2xl container mx-auto px-14 justify- <input
import { useAuth } from center type="password"
"../context/AuthProvider"; bg-linear-to-br from-[#C3F2EC] via- name="password"
import { useNavigate, Link } from "react- [#8FD6F6] to-[#3F51F4] onChange={handleChange}
router-dom"; py-12 value={[Link]}
import { toast } from "react-hot-toast"; " required
import { motion } from "framer-motion"; > className="
w-full mt-2 px-4 py-3 rounded-xl
const Login = () => { <[Link] border border-[#8FD6F6]/40
const { login } = useAuth(); initial={{ opacity: 0, scale: 0.9, y: 20 }} bg-[#F7FBFF] text-[#1B2A41]
const navigate = useNavigate(); animate={{ opacity: 1, scale: 1, y: 0 }} placeholder-gray-400
transition={{ duration: 0.5 }} focus:outline-none focus:ring-2
const [form, setForm] = useState({ email: className=" focus:ring-[#6A8EF0]
"", password: "" }); w-full max-w-md p-10 transition
const [loading, setLoading] = bg-white rounded-2xl shadow-xl "
useState(false); border border-[#8FD6F6]/40 placeholder="Enter your
" password"
const handleChange = (e) => > />
setForm({ ...form, [[Link]]: {/* Title */} </div>
[Link] }); <h1 className="text-3xl font-
extrabold text-center text-[#1B2A41]"> {/* Login Button */}
const handleLogin = async (e) => { Welcome Back <[Link]
[Link](); </h1> whileTap={{ scale: 0.95 }}
setLoading(true); type="submit"
<p className="text-center mt-2 text- disabled={loading}
try { gray-600"> className="
const res = await Login to continue your journey w-full py-3 rounded-xl text-white
[Link]("/auth/login", form); </p> font-semibold
bg-linear-to-r from-[#6A8EF0] to-
if ([Link]) { {/* Form */} [#3F51F4]
login([Link]); <form onSubmit={handleLogin} hover:opacity-95 transition
[Link]("token", className="space-y-6 mt-8"> shadow-lg
[Link]); "
{/* Email */} >
[Link]("Login successful!"); <div> {loading ? "Logging in..." : "Login"}
<label className="font-medium </[Link]>
const role = [Link]; text-[#1B2A41]">Email</label> </form>
<input
if (role === "user") navigate("/"); type="email" {/* Register Link */}
else if (role === "supplier") name="email" <p className="text-center mt-6 text-
navigate("/supplier/dashboard"); onChange={handleChange} gray-600">
else if (role === "admin") value={[Link]} Don’t have an account?{" "}
navigate("/admin/dashboard"); required <Link
} className=" to="/register"
} catch (error) { w-full mt-2 px-4 py-3 rounded-xl className="font-semibold text-
[Link]([Link]?.data?.mess border border-[#8FD6F6]/40 [#3F51F4] hover:underline"
age || "Login failed!"); bg-[#F7FBFF] text-[#1B2A41] >
} finally { placeholder-gray-400 Register
setLoading(false); focus:outline-none focus:ring-2 </Link>
} focus:ring-[#6A8EF0] </p>
}; transition </[Link]>
useEffect(() => { " </div>
[Link] = "Login | ZyCart"; placeholder="Enter your email" </>
}, []); /> );
</div> };
return (
<> {/* Password */} export default Login;
<div <div>

About the Code:


1) Manages login form state and authentication using context, Axios, and navigation.
2) Handles user login by sending credentials to the backend and redirecting based on user role.
3) Displays success or error notifications using react-hot-toast.
4) Sets the page title dynamically when the component loads.

[Link]
import React, { useEffect, useState } from if (!otp || ![Link] || ![Link] || </div>
"react"; ![Link]) {
import axios from "../utils/[Link]"; return [Link]("Please fill all fields"); <[Link]
import { useNavigate, Link } from "react- } whileTap={{ scale: 0.95 }}
router-dom"; type="submit"
import { toast } from "react-hot-toast"; setLoading(true); disabled={loading}
import { motion, AnimatePresence } from className="
"framer-motion"; try { w-full py-3 rounded-xl text-lg font-
const res = await semibold text-white
const Register = () => { [Link]("/auth/verify-otp", { bg-linear-to-r from-[#6A8EF0] to-
const navigate = useNavigate(); email, [#3F51F4]
otp, hover:opacity-90 transition shadow-
const [step, setStep] = useState(1); ...form, md
const [loading, setLoading] = }); "
useState(false); >
if ([Link]) { {loading ? "Sending OTP..." : "Send
const [email, setEmail] = useState(""); [Link]("Registration OTP"}
const [otp, setOtp] = useState(""); successful!"); </[Link]>
navigate("/login"); </[Link]>
const [form, setForm] = useState({ } );
name: "", } catch (error) {
mobile: "", // ------------------------------
password: "", [Link]([Link]?.data?.message // Step 2 UI (OTP + Details)
}); || "OTP verification failed"); // ------------------------------
} finally { const Step2 = (
// ------------------------------ setLoading(false); <[Link]
// Send OTP } key="step2"
// ------------------------------ }; initial={{ opacity: 0, y: 30 }}
const handleSendOtp = async (e) => { animate={{ opacity: 1, y: 0 }}
[Link](); // ------------------------------ exit={{ opacity: 0, y: -30 }}
// Step 1 UI (Email) onSubmit={handleVerifyOtp}
if (!email) return [Link]("Email is // ------------------------------ className="space-y-5"
required!"); const Step1 = ( >
<[Link] <div>
setLoading(true); key="step1" <label className="font-medium text-
initial={{ opacity: 0, y: 30 }} [#1B2A41]">OTP</label>
try { animate={{ opacity: 1, y: 0 }} <input
const res = await exit={{ opacity: 0, y: -30 }} type="text"
[Link]("/auth/send-otp", { email }); onSubmit={handleSendOtp} className="
className="space-y-5" w-full mt-2 px-4 py-3 rounded-xl
if ([Link]) { > border border-[#8FD6F6]/40 bg-
[Link]("OTP sent to your <div> [#F7FBFF]
email!"); <label className="font-medium text- text-[#1B2A41] placeholder-gray-
setStep(2); [#1B2A41]">Email</label> 400
} <input focus:outline-none focus:ring-2
} catch (error) { type="email" focus:ring-[#6A8EF0]
className=" transition
[Link]([Link]?.data?.message w-full mt-2 px-4 py-3 rounded-xl "
|| "Failed to send OTP"); border border-[#8FD6F6]/40 bg- value={otp}
} finally { [#F7FBFF] onChange={(e) =>
setLoading(false); text-[#1B2A41] placeholder-gray- setOtp([Link])}
} 400 required
}; focus:outline-none focus:ring-2 />
focus:ring-[#6A8EF0] </div>
// ------------------------------ transition
// Verify OTP + Register " <div>
// ------------------------------ value={email} <label className="font-medium text-
const handleVerifyOtp = async (e) => { onChange={(e) => [#1B2A41]">Full Name</label>
[Link](); setEmail([Link])} <input
required type="text"
/> className="
w-full mt-2 px-4 py-3 rounded-xl border border-[#8FD6F6]/40 bg- py-12
border border-[#8FD6F6]/40 bg- [#F7FBFF] "
[#F7FBFF] text-[#1B2A41] placeholder-gray- >
text-[#1B2A41] placeholder-gray- 400
400 focus:outline-none focus:ring-2 <div
focus:outline-none focus:ring-2 focus:ring-[#6A8EF0] className="
focus:ring-[#6A8EF0] transition w-full max-w-md p-10 bg-white
transition " rounded-2xl shadow-xl
" value={[Link]} border border-[#8FD6F6]/40
value={[Link]} onChange={(e) => setForm({ ...form, "
onChange={(e) => setForm({ ...form, password: [Link] })} >
name: [Link] })} required <h1
required /> className="
/> </div> text-3xl font-extrabold text-center
</div> mb-6
<[Link] text-[#1B2A41]
<div> whileTap={{ scale: 0.95 }} "
<label className="font-medium text- type="submit" >
[#1B2A41]">Mobile Number</label> disabled={loading} Register
<input className=" </h1>
type="text" w-full py-3 rounded-xl text-lg font-
className=" semibold text-white <AnimatePresence mode="wait">
w-full mt-2 px-4 py-3 rounded-xl bg-linear-to-r from-[#6A8EF0] to- {step === 1 ? Step1 : Step2}
border border-[#8FD6F6]/40 bg- [#3F51F4] </AnimatePresence>
[#F7FBFF] hover:opacity-90 transition shadow-
text-[#1B2A41] placeholder-gray- md <p className="text-center mt-6 text-
400 " gray-600">
focus:outline-none focus:ring-2 > Already have an account?{" "}
focus:ring-[#6A8EF0] {loading ? "Verifying..." : "Register"} <Link
transition </[Link]> to="/login"
" </[Link]> className="font-semibold text-
value={[Link]} ); [#3F51F4] hover:underline"
onChange={(e) => setForm({ ...form, >
mobile: [Link] })} useEffect(() => { Login
required [Link] = "Register | ZyCart"; </Link>
/> }, []); </p>
</div> </div>
return (
<div> <div </div>
<label className="font-medium text- className=" );
[#1B2A41]">Password</label> min-h-screen flex items-center max-w- };
<input screen-2xl container mx-auto px-14 justify-
type="password" center export default Register;
className=" bg-linear-to-br from-[#C3F2EC] via-
w-full mt-2 px-4 py-3 rounded-xl [#8FD6F6] to-[#3F51F4]

About the Code:


1) Manages multi-step registration with state for email, OTP, and user details.
2) Sends an OTP to the user's email and moves to the next step on success.
3) Verifies the OTP along with user details to complete registration and redirect to login.
4) Uses Framer Motion animations to smoothly transition between form steps.
5) Renders a styled, responsive registration form with separate UI for OTP sending and final user
details.
[Link]
import React from "react"; [Link]([Link]("root")).render(
import ReactDOM from "react-dom/client"; <[Link]>
import { BrowserRouter } from "react-router-dom"; <BrowserRouter>
<AuthProvider>
import App from "./App"; <CartProvider>
<App />
import "./[Link]"; </CartProvider>
</AuthProvider>
// Context Providers </BrowserRouter>
import { AuthProvider } from "./context/AuthProvider"; </[Link]>
import { CartProvider } from "./context/CartProvider"; );

About the Code:


1) Imports React, ReactDOM, routing, global styles, and the main App component.
2) Wraps the entire application with BrowserRouter to enable client-side routing.
3) Initializes AuthProvider to manage authentication and user session globally.
4) Wraps the app with CartProvider to handle cart state across all pages.
5) Renders the full application inside [Link] using [Link].

[Link]
import React, { createContext, useContext, [Link]("user", delete
useEffect, useState } from "react"; [Link](user)); [Link]["Authorizati
import axios from "../utils/[Link]"; }; on"];
}
const AuthContext = createContext(); // ------------------------------------------------------ }, [token]);
// Logout user
export const AuthProvider = ({ children }) => // ------------------------------------------------------ const value = {
{ const logout = () => { user,
const [token, setToken] = useState(() => setToken(null); token,
[Link]("token")); setUser(null); login,
const [user, setUser] = useState(() => { logout,
const u = [Link]("user"); [Link]("token"); isAuthenticated: !!token,
return u ? [Link](u) : null; [Link]("user"); };
}); [Link]("cart")
}; return <[Link]
// ------------------------------------------------------ value={value}>{children}</[Link]
// Save login data // ------------------------------------------------------ ider>;
// ------------------------------------------------------ // Attach token to axios headers };
const login = (data) => { // ------------------------------------------------------
const { token, user } = data; useEffect(() => { export const useAuth = () =>
if (token) { useContext(AuthContext);
setToken(token);
setUser(user); [Link]["Authorizati
on"] = `Bearer ${token}`;
[Link]("token", token); } else {

About the Code:


1) Creates a global authentication context to store and share user and token data across the app.
2) Loads existing token and user information from localStorage when the app starts.
3) Handles login by saving the token and user data both in state and in localStorage.
4) Logs out the user by clearing authentication state and removing stored session data.
5) Automatically attaches or removes the JWT token from Axios headers whenever the token
changes.
[Link]
import dotenv from "dotenv"; // ----------------------------------- [Link]("/api/supplier", supplierRoutes);
[Link](); // Middlewares [Link]("/api/admin", adminRoutes);
import express from "express"; // ----------------------------------- [Link]("/api/products", productRoutes);
import cors from "cors"; [Link]( [Link]("/api/orders", orderRoutes);
import cookieParser from "cookie-parser"; cors({ [Link]("/api/cart", cartRoutes);
import connectDB from "./config/[Link]"; origin: "[Link]
credentials: true, // -----------------------------------
import authRoutes from methods: ["GET", "POST", "PUT", // Error Handler (Global)
"./routes/[Link]"; "PATCH", "DELETE"] // -----------------------------------
import userRoutes from }) [Link]((err, req, res, next) => {
"./routes/[Link]"; ); [Link](" Server Error:", err);
import supplierRoutes from [Link]((req, res, next) => {
"./routes/[Link]"; [Link]("Access-Control-Allow-Origin", [Link]([Link] || 500).json({
import adminRoutes from "[Link] success: false,
"./routes/[Link]"; [Link]("Access-Control-Allow- message: [Link] || "Internal Server
import productRoutes from Credentials", "true"); Error",
"./routes/[Link]"; [Link]("Access-Control-Allow- });
import orderRoutes from Headers", "Content-Type, Authorization"); });
"./routes/[Link]"; next();
import cartRoutes from }); // -----------------------------------
"./routes/[Link]"; [Link]([Link]({ limit: "20mb" })); // Server Listen
[Link]([Link]({ extended: // -----------------------------------
true })); const PORT = [Link] || 5000;
const app = express(); [Link](cookieParser());
[Link](PORT, () => {
// ----------------------------------- // ----------------------------------- [Link](` Server running on port
// Database Connection // API ROUTES ${PORT}`);
// ----------------------------------- // ----------------------------------- });
connectDB(); [Link]("/api/auth", authRoutes);
[Link]("/api/users", userRoutes);

About the Code:


1) Loads environment variables, initializes Express, and connects to the MongoDB database.
2) Sets up core middleware such as CORS, JSON parsing, URL encoding, and cookie parsing.
3) Defines all main API routes for authentication, users, suppliers, admins, products, orders, and
carts.
4) Implements a global error handler to catch and format server-side errors.
5) Starts the Express server and listens on the configured port.

[Link]
import mongoose from "mongoose"; [Link](` MongoDB Connected: ${[Link]}`);
} catch (error) {
const connectDB = async () => { [Link](" MongoDB connection failed:", [Link]);
try { [Link](1);
const conn = await [Link]([Link].MONGO_URI, { }
useNewUrlParser: true, };
useUnifiedTopology: true,
}); export default connectDB;

About the Code:


1) Imports Mongoose to interact with MongoDB using an ODM.
2) Connects to the database using the MONGO_URI value from environment variables.
3) Enables MongoDB connection options for compatibility and stability.
4) Logs a success message when the database connection is established.
5) Catches any connection errors and stops the server if MongoDB fails to connect.
[Link]
import User from "../models/[Link]"; } export const login = async (req, res) => {
import jwt from "jsonwebtoken"; try {
import bcrypt from "bcryptjs"; [Link](200).json({ const { email, password } = [Link];
import { generateOTP, sendOTP } from success: true,
"../utils/[Link]"; message: "OTP sent successfully", const user = await [Link]({ email
}); }).populate("supplierId");
// -------------------------------------------------------- } catch (error) {
-- [Link]("OTP error:", error); if (!user)
// GENERATE JWT TOKEN [Link](500).json({ success: false, return [Link](404).json({ success:
// -------------------------------------------------------- message: "Server error" }); false, message: "User not found" });
-- }
const generateToken = (userId) => { }; if ([Link])
return [Link]({ id: userId }, return [Link](403).json({
[Link].JWT_SECRET, { // -------------------------------------------------------- success: false,
expiresIn: "7d", -- message: "Your account has been
}); // 2. VERIFY OTP + COMPLETE banned.",
}; REGISTRATION });
// --------------------------------------------------------
// -------------------------------------------------------- -- if (![Link])
-- export const verifyOtpAndRegister = async return [Link](400).json({
// 1. SEND OTP TO EMAIL (req, res) => { success: false,
// -------------------------------------------------------- try { message: "Complete registration
-- const { email, otp, name, mobile, before logging in.",
export const registerWithEmail = async password } = [Link]; });
(req, res) => {
try { const user = await [Link]({ email const isMatch = await
const { email } = [Link]; }); [Link](password);

if (!email) if (!user) if (!isMatch)


return [Link](400).json({ success: return [Link](404).json({ success: return [Link](400).json({
false, message: "Email required" }); false, message: "User not found" }); success: false,
message: "Incorrect password.",
let user = await [Link]({ email }); if ([Link] !== otp) });
return [Link](400).json({ success:
// If user exists but NOT verified → false, message: "Invalid OTP" }); const token = generateToken(user._id);
overwrite OTP
// If user exists AND has password → if ([Link] < [Link]()) [Link](200).json({
already registered return [Link](400).json({ success: success: true,
if (user && [Link]) { false, message: "OTP expired" }); message: "Login successful",
return res token,
.status(400) // Save user info user,
.json({ success: false, message: [Link] = name; });
"Email already registered." }); [Link] = mobile; } catch (error) {
} [Link] = password; // hashed by [Link]("Login error:", error);
pre('save') [Link](500).json({ success: false,
const otp = generateOTP(); [Link] = ""; message: "Server error" });
[Link] = null; }
if (!user) { };
user = await [Link]({ email, otp, await [Link]();
otpExpires: [Link]() + 5 * 60 * 1000 }); // --------------------------------------------------------
} else { [Link](201).json({ --
[Link] = otp; success: true, // 4. ADMIN REGISTRATION (POSTMAN
[Link] = [Link]() + 5 * 60 * message: "Registration successful!", ONLY)
1000; }); // --------------------------------------------------------
await [Link](); } catch (error) { --
} [Link]("Verify OTP error:", error); export const registerAdmin = async (req,
[Link](500).json({ success: false, res) => {
const mailSent = await sendOTP(email, message: "Server error" }); try {
otp); } const { email, password, name } =
}; [Link];
if (!mailSent) {
return [Link](500).json({ // -------------------------------------------------------- let admin = await [Link]({ email });
success: false, --
message: "Failed to send OTP. Try // 3. LOGIN (USER / SUPPLIER / ADMIN) if (admin)
again.", // -------------------------------------------------------- return res
}); -- .status(400)
.json({ success: false, message: }); [Link]("Admin register error:",
"Admin already exists" }); error);
[Link](201).json({ [Link](500).json({ success: false,
admin = await [Link]({ success: true, message: "Server error" });
email, message: "Admin created successfully", }
password, admin, };
name, });
role: "admin", } catch (error) {

About the Code:


1) Generates JWT tokens using the user ID with a 7-day expiration.
2) Sends OTP to a user’s email and stores it with a short expiry for secure verification.
3) Verifies OTP and completes user registration by saving name, mobile, and hashed password.
4) Handles login for users, suppliers, and admins while checking password, ban status, and
account completion.
5) Creates admin accounts manually through Postman for secure admin onboarding.

[Link]
import jwt from "jsonwebtoken"; message: "Not authorized. Token next();
import User from "../models/[Link]"; missing.", } catch (error) {
}); return [Link](401).json({
// -------------------------------------------------------- success: false,
-- // Verify token message: "Not authorized. Invalid or
// AUTHENTICATE USER USING JWT const decoded = [Link](token, expired token.",
// -------------------------------------------------------- [Link].JWT_SECRET); });
-- }
export const protect = async (req, res, next) // Fetch user };
=> { const user = await
try { [Link]([Link]); // --------------------------------------------------------
let token; --
if (!user) // ROLE-BASED PROTECTION
// Token via Authorization header: return [Link](401).json({ // --------------------------------------------------------
"Bearer token" success: false, --
if ( message: "User does not exist.", export const authorize = (...roles) => {
[Link] && }); return (req, res, next) => {
[Link]("B if (![Link]([Link]))
earer") // Check ban status return [Link](403).json({
){ if ([Link]) { success: false,
token = [Link](" return [Link](403).json({ message: "Forbidden. You do not
")[1]; success: false, have permission.",
} message: "Your account is banned. });
Contact support.",
if (!token) }); next();
return [Link](401).json({ } };
success: false, };
[Link] = user;

About the Code:


1) Extracts the JWT token from the Authorization header and verifies it using the secret key.
2) Retrieves the authenticated user from the database and blocks access if the user doesn’t exist.
3) Prevents banned users from accessing protected routes by checking their ban status.
4) Attaches the authenticated user to [Link] and allows the request to proceed.
5) Provides a role-based authorization middleware that restricts access to specific user roles.
[Link]
import mongoose from "mongoose"; type: String, },
import bcrypt from "bcryptjs"; default: "", qty: {
}, type: Number,
const userSchema = new otpExpires: { default: 1,
[Link]( type: Date, },
{ }, },
name: { ],
type: String, // -------------------------------------- },
default: "", // ADDRESS (added when first order) { timestamps: true }
}, // -------------------------------------- );
address: {
email: { type: String, // --------------------------------------
type: String, default: "", // Password Hashing Before Save
required: true, }, // --------------------------------------
unique: true, [Link]("save", async function
}, // -------------------------------------- (next) {
// BAN SYSTEM if (![Link]("password")) return
mobile: { // -------------------------------------- next();
type: String, isBanned: {
default: "", type: Boolean, if ([Link]) {
}, default: false, [Link] = await
}, [Link]([Link], 10);
password: { }
type: String, // --------------------------------------
default: "", // Supplier reference (if user becomes next();
}, supplier) });
// --------------------------------------
// -------------------------------------- supplierId: { // --------------------------------------
// ROLE: user | supplier | admin type: // Compare Password
// -------------------------------------- [Link], // --------------------------------------
role: { ref: "Supplier", [Link] =
type: String, default: null, async function (enteredPassword) {
enum: ["user", "supplier", "admin"], }, return await
default: "user", [Link](enteredPassword,
}, cart: [ [Link]);
{ };
// -------------------------------------- product: {
// OTP System type: const User = [Link]("User",
// -------------------------------------- [Link], userSchema);
otp: { ref: "Product", export default User;

About the Code:


1) Defines a complete user schema with fields for name, email, mobile, password, role, OTP
system, and address.
2) Includes ban status and supplier reference to support admin controls and supplier accounts.
3) Stores a user’s cart items as an array linked to product IDs and quantities.
4) Hashes the password automatically before saving using a Mongoose pre-save hook.
5) Provides a method to compare plain passwords with hashed passwords during login.
Home Page:
Login Page:
User cart page:
Supplier Dashboard page:
Admin Dashboard page:
CONCLUSION

Zycart successfully demonstrates a complete multi-role e-commerce platform built with modern
MERN technologies.
The system includes strong authentication, secure database interactions, smooth UI, and
advanced features like supplier-specific product and order handling.
The project reflects industrial-level engineering practices and the practical implementation of
full-stack development concepts.

Moreover, Zycart showcases scalable architecture with modular components, reusable hooks,
protected routing, and optimized state management.
The integration of admin and supplier dashboards highlights real-world workflow separation
and role-based access control.
With features like product reviews, Q&A, address management, analytics, and responsive
design, the platform delivers a professional and user-friendly experience.
FUTURE EXTENSION

➢ The project can be further enhanced with:


1. Online Payment Integration (UPI Payment / Stripe / Card Payment)
2. Advanced Analytics Dashboard
3. Search Optimization with Instant Suggestions
4. Email + SMS Order Notifications
5. Product Reviews & Ratings
6. Wishlist and Recently Viewed Items
7. AI Recommendation System
8. Mobile App using React Native

You might also like