Content ITV PRO
This is Itvedant Content department
Business Scenario
Hello talented developers!
ShopKart has successfully implemented its product listing and filtering functionality. Customers can now browse products and find items they are interested in purchasing.
What’s Already Working?
Product listing and filtering are implemented.Customers can now browse products and find items they are interested in purchasing
The Challenge
Add to Cart buttons are currently only part of the product interface.
Customers need a proper shopping cart where they can:
In this lab, students will transform the existing ShopKart product-selection experience into a fully functional shopping cart.
Pre-Lab Preparation
Module:
1) Handling Side-Effects
2) Handling Forms in React
git pull origin branchNameGit Pull
Task 1 : Create the Cart Page Structure
Cart.jsx page in the project, but it is currently only a placeholder.Open Cart.jsx and create the initial cart structure.
1
Style the Cart Page
4
<li>
<a className="dropdown-item" href="/register">Register</a>
</li>
</ul>
</div>Style the Account Section
4
Task 2 : Connect Login and Register Pages
/login
/register
In App.jsx, add:
1
import Login from "./pages/Login";
import Register from "./pages/Register";Then :
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />Plan the Login Form Workflow
2
User opens Login page
Enters username and passwords
Submits form
Form validation runs
Username is passed using setUserName()
User is redirected to Home
Navbar displays "Hello, Username"
Task 3 : Create the Login Form
Open Login.jsx and add imports:
1
import React from "react";
import { useForm } from "react-hook-form";And inside the component add :
const { register, handleSubmit, formState: { errors }} = useForm();useForm() provides the functionality required to:
Create the Login Form with Validation
2
import React from "react";
import { useForm } from "react-hook-form";
import "./Login.css";
function Login({ setUserName }) {
const { register, handleSubmit, formState: { errors }} = useForm();
return (
<div className="login-page">
<div className="login-container">
<div className="login-logo">
<img src="/images/logo.png" alt="ShopKart" />
</div>
<h2>Welcome Back!</h2>
<p className="login-subtitle"> Login to continue shopping with ShopKart </p>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<label>Username</label> <input type="text" placeholder="Enter your username"
{...register("username", {
required: "Username is required" })} />
{errors.username && (
<p className="form-error">
{errors.username.message}
</p>
)}
</div>
<div className="form-group">
<label>Password</label>
<input type="password" placeholder="Enter your password"
{...register("password", {
required: "Password is required",
minLength: {
value: 6,
message: "Password must be at least 6 characters"
}
})}
/>
{errors.password && (
<p className="form-error">
{errors.password.message}
</p>
)}
</div> <button type="submit"> Login </button>
</form>
<p className="register-text"> Don't have an account? <a href="/register">
Register</a> </p>
</div>
</div>
);
}
export default Login;Why are we using setUsername ?
setUserName as a prop.setUserName(data.username);Handle successful form submission
2
const onSubmit = (data) => {
setUserName(data.username);
};
Style the login form
3
Task 4 : Create the Registeration Form
Open Register.jsx and add :
1
import React from "react";
import { useForm } from "react-hook-form";
import "./Register.css";
function Register({ setUserName }) {
const { register,handleSubmit,formState: { errors }} = useForm();
};
return (
<div className="register-page">
<div className="register-container">
<div className="register-logo">
<img src="/images/logo.png" alt="ShopKart"/>
</div>
<h2>Create Your Account</h2>
<p className="register-subtitle"> Register to start shopping with ShopKart </p> <form onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<label>Full Name</label>
<input type="text" placeholder="Enter your full name"
{...register("fullName", {
required: "Full name is required"
})}
/>
{errors.fullName && (
<p className="form-error"> {errors.fullName.message}</p>
)}
</div>
<div className="form-group">
<label>Username</label>
<input type="text" placeholder="Enter your username"
{...register("username", {
required: "Username is required"
})}
/>
{errors.username && (
<p className="form-error"> {errors.username.message}</p>
)}
</div>
<div className="form-group">
<label>Email</label> <input type="email" placeholder="Enter your email"
{...register("email", {
required: "Email is required"
})}
/>
{errors.email && (
<p className="form-error">
{errors.email.message}
</p>
)}
</div>
<div className="form-group">
<label>Password</label>
<input type="password" placeholder="Create a password"
{...register("password", {
required: "Password is required",
minLength: {
value: 6,
message: "Password must be at least 6 characters"
}
})}/>
{errors.password && (
<p className="form-error">{errors.password.message} </p>
)}
</div> <div className="form-group">
<label>Confirm Password</label>
<input type="password" placeholder="Confirm your password"
{...register("confirmPassword", {
required: "Please confirm your password"
})}
/>
{errors.confirmPassword && (
<p className="form-error"> {errors.confirmPassword.message} </p>
)}
</div>
<button type="submit"> Register </button>
</form>
<p className="login-text"> Already have an account? <a href="/login"> Login</a>
</p>
</div>
</div>
);
}
export default Register;Handle successful form submission
2
const onSubmit = (data) => {
if (data.password === data.confirmPassword) {
setUserName(data.username);
} else {
alert("Passwords do not match");
}
};
Why are we using if...else here ?
We use if...else to compare the Password and Confirm Password values after the
other form validations have passed.
Style the Register form
3
Task 5 : Introduce useState
1
import React, { useState } from "react";useState in App.jsx because the username needs to be available to both the Login/Register pages and the Navbar.Add this import at the top
2
Inside App() add:
const [userName, setUserName] = useState("");3
Connect Login & Register Using setUserName
Now we pass setUserName from App.jsx to Login and Register.
Change:
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />To :
<Route path="/login" element={<Login setUserName={setUserName} />}/>
<Route path="/register" element={<Register setUserName={setUserName} />} />Task 6 : Use useNavigate for Redirect
1
Open Login.jsx and import useNavigate
import { useNavigate } from "react-router-dom";2
Initialize the useNavigate hook inside your component.
const navigate = useNavigate();const onSubmit = (data) => {
setUserName(data.username);
navigate("/");
};3
Update form submission
1
Open Register.jsx and import useNavigate
const navigate = useNavigate();2
Initialize the useNavigate hook inside your component.
import { useNavigate } from "react-router-dom";3
Update form submission
const onSubmit = (data) => {
if (data.password === data.confirmPassword) {
setUserName(data.username);
navigate("/");
} else {
alert("Passwords do not match");
}
};Task 7 : Render Navbar from App.jsx
Navbar was rendered inside Home.jsx and Products.jsx.App.jsx.Why are we doing this?
App.jsx contains : const [userName, setUserName] = useState("");
userName to display:Hello, Username
Home.jsx, we would have to pass userName:App.jsx(userName) --> Home.jsx(userName) --> Navbar.jsx
App.jsx
userName state
Navbar --> Hello, Username
1
Update App.jsx
import Navbar from "./components/Navbar";<Routes> <Navbar userName={userName} />
<Routes>
---
</Routes>2
Remove Navbar from Home and Products
3
Receive userName in Navbar
function Navbar() {
function Navbar({userName}) {
Task 8 : Display Greeting
1
Open Navbar.jsx - In your account/profile section, use:
{/* Account / Greeting */}
{userName ? (
<span className="user-greeting">
<img src="/icons/profile-icon.png" alt="Profile" className="greeting-profile-icon" />
Hello, {userName}
</span>
) : (
<div className="dropdown account-dropdown">
<button className="account-btn" type="button" data-bs-toggle="dropdown"
aria-expanded="false" aria-label="My Account">
<img src="/icons/profile-icon-2.png" alt="My Account" className="profile-icon" />
</button>
<ul className="dropdown-menu account-menu">
<li><a className="dropdown-item" href="/login">Login</a></li>
<li><a className="dropdown-item" href="/register">Register</a></li>
</ul>
</div>
)}2
Style the Greetings section
Task 9 : Use React Router Links for Navbar Navigation
<a href=""> links with React Router's Link and NavLink.Why are we doing this?
userName stored in useState is reset.1
In Navbar.jsx import :
import { Link, NavLink } from "react-router-dom";2
Use NavLink for the main page navigation:
<NavLink className="nav-link" to="/"> Home </NavLink>
<NavLink className="nav-link" to="/products"> Products </NavLink>
<NavLink className="nav-link" to="/about"> About </NavLink>
<NavLink className="nav-link" to="/contact"> Contact </NavLink>
<NavLink className="nav-link" to="/cart"> Cart </NavLink>3
Use Link for the logo , login and register
<Link className="navbar-brand" to="/">
<img src="/images/logo.png" alt="ShopKart" className="shopkart-logo"/>
</Link>
<Link className="dropdown-item" to="/login"> Login </Link>
<Link className="dropdown-item" to="/register"> Register </Link>4
Add this at the end of Navbar.css
.navbar .nav-link.active {
color: #0aa89e;
position: relative;
}
.navbar .nav-link.active::after {
content: "";
position: absolute; left: 5px;
right: 5px;
bottom: 2px;
height: 2px;
background-color: #0aa89e;
border-radius: 2px;
}Task 10 : Connect Trending Link to Home Section
The Trending 🔥 Navbar link is not a separate page. It points to the Trending Products section inside the Home page.
But the problem is: If we are on the Products page and click the Trending link, nothing happens.
#trending section does not exist on the Products page.Solution :
We will make the link:
If already on Home → scroll to Trending
If on another page → go to Home → scroll to Trending
1
Update the Navbar.jsx import
import { Link, NavLink, useNavigate } from "react-router-dom";Then inside the Navbar :
function Navbar({ userName }) {
const navigate = useNavigate();
// existing code
}2
Now Replace the Trending link with:
<a
className="nav-link"
href="#trending"
onClick={(e) => {
e.preventDefault();
if (window.location.pathname === "/") {
document.getElementById("trending")?.scrollIntoView({behavior: "smooth"});
} else {
navigate("/");
setTimeout(() => {
document.getElementById("trending")?.scrollIntoView({
behavior: "smooth"
});
}, 100);
}
}}
>
Trending 🔥
</a> the user is already on the Home page.2. document.getElementById("trending")?.scrollIntoView({ behavior: "smooth" });
3. else { navigate("/");
/products" or another page, we first navigate them back to:"/"id="trending" and scrolls to it.behavior: "smooth" which makes the scrolling animated instead of jumping instantly.
4. setTimeout(() => {
#trending.5. document.getElementById("trending")?.scrollIntoView({ behavior: "smooth" });
We are done with this lab. The latest source code has been uploaded to GitHub. You can access the latest commit using the link below:
Great job!
Your ShopKart Login, Registration & Forms are now working smoothly with validation, navigation.
Checkpoint
Git Push
git push origin branchNameNext-Lab Preparation
Module:
1) Handling Side-Effects
2) React Context & Reducers
By Content ITV