You are on page 1of 34

MINI PROJECT

OF
CRWN CLOTHING
A E-Commerce for clothing

by

RISHAV RAJ
1901270100042
Final Year CSE

DEPARTMENT OF COMPUTER SCIENCE & ENGINEERING


Dr APJ Abdul Kalam Technical University
Lucknow

SUBMITTED TO
Mr. Renu Kumar
Contents

Chapter 1 1

Introduction 1

1.1 Motivation 1

1.2 Objective 1

Chapter 2 2

Project Title 2

2.1 Name of the Project and Category 2

Chapter 3 3

Scope of the project 3

3.1 Scope For Users 3

3.2 Scope Of E-commerce 4

Chapter 4 4

Working Methodology 4

4.1 Agile 4

4.2 How We Are Using Agile 5

Chapter 5 5

System Design and Structure Of The Application 5

5.1 Stucture Of The Application 6

5.1.1 App 6

5.1.2 Home Route 6

5.1.3 Category Route 7


5.1.3 Checkout Route 7

5.1.4 Auth Route 7

5.1.5 Navigation Component 7

5.1.6 Firebase 7

5.2 System Design 7

Chapter 6 9

Technologies used 9

6.1 Stack Used In Frontend 9

6.2 Technologies Used In Backend 9

6.3 Hosting 9

6.4 Other Tools 10

Code 11

Chapter 7 30

Conclusion 30
1

Chapter 1

Introduction

1.1 Motivation

In recent years digitalization spread like wildfire business and trades shifted online
making market competitive and accessible to everyone. These shifts make the market for
uncompontent very vulnerable. Everyone is selling their products and services on the
internet. In recent years many e-commerce came in market and traffic on e-commerce on
these sites is unimaginable and engineers are very key component to manage these
traffics and complexity of the e-commerce. So, I decided to make a e-commerce from
scratch to test my skills try to build a application that give users a great experience.

This will also be a great opportunity to implement what i learned through my engineering
and to learn few more skills while developing this application.

1.2 Objective

The primary goal of e-commerce is to reach maximum customers at the right time to
increase sales and profitability of the business. Functions of e-commerce include buying
and selling goods, transmitting funds or data over the internet. Boosting the efficiency of
services: With the continually evolving technology, you need to enhance the efficiency of
your services. By choosing an online ecommerce platform to create an online store, you
can efficiently reduce the cost of managing and selling online. You have various
opportunities to boost the efficiency of your service that eventually enhances the revenue
earned. By reducing the delivery time, you can witness happy customers getting back to
your business two times faster. Another way is to provide your customers with automated
services such as status update, invoice creating, chat support, etc. When you update your
efficiency of delivering products or services to your customers, you are creating a strong
online presence that helps you sell more.
2

Chapter 2

Project Title

2.1 Name of the Project and Category

The name of the project is “CRWN CLOTHING” where crwn is picked as symbol of
clothing and custom is king. Crwn Clothing will be a clothing e-commerce application
which will focus on clothes and accessories and nothing more which restric our services
but also establish some strict rule which prevent us from making the application complex
to use and manage. And clothing is also a thing which also interest me which i think a
very bare minimum thing to do uplift your self confidence.

CRWN CLOTHING

/kraʊn/
3

Figure 1.1 Screenshot of crwn clothing application

Chapter 3

Scope of the project

3.1 Scope For Users

This is a project which build from the perspective of users so, the user experience of the
the project is very important. Making the user experience good we give user to only to
buy not to sell any product. User can make a account with us and authenticate themselves
on app using their credentials . Users can also use their google account to authenticate.
User cart data will persist in their account. User can access the web app from anywhere
and anytime. Users can pay using the cards , internet banking and upi through stripe API
which is well trusted in the industry.

3.2 Scope Of E-commerce

The scope of ecommerce is expanding day by day due to the heavy number of internet
users all over the world. People are spending more time in doing online shopping for
various products available on the ecommerce platforms. According to Demand Sage, 2.14
billion people are shopping through e-commerce as of 2022. People spend more time
online shopping for various products available on e-commerce platforms. Amazon offers
items in almost every category to all the users. Additionally, It also provides the best
promotion and discounts whenever seasonal sales come. The impact of e commerce is
really good in all the developing countries.

The future scope of ecommerce in india is really going to have big growth potential in all
the categories of items. The user experience is very good in all e-commerce websites if
they continue to provide best customer support in the customer’s online shopping
journey.
4

Chapter 4

Working Methodology

4.1 Agile

It’s a process for managing a project that involves constant collaboration and working in
iterations. Agile project management works off the basis that a project can be
continuously improved upon throughout its life cycle, with changes being made quickly
and responsively. Agile project management is not a singular framework — rather, it can
be used as an umbrella term to include many different frameworks. Agile project
management can refer to terms including Scrum, Kanban, Extreme Programming (XP),
and Adaptive Project Framework (APF).

4.2 How We Are Using Agile

I am using the Agile method for this project. I will maintain a kanban board by which i
track the steps and try to build the functionality in the iteration and will maintain a
backlog list. I am going to review work on GitHub before the final merging. This will
give me ability to work on the project as different roles and divide the code according to
commits.

STEP 1 STEP 2 STEP 3


KANBAN BOARD CODE OR GITHUB
IMPLEMENTATING

Table 1.1 Workflow for the project


5

Chapter 5

System Design and Structure Of The Application

5.1 Stucture Of The Application

Figure 1.2 Structure of the application

The structure of the application of quite simple there is a app component which have four
routes home, category, checkout and auth. The navigation component will appear on
every route.

5.1.1 App
6

The app is the entry point for the application. The app.js file contains main logic to
control the routes of the single page application.

5.1.2 Home Route

The home route is the index route of the application which contains all the directory of
the application like mens, womans, hats, jeans etc.

5.1.3 Category Route

The category Route contains details listing of all the directory or categories . The
category route will show five items from every categories. It will give insigh to the
products.

5.1.3 Checkout Route

The checkout route will show all the items in your cart with quantity number and the
grand total of all the items in your cart. The checkout route will give the users payments
options

5.1.4 Auth Route

The auth route will contains sign in and sign up form component. We can create user
account and login with google user.

5.1.5 Navigation Component

Navigation component will appear on every page it will contain the link to the all pages.
It will also contain a cart icon which when clicked will show a drop down cart list which
help user to peek the cart items and quantity of the each items.

5.1.6 Firebase
7

For backend and database i am using firebase and firebase firestore. For authentication i
am using firebase auth. For database i am using firebase no sql firestore.

5.2 System Design

Figure 1.3 System Desgin Of Crwn Clothing

The workflow of the app is quite straightforward the frontend will request with user
credential or session id which stored in local storage of the web browser. It will then give
back the session id after validation of id or credential. The firebase db is used to store
8

user and user data which is a no sql database data store have schema which is useful to
validate user data.

Chapter 6

Technologies used

6.1 Stack Used In Frontend

- React .js library is used for making frontend of the project


- Redux is used to manage state in the project
- React router dom library is used for implementation of routes
- Sass is used for styling the component of the projects
- Jsx is used in react.js which javascript + html

6.2 Technologies Used In Backend

- Firebase is used for backend which is google service


- Firebase firestore for database which a no sql database which have many features
like schema based validation
- Firebase auth is used for user authentication
- Firebase auth also provide few more options to user authentication like sign in
with google
- Strip api is used for managing payments

6.3 Hosting

- Github is used to host the source code of the project.


- Netlify is used to host the project
- I am using ci/cd of netlify and github for continuous integration and continuous
deployment
- Any changeses on github repository will immeditely reflect on netlify.
9

- Netlify will build my code from source using scripts and deploy

6.4 Other Tools

- Vim text editor for developing the project


- Language server protocol is used for code intelliscene
- Prettier for formatting the code for consistency
- Figma for designing ui and ux
- Inkscape for designing the logo
- Canvas for graphic design
- Git for version control
- Github for remote storage
10

Chapter 7

Conclusion
All we want is to provide applicationthat will be affordable, accessible, and with
minimum entry barriers. The software will be very scalable and easy to maintain. Crwn
Clothing will focus on one thing and focus well. Ecommerce has always been the way of
the future, but it is more so now than ever. The outer world has become a place of
ambiguity, caution, and social distance, highlighting the many benefits of e-commerce for
both companies and customers.

Customers are looking for a detailed overview of the items they wish to purchase, which
is a critical aspect of ecommerce. An e-commerce platform provides its customers with a
product catalogue that includes data sheets that detail all of the company’s products and
services. The characteristics, utility, and specifications are comprehensive. Even the
colours of certain items, such as hats, are defined so that you can make your selection
based on personal preference. Customers can learn about the new trends in fashion and
gather additional knowledge that is not available in retail stores.

Another benefit of online selling that you might not have considered is the ease with
which consumer data can be collected, analysed, and acted upon. If you want to maintain
a laser-like emphasis on the customer experience, you must own the consumer data. By
monitoring consumer experiences, online selling enables you to collect first-hand data.
You’ll benefit from a continuous feedback loop of actionable insights that will allow you
to reinvent the customer experience continuously.

Customers are encouraged to leave feedback on online stores in order to learn about
customer satisfaction and any issues they are having when using the products and
services. The availability of these reviews on ecommerce stores allows potential buyers
to learn more about the product and determine if it is appropriate for their specific needs.
It also aids sellers in improving their services and products to increase sales and customer
satisfaction.
11
FIREBASE

import { initializeApp } from "firebase/app";


import {
getAuth,
signInWithPopup,
GoogleAuthProvider,
signInWithRedirect,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
onAuthStateChanged,
} from "firebase/auth";

import { getFirestore, doc, getDoc, setDoc, collection,


writeBatch, query, getDocs } from "firebase/firestore";

const firebaseConfig = {
apiKey: "AIzaSyAwPTuna5scvPdX4JDm0efMS5wV1ebWXfc",
authDomain: "crwn-clothing-db-b87c0.firebaseapp.com",
projectId: "crwn-clothing-db-b87c0",
storageBucket: "crwn-clothing-db-b87c0.appspot.com",
messagingSenderId: "386293404436",
appId: "1:386293404436:web:e80e325c5b26fc240fe801",
};

// Initialize Firebase
const firebaseApp = initializeApp(firebaseConfig);

//Authentication
const provider = new GoogleAuthProvider();

provider.setCustomParameters({
prompt: "select_account",
});

export const auth = getAuth();


export const signInWithGooglePopup = () => signInWithPopup(auth,
provider);
export const signInWithGoogleRedirect = () =>
signInWithRedirect(auth, provider);

//Database
export const db = getFirestore();

export const addCollectionDocument = async (collectionKey,


objectsToAdd) => {

const collectionRef = collection(db, collectionKey);


const batch = writeBatch(db);

objectsToAdd.forEach((object) => {
const docRef = doc(collectionRef, object.title.toLowerCase())
batch.set(docRef, object)
})

await batch.commit();
console.log('done');

export const getCategoriesAndDocuments = async () => {


const collectionRef = collection(db, 'categories');
const q = query(collectionRef)

const querySnapshot = await getDocs(q);


const categoryMap = querySnapshot.docs.reduce((acc,
docSnapshot) => {
const { title, items } = docSnapshot.data();
acc[title.toLowerCase()] = items;
return acc;
}, {})

return categoryMap;
}

export const createAuthUserWithEmailAndPassword = async (email,


password) => {
if (!email || !password) return;

return await createUserWithEmailAndPassword(auth, email,


password);
};

export const createUserDocumentFromAuth = async (


userAuth,
additionalInformation = {}
) => {
const userDocRef = doc(db, "users", userAuth.uid);

const userSnapshot = await getDoc(userDocRef);

if (!userSnapshot.exists()) {
const { displayName, email } = userAuth;
const createdAt = new Date();

try {
await setDoc(userDocRef, {
displayName,
email,
createdAt,
...additionalInformation,
});
} catch (error) {
if (error.code === "auth/email-already-in-use") {
alert("email already is use");
}
console.log("error creating the user", error.message);
}

return userDocRef;
}
};

export const authWithEmailAndPassword = async (email, password)


=> {
if (!email || !password) return;

return await signInWithEmailAndPassword(auth, email, password);


};

export const signOutUser = async () => await signOut(auth);

export const onAuthStateChangedListener = (callback) =>


onAuthStateChanged(auth, callback);

App.js

import { Route, Routes } from 'react-router-dom'


import './App.css'
import Home from './routes/home/home.component'
import Navigation from
'./routes/navigation/navigation.component'
import Authentication from
'./routes/authentication/authentication.component'
import Shop from './routes/shop/shop.component'
import Checkout from './routes/checkout/checkout.component'

const App = () => {


return (
<Routes>
<Route path='/' element={<Navigation />}>
<Route index element={<Home />} />
<Route path='shop/*' element={<Shop />} />
<Route path='auth' element={<Authentication />} />
<Route path='checkout' element={<Checkout />} />
</Route>
</Routes>
)
}

export default App

Shop.js

import { Routes, Route } from "react-router-dom"


import "./shop.styles.scss"
import CategoriesPreview from
"../categories-preview/categories-preview.component"
import Category from "../category/category.component"

const Shop = () => {

return (
<Routes>
<Route index element={<CategoriesPreview />} />
<Route path=":category" element={<Category />} />
</Routes>

);
};

export default Shop;

Navigation.js

import { Outlet, Link } from "react-router-dom";


import { Fragment, useContext } from "react";
import { UserContext } from "../../contexts/user.context";
import { ReactComponent as CrwnLogo } from
"../../assets/crown.svg";
import "./navigation.styles.scss";
import { signOutUser } from
"../../utils/firebase/firebase.utils";
import CartIcon from
"../../component/cart-icon/cart-icon.component.jsx";
import CartDropDown from
"../../component/cart-dropdown/cart-dropdown.component.jsx";
import { CartContext } from "../../contexts/cart.context.jsx";

const Navigation = () => {


const { currentUser } = useContext(UserContext);
const { cartDropDownShow } = useContext(CartContext);

// setCartDropDownShow(true);
const signOutHandler = async () => {
await signOutUser();
};
return (
<Fragment>
<div className="navigation">
<Link className="logo-container" to="/">
<CrwnLogo className="logo" />
</Link>
<div className="nav-links-container">
<Link className="nav-link" to="/shop">
SHOP
</Link>
{currentUser ? (
<span className="nav-link" onClick={signOutUser}>
SIGN OUT
</span>
) : (
<Link className="nav-link" to="/auth">
SIGN IN
</Link>
)}
<CartIcon />
</div>
{cartDropDownShow &&
<CartDropDown />
}
</div>
<Outlet />
</Fragment>
);
};

export default Navigation;

Home.js

import Directory from


"../../component/directory/directory.component";

const Home = () => {


const categories = [
{
id: 1,
title: "hats",
imageUrl: "https://i.ibb.co/cvpntL1/hats.png",
route: 'shop/hats'
},
{
id: 2,
title: "jackets",
imageUrl: "https://i.ibb.co/px2tCc3/jackets.png",
route: 'shop/jackets'
},
{
id: 3,
title: "sneakers",
imageUrl: "https://i.ibb.co/0jqHpnp/sneakers.png",
route: 'shop/sneakers'
},
{
id: 4,
title: "womens",
imageUrl: "https://i.ibb.co/GCCdy8t/womens.png",
route: 'shop/womens'
},
{
id: 5,
title: "mens",
imageUrl: "https://i.ibb.co/R70vBrQ/men.png",
route: 'shop/mens'
},
];

return <Directory categories={categories} />;


};

export default Home;


Checkout.js

import React from "react";


import { useContext } from "react";
import { CartContext } from "../../contexts/cart.context";
import "./checkout.styles.scss";
import CheckoutItem from
"../../component/checkout-item/checkout-item.component";

const Checkout = () => {


const { cartItems, cartTotal } =
useContext(CartContext);
return (
<div className="checkout-container">
<div className="checkout-header">
<div className="header-block">
<span>Product</span>
</div>
<div className="header-block">
<span>Quantity</span>
</div>
<div className="header-block">
<span>Price</span>
</div>
<div className="header-block">
<span>Remove</span>
</div>
<div className="header-block"></div>
</div>

{cartItems.map((cartItem) => {
return <CheckoutItem key={cartItem.id}
cartItem={cartItem} />;
})}
<span className="total">Total: ${cartTotal}</span>
</div>
);
};

export default Checkout;

Category.js

import './category.styles.scss'
import ProductCard from
'../../component/product-card/product-card.component'
import { useParams } from 'react-router-dom'
import { Fragment, useContext, useEffect, useState } from
'react'
import { CategoriesContext } from
'../../contexts/categories.context'

const Category = () => {


const { category } = useParams()
const { categoriesMap } = useContext(CategoriesContext)
const [products, setProducts] =
useState(categoriesMap[category])

useEffect(() => {
setProducts(categoriesMap[category])
}, [category, categoriesMap])

return (
<Fragment>
<h2
className='category-title'>{category.toUpperCase()}</h2>
<div className='category-container'>
{products &&
products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
</Fragment>
)
}

export default Category

Category.js

import { Fragment, useContext } from "react";


import { CategoriesContext } from
"../../contexts/categories.context";
import CategoryPreview from
"../../component/category-preview/category-preview.component"

const CategoriesPreview = () => {


const { categoriesMap } = useContext(CategoriesContext);
return (
<Fragment>
{
Object.keys(categoriesMap).map(title => {
const products = categoriesMap[title];
return <CategoryPreview key={title} title={title}
products={products} />
})
}

</Fragment>
);
};

export default CategoriesPreview;

Authentication.js
Authentication.js

import SignUpForm from


"../../component/sign-up-form/sign-up-form.component";
import SignInForm from
"../../component/sign-in-form/sign-in-form.component";
import "./authentication.styles.scss";

const Authentication = () => {


return (
<div className="authentication-container">
<SignInForm />
<SignUpForm />
</div>
);
};

export default Authentication;

Cart.context.js

import { useState, createContext, useEffect } from "react";

const addCartItem = (cartItems, productToAdd) => {


const existingCartItem = cartItems.find(
(cartItem) => cartItem.id === productToAdd.id
);

if (existingCartItem) {
return cartItems.map((cartItem) =>
cartItem.id === productToAdd.id
? { ...cartItem, quantity: cartItem.quantity + 1 }
: cartItem
);
}
return [...cartItems, { ...productToAdd, quantity: 1 }];
};

const removeCartItem = (cartItems, cartItemToRemove) => {


const existingCartItem = cartItems.find(
(cartItem) => cartItem.id === cartItemToRemove.id
);

if (existingCartItem.quantity === 1) {
return cartItems.filter((cartItem) => cartItem.id !==
cartItemToRemove.id);
}

return cartItems.map((cartItem) =>


cartItem.id === cartItemToRemove.id
? { ...cartItem, quantity: cartItem.quantity - 1 }
: cartItem
);
};

const clearCartItem = (cartItems, cartItemToClear) => {


return cartItems.filter((cartItem) => cartItem.id !==
cartItemToClear.id);
};

export const CartContext = createContext({


cartDropDownShow: null,
setCartDropDownShow: () => { },
cartItems: [],
addItemToCart: () => { },
removeItemToCart: () => { },
clearItemFromCart: () => { },
cartCount: 0,
cartTotal: 0
});

export const CartProvider = ({ children }) => {


const [cartDropDownShow, setCartDropDownShow] =
useState(false);
const [cartItems, setCartItems] = useState([]);
const [cartCount, setCartCount] = useState(0);
const [cartTotal, setCartTotal] = useState(0);

const addItemToCart = (productToAdd) => {


setCartItems(addCartItem(cartItems, productToAdd));
};
useEffect(() => {
const totalCartQuantity = cartItems.reduce(
(previousValue, { quantity }) => previousValue + quantity,
0
);

setCartCount(totalCartQuantity);
}, [cartItems]);

useEffect(() => {
const newCartTotal = cartItems.reduce(
(previousValue, { quantity, price }) => previousValue +
quantity * price,
0
);

setCartTotal(newCartTotal);
}, [cartItems]);
const removeItemToCart = (cartItemToRemove) =>
setCartItems(removeCartItem(cartItems, cartItemToRemove));

const clearItemFromCart = (cartItemToClear) =>


setCartItems(clearCartItem(cartItems, cartItemToClear));

const value = {
cartDropDownShow,
setCartDropDownShow,
addItemToCart,
cartItems,
cartCount,
removeItemToCart,
clearItemFromCart,
cartTotal,
};

return <CartContext.Provider
value={value}>{children}</CartContext.Provider>;
};

Categories.context.js

import { useEffect, useState } from "react";


import { createContext } from "react";
// import SHOP_DATA from "../shop-data.js";
import { getCategoriesAndDocuments } from
"../utils/firebase/firebase.utils"

export const CategoriesContext = createContext({


categoriesMap: {},
});
export const CategoriesProvider = ({ children }) => {

const [categoriesMap, setCategoriesMap] = useState({});


useEffect(() => {
const getCategoriesMap = async () => {
const categoryMap = await getCategoriesAndDocuments();
setCategoriesMap(categoryMap)
}
getCategoriesMap();
}, [])

const value = { categoriesMap };

return (
<CategoriesContext.Provider value={value}>
{children}
</CategoriesContext.Provider>
);
};

User.context.js

import { useState, useEffect } from 'react'


import { createContext } from 'react'
import {
createUserDocumentFromAuth,
onAuthStateChangedListener,
} from '../utils/firebase/firebase.utils'

export const UserContext = createContext({


currentUser: null,
setCurrentUser: () => null,
})

export const UserProvider = ({ children }) => {


const [currentUser, setCurrentUser] = useState(null)
const value = { currentUser, setCurrentUser }

useEffect(() => {
const unSubscribe = onAuthStateChangedListener((user) => {
if (user) {
createUserDocumentFromAuth(user)
}
setCurrentUser(user)
})
return unSubscribe
}, [])

return <UserContext.Provider
value={value}>{children}</UserContext.Provider>
}

Sign-up-form.js

import { useState, useContext } from "react";


import { UserContext } from "../../contexts/user.context";
import {
createAuthUserWithEmailAndPassword,
createUserDocumentFromAuth,
} from "../../utils/firebase/firebase.utils";
import FormInput from
"../../component/form-input/form-input.component";
import "./sign-up-form.styles.scss";
import Button from "../button/button.component";

const defaultFormField = {
displayName: "",
email: "",
password: "",
confirmPassword: "",
};

const SignUpForm = () => {


const [formFields, setFormFields] = useState(defaultFormField);
const { displayName, email, password, confirmPassword } =
formFields;
const { setCurrentUser } = useContext(UserContext);

const handleChange = (event) => {


const { name, value } = event.target;
setFormFields({ ...formFields, [name]: value });
};

const resetFormFields = () => {


setFormFields(defaultFormField);
};

const handleSubmit = async (e) => {


e.preventDefault();

if (password !== confirmPassword) {


alert("passwords do not match");
return;
}

try {
const { user } = await createAuthUserWithEmailAndPassword(
email,
password
);

await createUserDocumentFromAuth(user, { displayName });

setCurrentUser(user);
resetFormFields();
} catch (error) {
if (error.code === "auth/email-already-in-use") {
alert("Email already Exist");
} else {
console.log("A error occured while creating user",
error);
}
}
};

return (
<div className="sign-up-container">
<h1>Don't have an account?</h1>
<span>Sign up with your email and password</span>
<form onSubmit={handleSubmit}>
<FormInput
label="Display Name"
type="text"
required
onChange={handleChange}
name="displayName"
value={displayName}
/>

<FormInput
label="Email"
type="email"
required
onChange={handleChange}
name="email"
value={email}
/>
<FormInput
label="Password"
type="password"
required
onChange={handleChange}
name="password"
value={password}
/>

<FormInput
label="Confirm Password"
type="password"
required
onChange={handleChange}
name="confirmPassword"
value={confirmPassword}
/>

<Button buttonType="google" type="submit">


SIGN UP
</Button>
</form>
</div>
);
};

export default SignUpForm;

You might also like