0% found this document useful (0 votes)
107 views78 pages

Experiment 1) Program To Build A Chat Module Using HTML Css and Javascript

This document outlines two experiments: the first experiment focuses on building a basic chat module using HTML, CSS, and JavaScript, allowing users to send and receive messages. The second experiment involves creating an interactive star rating system using jQuery, where users can select a rating by clicking on stars. Each experiment includes a detailed explanation, file structure, and code snippets for implementation.

Uploaded by

Umesh Sahu
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)
107 views78 pages

Experiment 1) Program To Build A Chat Module Using HTML Css and Javascript

This document outlines two experiments: the first experiment focuses on building a basic chat module using HTML, CSS, and JavaScript, allowing users to send and receive messages. The second experiment involves creating an interactive star rating system using jQuery, where users can select a rating by clicking on stars. Each experiment includes a detailed explanation, file structure, and code snippets for implementation.

Uploaded by

Umesh Sahu
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
You are on page 1/ 78

B64

Experiment 1) Program to build a Chat module


using HTML CSS and JavaScript
Explanation
This experiment aims to create a basic front-end chat interface. Users can type
messages, send them, and see the conversation displayed in a chat window
simulation.

Program Explanation
The program uses three files: HTML sets up the structure (message area, input,
button). CSS styles the elements (layout, colors, bubbles). JavaScript handles
the interactivity, like adding messages to the display and simulating replies.

File Structure
/Experiment_1_Chat_Module
├── index.html (HTML Structure)
├── style.css (CSS Styling)
└── script.js (JavaScript Functionality)

Code
1. index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>Experiment 1: Chat Module</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com"
crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;50
0;600;700&display=swap" rel="stylesheet">
<script src="script.js" defer></script>
</head>
<body>
<div class="chat-container">

1
B64

<div class="chat-header">
Chat Module
</div>

<div class="chat-messages" id="chat-messages">


<div class="message bot-message">
<div class="message-bubble">
Hi there! Ask me anything.
</div>
</div>
</div>

<div class="chat-input-area">
<input
type="text"
id="message-input"
placeholder="Type your message here..."
class="message-input"
>
<button id="send-button" class="send-button">
Send
</button>
</div>
</div>
</body>
</html>

2. style.css:
/* Basic body styling */
body {
font-family: 'Inter', sans-serif; /* Preferred font */
background-color: #f0f2f5; /* Light gray background */
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh; /* Full viewport height */
margin: 0;
padding: 16px; /* Padding around the chat container */
box-sizing: border-box;
}

/* Main chat container styling */


.chat-container {
width: 100%;
max-width: 450px; /* Max width for the chat box */
background-color: #ffffff; /* White background */

2
B64

border-radius: 8px; /* Rounded corners */


box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); /* Subtle shadow */
overflow: hidden; /* Hide overflowing content */
display: flex;
flex-direction: column; /* Stack elements vertically */
}

/* Chat header styling */


.chat-header {
background-color: #007bff; /* Blue header */
color: white;
padding: 16px;
text-align: center;
font-weight: 600; /* Semi-bold */
font-size: 1.1rem;
}

/* Chat messages area styling */


.chat-messages {
flex-grow: 1; /* Take available vertical space */
padding: 16px;
height: 350px; /* Fixed height */
overflow-y: auto; /* Enable vertical scrollbar if needed */
border-bottom: 1px solid #e0e0e0; /* Separator line */
}

/* Optional: Custom scrollbar styling */


.chat-messages::-webkit-scrollbar {
width: 8px;
}
.chat-messages::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.chat-messages::-webkit-scrollbar-thumb {
background: #cccccc;
border-radius: 10px;
}
.chat-messages::-webkit-scrollbar-thumb:hover {
background: #aaaaaa;
}

/* Individual message container styling */


.message {
margin-bottom: 12px; /* Space between messages */
display: flex; /* Use flexbox for alignment */
}

3
B64

/* Message bubble styling */


.message-bubble {
padding: 10px 15px;
border-radius: 18px; /* More rounded bubbles */
max-width: 75%; /* Max width of bubble */
word-wrap: break-word; /* Break long words */
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}

/* Bot message specific styling */


.bot-message {
justify-content: flex-start; /* Align bot messages to the left */
}
.bot-message .message-bubble {
background-color: #e9e9eb; /* Light gray for bot */
color: #333; /* Dark text */
margin-right: auto; /* Push bubble to the left */
}

/* User message specific styling */


.user-message {
justify-content: flex-end; /* Align user messages to the right */
}
.user-message .message-bubble {
background-color: #007bff; /* Blue for user */
color: white;
margin-left: auto; /* Push bubble to the right */
}

/* Chat input area styling */


.chat-input-area {
display: flex;
align-items: center;
padding: 12px;
background-color: #f8f9fa; /* Slightly different background */
}

/* Message input field styling */


.message-input {
flex-grow: 1; /* Take available horizontal space */
padding: 12px;
border: 1px solid #ced4da;
border-radius: 20px; /* Pill shape */
margin-right: 8px;
font-size: 1rem;
outline: none; /* Remove default outline */

4
B64

transition: border-color 0.2s ease-in-out;


}
.message-input:focus {
border-color: #007bff; /* Highlight border on focus */
}

/* Send button styling */


.send-button {
background-color: #007bff; /* Blue button */
color: white;
border: none;
padding: 12px 18px;
border-radius: 20px; /* Pill shape */
cursor: pointer;
font-weight: 500;
font-size: 1rem;
transition: background-color 0.2s ease-in-out;
}
.send-button:hover {
background-color: #0056b3; /* Darker blue on hover */
}

3. script.js:
// script.js - Chat Module Functionality

// Wait for the HTML document to be fully loaded and parsed


document.addEventListener('DOMContentLoaded', () => {

// Get references to DOM elements


const chatMessages = document.getElementById('chat-
messages');
const messageInput = document.getElementById('message-
input');
const sendButton = document.getElementById('send-button');

/**
* Adds a new message to the chat display area.
* @param {string} message - The text content of the message.
* @param {string} [sender='user'] - The sender ('user' or
'bot').
*/
function addMessage(message, sender = 'user') {
// Create the main message container div
const messageDiv = document.createElement('div');
messageDiv.classList.add('message'); // Common class for

5
B64

all messages

// Add sender-specific class for alignment and styling


if (sender === 'user') {
messageDiv.classList.add('user-message');
} else {
messageDiv.classList.add('bot-message');
}

// Create the message bubble div


const messageBubble = document.createElement('div');
messageBubble.classList.add('message-bubble');
messageBubble.textContent = message; // Set the text
content

// Append the bubble to the message container


messageDiv.appendChild(messageBubble);
// Append the message container to the chat display area
chatMessages.appendChild(messageDiv);

// Scroll the chat area to the bottom to show the latest


message
// Use smooth scroll for better UX if supported
chatMessages.scrollTo({ top: chatMessages.scrollHeight,
behavior: 'smooth' });
}

/**
* Handles sending a message when the button is clicked or
Enter is pressed.
*/
function sendMessage() {
// Get the message text from input, removing
leading/trailing whitespace
const messageText = messageInput.value.trim();

// Proceed only if the message is not empty


if (messageText) {
addMessage(messageText, 'user'); // Display the
user's message
messageInput.value = ''; // Clear the input field
messageInput.focus(); // Keep focus on the input
field

// Simulate a bot reply after a short delay


setTimeout(() => {
// Array of possible bot replies

6
B64

const replies = [
"Hmm, interesting.",
"Okay, I understand.",
"I'm not sure about that.",
"Alright.",
"Tell me more!",
"Got it!",
"I am just a simple bot."
];
// Select a random reply
const randomReply =
replies[Math.floor(Math.random() * replies.length)];
addMessage(randomReply, 'bot'); // Display the
bot's reply
}, 1000); // Reply after 1000 milliseconds (1 second)
}
}

// --- Event Listeners ---

// Add click event listener to the send button


if (sendButton) {
sendButton.addEventListener('click', sendMessage);
}

// Add keypress event listener to the message input field


if (messageInput) {
messageInput.addEventListener('keypress',
function(event) {
// Check if the pressed key is 'Enter' and Shift key
is not held
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault(); // Prevent default Enter
behavior (like adding a new line)
sendMessage(); // Send the message
}
});
}

}); // End of DOMContentLoaded listener

7
B64

Output

8
B64

Experiment 2) Program to create and Build a star


rating system using Jquery
Explanation
This experiment focuses on creating an interactive star rating component. Users
can visually select a rating (e.g., 1 to 5 stars) by clicking on the stars.

Program Explanation
The implementation uses HTML to structure the star icons and display area. CSS
styles the stars' appearance (default, hover, selected states). jQuery handles the
dynamic behavior, detecting mouse hovers and clicks on stars to update the
visual rating and display the selected value.

File Structure
/Experiment_2_Star_Rating
├── index.html (HTML Structure, includes jQuery CDN)
├── style.css (CSS Styling for stars)
└── script.js (jQuery code for interaction)

Code

1. index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>Experiment 2: Star Rating</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-
awesome/6.5.1/css/all.min.css" integrity="sha512-
DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4Tc
tnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous"
referrerpolicy="no-referrer" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com"
crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;50
0;600;700&display=swap" rel="stylesheet">
</head>
<body>

9
B64

<div class="rating-container">
<h2>Rate this Product:</h2>
<div class="star-rating" id="star-rating-container">
<i class="fa-solid fa-star" data-value="1"></i><i
class="fa-solid fa-star" data-value="2"></i><i class="fa-solid
fa-star" data-value="3"></i><i class="fa-solid fa-star" data-
value="4"></i><i class="fa-solid fa-star" data-
value="5"></i></div>
<div id="rating-value" class="rating-value-
display">Rating: 0 / 5</div>
<input type="hidden" id="selected-rating" name="rating"
value="0">
</div>

<script src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
crossorigin="anonymous"></script>
<script src="script.js"></script> </body>
</html>

2. style.css:
/* Basic body styling */
body {
font-family: 'Inter', sans-serif;
background-color: #f0f2f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}

/* Container for the rating elements */


.rating-container {
background-color: #ffffff;
padding: 30px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
text-align: center;
}

/* Styling for the star rating container */


.star-rating {
font-size: 2.5rem; /* Size of the stars */
color: #d3d3d3; /* Default color for empty stars (light
gray) */
cursor: pointer; /* Indicate stars are clickable */
margin-bottom: 15px; /* Space below stars */
}

/* Styling for individual stars */


.star-rating .fa-star {
margin: 0 5px; /* Space between stars */
transition: color 0.2s ease-in-out; /* Smooth color

10
B64

transition */
}

/* Styling for stars on hover (temporary highlight) */


.star-rating .fa-star.hover {
color: #ffdd00; /* Yellow color on hover */
}

/* Styling for selected stars (permanent highlight) */


.star-rating .fa-star.selected {
color: #ffcc00; /* Slightly darker yellow for selected */
}

/* Styling for the text displaying the rating */


.rating-value-display {
margin-top: 15px;
font-size: 1.1rem;
font-weight: 500;
color: #555;
}

3. script.js:
// script.js - Star Rating Functionality using jQuery

// Ensure the script runs after the DOM is fully loaded


$(document).ready(function() {

// Select all star icons within the container


const stars = $('#star-rating-container .fa-star');
// Select the element to display the rating value
const ratingValueDisplay = $('#rating-value');
// Select the hidden input to store the rating (optional)
const selectedRatingInput = $('#selected-rating');

// Variable to store the currently selected rating (0 means


no rating)
let currentRating = 0;

// --- Hover Effect ---

// When the mouse enters a star


stars.on('mouseenter', function() {
const hoverValue = $(this).data('value'); // Get the
value (1-5) of the hovered star

// Add 'hover' class to stars up to the one being


hovered over
stars.each(function() {
if ($(this).data('value') <= hoverValue) {
$(this).addClass('hover'); // Highlight star
} else {
$(this).removeClass('hover'); // Ensure stars
beyond hover are not highlighted
}
});

11
B64

// Also ensure 'selected' class is removed during hover


preview if needed
stars.removeClass('selected');
});

// When the mouse leaves the star rating container area


$('#star-rating-container').on('mouseleave', function() {
// Remove the temporary 'hover' class from all stars
stars.removeClass('hover');
// Re-apply the 'selected' class based on the actual
clicked rating
stars.each(function() {
if ($(this).data('value') <= currentRating) {
$(this).addClass('selected'); // Keep selected
stars highlighted
} else {
$(this).removeClass('selected'); // Ensure
others are not highlighted
}
});
});

// --- Click Effect ---

// When a star is clicked


stars.on('click', function() {
currentRating = $(this).data('value'); // Store the
value of the clicked star

// Update the hidden input value (optional)


selectedRatingInput.val(currentRating);
// Update the display text
ratingValueDisplay.text(`Rating: ${currentRating} / 5`);

// Update the permanent 'selected' state for stars


stars.each(function() {
if ($(this).data('value') <= currentRating) {
$(this).addClass('selected'); // Add selected
class up to the clicked star
} else {
$(this).removeClass('selected'); // Remove
selected class from stars beyond
}
});
// Ensure hover effect is removed after click if mouse
is still over stars
stars.removeClass('hover');
});

}); // End of $(document).ready()

12
B64

Output

13
B64

Experiment 3) Program in Node js for streaming


application
Explanation
This experiment demonstrates a basic streaming application in Node.js. It shows
how to efficiently read data from a source (like a file) in chunks (streams) instead
of loading everything into memory at once.

Program Explanation
The program uses Node.js's built-in fs (File System) module. It creates a
readable stream from a sample text file (data.txt) and pipes this stream
directly to a writable stream (process.stdout, which represents the console
output), logging data chunk by chunk.

File Structure
/Experiment_3_Node_Streaming
├── streamApp.js (Node.js code)
└── data.txt (Sample data file to be streamed)

Code

1. data.txt: (Create this file with some sample text)


This is line 1 of the sample data file.
Node.js streams are powerful for handling large data.
This is line 3.
We are streaming this content chunk by chunk.
End of file.

2. streamApp.js:
// streamApp.js - Basic Node.js File Streaming Example

// Import the built-in 'fs' module


const fs = require('fs');
const path = require('path'); // To handle file paths correctly

// Define the path to the data file


const dataFilePath = path.join(__dirname, 'data.txt');

// Check if the data file exists


if (!fs.existsSync(dataFilePath)) {

14
B64

console.error(`Error: Data file not found at


${dataFilePath}`);
console.log('Please create a file named "data.txt" in the same
directory with some text content.');
process.exit(1); // Exit the script with an error code
}

// Create a readable stream from the data file


// encoding 'utf8' ensures we get strings instead of raw buffers
const readableStream = fs.createReadStream(dataFilePath, {
encoding: 'utf8' });

// --- Stream Event Handling (Optional but good practice) ---

// Event listener for when data is available to read


readableStream.on('data', (chunk) => {
// This event fires whenever a chunk of data is read
console.log('--- Received Chunk ---');
// process.stdout.write(chunk); // We pipe directly below, so
this isn't strictly needed here
});

// Event listener for when the stream has finished reading


readableStream.on('end', () => {
console.log('\n--- Stream Finished ---');
});

// Event listener for any errors during streaming


readableStream.on('error', (err) => {
console.error('--- Stream Error ---');
console.error(err);
});

// --- Piping the Stream ---


// Pipe the readable stream directly to the standard output
(console)
console.log('--- Starting Stream Pipe ---');
readableStream.pipe(process.stdout);

// Note: When you pipe, data automatically flows from readable


to writable.
// The 'data' event still fires, but piping is often simpler for
direct transfers.

15
B64

Output

16
B64

Experiment 4) Create an authentication app in


Node JS using OAuth
Explanation
This experiment demonstrates a user authentication flow in a Node.js web
application, mimicking concepts used in OAuth. It allows users to "log in" with
mock user data without needing external provider keys, making it easier to run
and understand the basic principles.

Program Explanation
The application uses Node.js with the Express framework and Passport.js for
session management. Instead of using an external OAuth provider strategy (like
Google), it uses a mock login route. When the user clicks "Mock Login", the
application manually logs in a predefined mock user using Passport's
req.login(), which utilizes serializeUser to store user info in a session
cookie via express-session. Routes are defined to handle this mock login and
logout.

File Structure
/Experiment_4_Node_Mock_Auth
├── app.js (Main application file)
├── package.json (Lists dependencies)
├── config/
│ ├── keys.js (Stores session key ONLY)
│ └── passport-setup.js (Passport configuration - simplified)
├── routes/
│ └── auth-routes.js (Authentication related routes - simplified)
└── views/ (EJS Template files)
├── login.ejs (Login page view - updated button)
└── profile.ejs (User profile page view)
└── home.ejs (Homepage view)

17
B64

Code
File: package.json
(Defines project metadata and dependencies)

{
"name": "exp4-node-mock-auth-fixed",
"version": "1.0.0",
"description": "Node.js Mock Auth Example using express-
session",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express-session": "^1.17.3",
"ejs": "^3.1.6",
"express": "^4.17.1",
"passport": "^0.6.0"
}
}

File: config/keys.js
(Stores configuration keys, like the session secret)

// config/keys.js
// Session secret key for express-session
module.exports = {
session: {
// express-session uses a 'secret' instead of 'keys' array
secret: 'aRandomSecretKeyForSessionEncryption' // Choose any
random string here!
}
};

File: config/passport-setup.js
(Configures Passport serialize/deserialize functions)

// config/passport-setup.js
const passport = require('passport');

// --- User Serialization/Deserialization ---


// Still needed for session management

// Decide what data to store in the session cookie


// We'll store our mock user object
passport.serializeUser((user, done) => {
console.log('Serializing user:', user.displayName);

18
B64

// Store user id (or whole object for simplicity) in session


done(null, user);
});

// Retrieve user data from the session cookie


passport.deserializeUser((user, done) => {
console.log('Deserializing user:', user.displayName);
// For mock, we retrieve the stored object directly
// In real app with DB, find user by ID stored in 'user'
done(null, user); // Makes user object available as req.user
});

// --- No External Strategy Needed ---


// We are not using GoogleStrategy or any external provider in
this mock version.
// The login logic will be handled directly in the auth route.

File: routes/auth-routes.js
(Defines routes related to authentication: login, logout, mock
login)

// routes/auth-routes.js
const router = require('express').Router();
const passport = require('passport'); // Still needed for
req.login/req.logout

// Auth login route (renders login page)


router.get('/login', (req, res) => {
res.render('login', { user: req.user });
});

// Auth logout
router.get('/logout', (req, res, next) => {
req.logout(function(err) {
if (err) { return next(err); }
res.redirect('/');
});
});

// Mock Login Route - Simulates a successful login


router.get('/mock', (req, res) => {
// Create a mock user object
const mockUser = {
id: 'mock12345',
displayName: 'Mock User',
// Add other fields if your profile page expects them
emails: [{ value: '[email protected]' }],
photos: [{ value: 'https://via.placeholder.com/50' }] //

19
B64

Placeholder image
};

// Use req.login() provided by Passport to establish a


session
// This calls serializeUser internally
req.login(mockUser, (err) => {
if (err) {
console.error("Mock login error:", err);
return res.redirect('/auth/login'); // Redirect to
login on error
}
// If login is successful, redirect to profile
console.log("Mock user logged in, redirecting to
profile...");
return res.redirect('/profile/');
});
});

module.exports = router;

File: views/home.ejs
(EJS template for the homepage)

<!DOCTYPE html>
<html>
<head>
<title>Mock Auth App Homepage</title>
<style> body { font-family: Arial, sans-serif; padding: 20px;
} a { margin: 5px; padding: 10px; background-color: #eee; text-
decoration: none; color: #333; border-radius: 4px;} </style>
</head>
<body>
<h1>Welcome to the Mock Auth App!</h1>
<% if (user) { %>
<p>You are logged in as <%= user.displayName %></p>
<a href="/profile">View Profile</a>
<a href="/auth/logout">Logout</a>
<% } else { %>
<p>Please login to continue.</p>
<a href="/auth/login">Login</a>
<% } %>
</body>
</html>

File: views/login.ejs
(EJS template for the login page)

20
B64

<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<style> body { font-family: Arial, sans-serif; padding: 20px;
} a { display: inline-block; margin-top: 10px; padding: 10px
15px; background-color: #4CAF50; color: white; text-decoration:
none; border-radius: 4px;} </style>
</head>
<body>
<h1>Login</h1>
<% if (user) { %>
<p>You are already logged in as <%= user.displayName %></p>
<a href="/profile">Go to Profile</a>
<a href="/auth/logout">Logout</a>
<% } else { %>
<p>Click the button to simulate login:</p>
<a href="/auth/mock">Mock Login</a>
<% } %>
</body>
</html>

File: views/profile.ejs
(EJS template for the user profile page)

<!DOCTYPE html>
<html>
<head>
<title>Profile</title>
<style> body { font-family: Arial, sans-serif; padding: 20px;
} img { border-radius: 50%; vertical-align: middle; margin-right:
10px;} a { margin-top: 15px; display: inline-block;}</style>
</head>
<body>
<h1>Your Profile</h1>
<% if (user) { %>
<p>
<% if (user.photos && user.photos.length > 0) { %>
<img src="<%= user.photos[0].value %>"
alt="Profile Picture" width="50" height="50">
<% } %>
<strong>Welcome, <%= user.displayName %>!</strong>
</p>
<p>Email: <%= user.emails && user.emails.length > 0 ?
user.emails[0].value : 'Not available' %></p>
<p>Mock ID: <%= user.id %></p>
<a href="/auth/logout">Logout</a>

21
B64

<br>
<a href="/">Go to Homepage</a>
<% } else { %>
<p>You need to be logged in to view this page.</p>
<a href="/auth/login">Login</a>
<% } %>
</body>
</html>

File: app.js
(Main application file: sets up Express, middleware, routes, and
starts server)

// app.js - Main application file (Mock Auth Version - Fixed)


const express = require('express');
// const cookieSession = require('cookie-session'); // Remove
this
const session = require('express-session'); // Add this
const passport = require('passport');
const authRoutes = require('./routes/auth-routes');
const passportSetup = require('./config/passport-setup');
const keys = require('./config/keys');

const app = express();

// Set up view engine


app.set('view engine', 'ejs');

// Set up session middleware using express-session


app.use(session({
secret: keys.session.secret, // Use the secret from keys.js
resave: false, // Don't save session if
unmodified
saveUninitialized: false, // Don't create session until
something stored
// cookie: { secure: true } // Optional: use secure cookies
in production (requires HTTPS)
}));

// Initialize passport and enable session support (AFTER session


middleware)
app.use(passport.initialize());
app.use(passport.session());

// Set up authentication routes


app.use('/auth', authRoutes);

22
B64

// Create home route


app.get('/', (req, res) => {
res.render('home', { user: req.user });
});

// Create profile route


app.get('/profile', (req, res) => {
// Render profile page, passing user data if available from
session
res.render('profile', { user: req.user });
});

// Start the server


const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`App now listening for requests on port
${PORT}`);
});

Output

23
B64

24
B64

Experiment 5) Create an application in Node JS to


send an email
Explanation
This experiment demonstrates how to send emails programmatically from a
Node.js application. It utilizes the Nodemailer library to connect to an SMTP
service (like Gmail) and dispatch email messages.

Program Explanation
The core logic involves using Nodemailer. First, a transporter object is
created and configured with the SMTP service details (host, port) and
authentication credentials (e.g., a Gmail address and its corresponding App
Password). Then, mailOptions are defined specifying the sender, recipient,
subject, and body of the email. Finally, the transporter.sendMail() method
is called with these options to send the email asynchronously. Proper credential
setup (like using Gmail App Passwords) is crucial for successful execution.

File Structure
/Experiment_5_Node_Email
├── package.json (Defines dependencies like Nodemailer)
└── sendEmail.js (The Node.js script to send the email)

Code
File: package.json
(Defines project metadata and dependencies)

{
"name": "exp5-node-email",
"version": "1.0.0",
"description": "Node.js email sending example using
Nodemailer",
"main": "sendEmail.js",
"scripts": {
"start": "node sendEmail.js"
},
"dependencies": {
"nodemailer": "^6.7.0"
}
}

25
B64

File: sendEmail.js
(Contains the Node.js code using Nodemailer to send an email -
Comments Removed)

const nodemailer = require('nodemailer');

const senderEmail = '[email protected]';


const senderAppPassword = 'YOUR_GMAIL_APP_PASSWORD';
const recipientEmail = '[email protected]';

let transporter = nodemailer.createTransport({


host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: senderEmail,
pass: senderAppPassword
}
});

let mailOptions = {
from: `"Your Name or App Name" <${senderEmail}>`,
to: recipientEmail,
subject: 'Test Email from Node.js App',
text: 'Hello! This is a test email sent from a Node.js
application using Nodemailer.',
html: '<b>Hello!</b><p>This is a test email sent from a
Node.js application using Nodemailer.</p>'
};

async function sendTestEmail() {


console.log(`Attempting to send email from ${senderEmail} to
${recipientEmail}...`);
try {
let info = await transporter.sendMail(mailOptions);
console.log('Email sent successfully!');
console.log('Message ID:', info.messageId);
} catch (error) {
console.error('Error sending email:');
console.error(error);
if (error.code === 'EAUTH' || error.responseCode === 535)
{
console.error('\nAuthentication Error: Check if your
sender email and App Password are correct.');
console.error('Make sure you generated and used an
App Password if using Gmail with 2FA.');
} else if (error.code === 'EENVELOPE') {
console.error('\nRecipient Error: Check if the

26
B64

recipient email address is valid.');


}
}
}

sendTestEmail();)

Output
Attempting to send email from [email protected] to
[email protected]...

Email sent successfully!

27
B64

Experiment 6) Create and deploy REST API based


web service using Node js
Explanation
[REST API banane aur deploy karne ka objective. API kya data provide karegi
aur kaunse operations (CRUD) support karegi.]

Program Explanation
[Node.js (with Express.js) ka use karke API endpoints (routes) kaise define kiye
gaye hain. HTTP methods (GET, POST, PUT, DELETE) ka use. Request handling
(req.params, req.query, req.body). Response sending (res.json, res.send, status
codes). Deployment platform (e.g., Heroku, Vercel, AWS) aur process ka brief.]

File Structure
[e.g.,
● server.js / app.js
● routes/api.js
● controllers/ (optional, for route logic)
● models/ (optional, for data structure/database interaction)
● Procfile / vercel.json (for deployment)]

Code
[Yahan javascript ... block mein Node.js (Express) code paste karna hai (server
setup, routes).]

// Node.js Server Code (e.g., server.js)


```javascript
// API Routes (e.g., routes/api.js)

Output
[Yahan API endpoints ko test karne ka example (using tools like Postman/curl)
aur expected JSON response dikhana hai. Deployed API ka URL mention karna
hai.]

28
B64

Experiment 7) Program to create a simple


calculator application using React JS
Explanation
This experiment involves building a functional simple calculator user interface
using the React JS library. It allows users to perform basic arithmetic operations.

Program Explanation
The provided code defines React components, likely intended for a single file
structure. An App class component manages the state, holding the sequence of
operations (numbers and operators) in an array (this.state.operations).
Separate components Display, Buttons, and Button handle rendering the
output screen and the calculator buttons. The handleClick method updates
the operations state based on button presses. A calculateOperations
method joins the operations array into a string and uses math.eval() (likely
from the mathjs library, which would need to be installed) to compute the result
upon pressing '='.

File Structure
/Experiment_7_React_Calculator
├── public/
│ └── index.html
├── src/
│ ├── App.js (Contains all React components and logic)
│ ├── App.css (Contains styling - CSS not provided in PDF)
│ └── index.js (Renders the App component)
└── package.json (Defines dependencies like react, react-dom, mathjs)

Code
src/App.js (Components and Logic):
import React, { Component } from 'react';
// import update from 'immutability-helper'; // Needed for
the $push syntax shown in PDF
import * as math from 'mathjs'; // Needed for math.eval and
math.format
// import './App.css'; // Assuming CSS is in App.css

29
B64

// Display Component
class Display extends Component {
render() {
// Join the operations array, default to '0' if empty
const string = this.props.data.join('') || '0';
return <div className="Display"> {string} </div>;
}
}

// Button Component
class Button extends Component {
render() {
return (
<div
onClick={this.props.onClick}
className="Button"
data-size={this.props.size} // For potential styling
of wider buttons
data-value={this.props.value} // The value passed to
handleClick
>
{this.props.label} {/* The text shown on the button
*/}
</div>
);
}
}

// Buttons Container Component


class Buttons extends Component {
render() {
// Renders the children Buttons passed to it
return <div className="Buttons"> {this.props.children}
</div>;
}
}

// Main App Component


class App extends Component {
constructor() {
super();
// Initialize state with an empty array for operations

30
B64

this.state = { operations: [] };
}

// Handles clicks on any button


handleClick = e => {
const value = e.target.getAttribute('data-value'); //
Get value from clicked button

switch (value) {
case 'clear':
// Clear the operations array
this.setState({
operations: [],
});
break;
case 'equal':
// Calculate the result
this.calculateOperations();
break;
default:
// Append the button value (number or operator) to
the operations array
// Using simple array concat instead of 'update'
helper for simplicity
const newOperations = [...this.state.operations,
value];
this.setState({
operations: newOperations,
});
break; // Added missing break statement
}
// Removed extra closing brace from PDF snippet
} // Added missing closing brace for handleClick

// Performs the calculation


calculateOperations = () => {
let result = this.state.operations.join(''); // Join
array into a string like "1+2*3"
if (result) {
try {
result = math.evaluate(result); // Use
math.evaluate (safer than eval)
result = math.format(result, { precision: 14 });
// Format result

31
B64

result = String(result); // Convert back to string


this.setState({
operations: [result], // Replace operations with
the result
});
} catch (error) {
// Handle potential errors during evaluation
(e.g., invalid expression)
this.setState({
operations: ['Error']
});
console.error("Calculation Error:", error);
}
}
}

render() {
return (
<div className="App"> {/* Assuming a root div with
class App */}
{/* Display component showing current
operations/result */}
<Display data={this.state.operations} />
{/* Container for all buttons */}
<Buttons>
{/* Row 1 */}
<Button onClick={this.handleClick} label="C"
value="clear" />
{/* PDF shows +/- and % here, not implemented in
logic */}
<Button label="+/-" value="null" /> {/*
Placeholder */}
<Button label="%" value="null" /> {/* Placeholder
*/}
<Button onClick={this.handleClick} label="/"
value="/" />
{/* Row 2 */}
<Button onClick={this.handleClick} label="7"
value="7" />
<Button onClick={this.handleClick} label="8"
value="8" />
<Button onClick={this.handleClick} label="9"
value="9" />
<Button onClick={this.handleClick} label="x"

32
B64

value="*" />
{/* Row 3 */}
<Button onClick={this.handleClick} label="4"
value="4" />
<Button onClick={this.handleClick} label="5"
value="5" />
<Button onClick={this.handleClick} label="6"
value="6" />
<Button onClick={this.handleClick} label="-"
value="-" />
{/* Row 4 */}
<Button onClick={this.handleClick} label="1"
value="1" />
<Button onClick={this.handleClick} label="2"
value="2" />
<Button onClick={this.handleClick} label="3"
value="3" />
<Button onClick={this.handleClick} label="+"
value="+" />
{/* Row 5 */}
<Button onClick={this.handleClick} label="0"
value="0" size="2"/> {/* Assuming size="2" makes it wider
*/}
<Button onClick={this.handleClick} label="."
value="." />
<Button onClick={this.handleClick} label="="
value="equal" />
</Buttons>
</div>
);
}
}

export default App;

.App {
width: 300px;
margin: 50px auto;
border: 1px solid #ccc;
border-radius: 5px;
overflow: hidden;
box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
}

33
B64

.Display {
background-color: #222;
color: white;
font-size: 2em;
padding: 15px;
text-align: right;
min-height: 1.5em;
line-height: 1.5em;
word-wrap: break-word;
}

.Buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
}

.Button {
background-color: #f0f0f0;
border: 1px solid #ccc;
padding: 20px 0;
font-size: 1.2em;
text-align: center;
cursor: pointer;
user-select: none;
}

.Button:hover {
background-color: #e0e0e0;
}

.Button:active {
background-color: #d0d0d0;
}

.Button[data-value="/"],
.Button[data-value="*"],
.Button[data-value="-"],
.Button[data-value="+"],
.Button[data-value="equal"] {
background-color: #ff9800;
color: white;
}
.Button[data-value="/"]:hover,
.Button[data-value="*"]:hover,

34
B64

.Button[data-value="-"]:hover,
.Button[data-value="+"]:hover,
.Button[data-value="equal"]:hover {
background-color: #f57c00;
}

.Button[data-value="clear"] {
background-color: #e0e0e0;
}
.Button[data-value="clear"]:hover {
background-color: #d0d0d0;
}

.Button[data-size="2"] {
grid-column: span 2;
}

Output

35
B64

Experiment 8) Program to create a voting


application using React JS
Explanation
This experiment demonstrates building a basic, interactive voting application
user interface using React JS.

Program Explanation
The code utilizes React loaded via CDN and the useState hook to manage the
state of different voting options (name and vote count). A single functional App
component renders the list of options, displays vote counts, and provides
buttons. Clicking a "Vote" button triggers the handleVote function, which
updates the state immutably to increment the respective option's vote count.
Embedded CSS provides styling, and the Babel CDN transpiles the JSX code
within the browser.

File Structure
/Experiment_8_React_Voting
└── index.html (Contains HTML, CSS, React/JSX code, and CDN links)

Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>Experiment 8: React Voting App (Preview)</title>

<script
src="https://unpkg.com/react@18/umd/react.development.js"
crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-
dom.development.js" crossorigin></script>

<script
src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

<style>
/* --- CSS Code --- */
/* Basic styling for the voting app */

36
B64

body {
font-family: sans-serif;
background-color: #f0f2f5; /* Apply background to body
*/
display: flex; /* Use flex to center the app */
justify-content: center;
align-items: flex-start; /* Align top */
min-height: 100vh;
padding-top: 40px; /* Add some padding at the top */
margin: 0;
}

.App {
/* font-family: sans-serif; */ /* Moved to body */
max-width: 500px;
/* margin: 40px auto; */ /* Centered by body flex */
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
background-color: #f9f9f9;
width: 90%; /* Ensure it doesn't stretch too wide on
large screens */
}

h1, h2 {
text-align: center;
color: #333;
}

.options-list {
list-style: none;
padding: 0;
margin-top: 20px;
}

.option-item {
background-color: #fff;
border: 1px solid #eee;
border-radius: 5px;
padding: 15px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
transition: box-shadow 0.2s ease-in-out;
}

37
B64

.option-item:hover {
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}

.option-name {
font-size: 1.1em;
font-weight: 500;
}

.vote-count {
font-size: 1em;
color: #555;
margin: 0 15px; /* Added margin for spacing */
font-weight: bold;
}

.vote-button {
background-color: #007bff;
color: white;
border: none;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 0.9em;
transition: background-color 0.2s ease-in-out;
}

.vote-button:hover {
background-color: #0056b3;
}

.results-section {
margin-top: 30px;
padding-top: 20px;
border-top: 1px dashed #ccc;
}
</style>
</head>
<body>
<div id="root"></div>

<script type="text/babel">
const { useState } = React; // Destructure useState from
React

function App() {
// Initial state for voting options

38
B64

const [options, setOptions] = useState([


{ id: 1, name: 'Option A', votes: 0 },
{ id: 2, name: 'Option B', votes: 0 },
{ id: 3, name: 'Option C', votes: 0 },
{ id: 4, name: 'Option D', votes: 0 },
]);

// Function to handle voting


const handleVote = (optionId) => {
// Update the state immutably
setOptions(prevOptions =>
prevOptions.map(option =>
// If the option id matches, increment its vote
count
option.id === optionId ? { ...option, votes:
option.votes + 1 } : option
)
);
console.log(`Voted for option ID: ${optionId}`); // Log
vote action
};

// Calculate total votes (optional, for display)


const totalVotes = options.reduce((sum, option) => sum +
option.votes, 0);

return (
<div className="App">
<h1>React Voting App</h1>

<div className="options-section">
<h2>Cast Your Vote:</h2>
<ul className="options-list">
{options.map(option => (
<li key={option.id} className="option-item">
<div>
<span className="option-
name">{option.name}</span>
</div>
{/* Wrap vote count and button for better
alignment */}
<div style={{ display: 'flex', alignItems:
'center' }}>
{/* Display current votes */}
<span className="vote-count">Votes:
{option.votes}</span>
{/* Button to vote for this option */}
<button

39
B64

className="vote-button"
onClick={() => handleVote(option.id)} //
Call handleVote with option's id
>
Vote
</button>
</div>
</li>
))}
</ul>
</div>

{/* Optional: Display results or total votes */}


<div className="results-section">
<h2>Results:</h2>
<p>Total Votes Cast: {totalVotes}</p>
{/* You could add more detailed results display
here if needed */}
</div>
</div>
);
}

// Render the App component into the 'root' div


// Using the new React 18 createRoot API
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(<App />);

</script>
</body>
</html>

40
B64

Output

41
B64

Experiment 9) Create a Simple Login form using


React JS
Explanation
This experiment demonstrates the creation of a basic user login form using
React JS. It includes input fields for username and password, submission
handling, and simple validation against predefined user credentials.

Program Explanation
The code uses a React functional component (App) with the useState hook to
manage error messages and the form submission status (isSubmitted). An
array (database) holds hardcoded username/password pairs for validation. The
handleSubmit function prevents default form submission, retrieves input
values, finds the matching user, checks the password, and updates the state
either to show an error message (using renderErrorMessage) or a success
message. Basic styling is provided via CSS (App.css).

File Structure
/Experiment_9_React_Login
├── public/
│ └── index.html
├── src/
│ ├── App.js (Contains the React component logic)
│ ├── App.css (Contains CSS styling)
│ └── index.js (Renders the App component)
└── package.json (Defines dependencies like react, react-dom)

Code
src/App.js:
import './App.css';
import React, { useState } from "react";
// import ReactDOM from "react-dom"; // ReactDOM is usually used
in index.js

function App() {

42
B64

// React States
const [errorMessages, setErrorMessages] = useState({});
const [isSubmitted, setIsSubmitted] = useState(false);

// User Login info (Hardcoded)


const database = [
{
username: "user1",
password: "pass1"
},
{
username: "user2",
password: "pass2"
}
];

// Error messages
const errors = {
uname: "invalid username",
pass: "invalid password"
};

const handleSubmit = (event) => {


//Prevent page reload
event.preventDefault();

// Get form values using event target (more React-idiomatic


than document.forms)
// Assuming input names are 'uname' and 'pass'
const uname = event.target.uname.value;
const pass = event.target.pass.value;

// Find user login info


const userData = database.find((user) => user.username ===
uname);

// Compare user info


if (userData) {
if (userData.password !== pass) {
// Invalid password
setErrorMessages({ name: "pass", message: errors.pass });
} else {
// Login successful
setIsSubmitted(true);
}
} else {
// Username not found
setErrorMessages({ name: "uname", message: errors.uname });

43
B64

}
};

// Generate JSX code for error message


const renderErrorMessage = (name) =>
name === errorMessages.name && (
<div className="error">{errorMessages.message}</div>
);

// JSX code for login form


const renderForm = (
<div className="form">
<form onSubmit={handleSubmit}>
<div className="input-container">
<label>Username </label>
{/* Use controlled components or leave as uncontrolled
with name attribute */}
<input type="text" name="uname" required />
{renderErrorMessage("uname")}
</div>
<div className="input-container">
<label>Password </label>
<input type="password" name="pass" required />
{renderErrorMessage("pass")}
</div>
<div className="button-container">
<input type="submit" />
</div>
</form>
</div>
);

return (
<div className="app">
<div className="login-form">
<div className="title">Sign In</div>
{/* Conditionally render success message or login form
*/}
{isSubmitted ? <div>User is successfully logged in</div>
: renderForm}
</div>
</div>
);
}

export default App;

src/App.css:

44
B64

.app {
font-family: sans-serif;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 20px;
height: 100vh;
/* font-family: Cambria, Cochin, Georgia, Times, "Times New
Roman", serif; */ /* Overridden by sans-serif above */
background-color: #f8f9fd;
}

input[type="text"],
input[type="password"] {
height: 25px;
border: 1px solid rgba(0, 0, 0, 0.2);
padding: 5px 10px; /* Added padding for better appearance */
border-radius: 3px; /* Added border-radius */
font-size: 1em; /* Added font-size */
}

input[type="submit"] {
margin-top: 10px;
cursor: pointer;
font-size: 15px;
background: #01d28e;
border: 1px solid #01d28e;
color: #fff;
padding: 10px 20px;
border-radius: 3px; /* Added border-radius */
}

input[type="submit"]:hover {
background: #6cf0c2;
}

.button-container {
display: flex;
justify-content: center;
}

.login-form {
background-color: white;
padding: 2rem;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0
rgba(0, 0, 0, 0.19);
border-radius: 5px; /* Added border-radius */

45
B64

/* .list-container { */ /* Not used in the provided JS */


/* display: flex; */
/* } */

.error {
color: red;
font-size: 12px;
}

.title {
font-size: 25px;
margin-bottom: 20px;
text-align: center; /* Added text-align */
}

.input-container {
display: flex;
flex-direction: column;
gap: 8px;
margin: 10px;
}

/* Added label styling */


label {
font-weight: bold;
font-size: 0.9em;
}

46
B64

Output

47
B64

Experiment 10) Program to perform input


validation using Angular JS
Explanation
Objective: To implement client-side form input validation using AngularJS (v1.x)
directives within a single HTML file runnable via CDN.

Program Explanation
Implementation: Utilizes AngularJS (CDN) with ng-model for data binding.
Validation rules (required, ng-minlength, min, max, type="email",
type="number") are applied in HTML. Error messages display conditionally
using ng-show based on form state ($touched, $invalid, $error). The
submit button uses ng-disabled="myForm.$invalid" for dynamic state
control.

File Structure
/Experiment_10_AngularJS_Validation
└── index.html (Contains HTML, CSS, AngularJS script, and CDN link)

Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>Experiment 10: AngularJS Validation</title>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angula
r.min.js"></script>

<style>
body {
font-family: sans-serif;
padding: 20px;
background-color: #f4f4f4;
}
.container {
background-color: #fff;
padding: 30px;
border-radius: 8px;

48
B64

box-shadow: 0 2px 5px rgba(0,0,0,0.1);


max-width: 500px;
margin: auto;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #333;
}
input[type="text"],
input[type="email"],
input[type="number"] {
width: calc(100% - 20px); /* Adjust width considering
padding */
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1em;
}
/* Style for invalid inputs */
input.ng-invalid.ng-touched {
border-color: #dc3545; /* Red border for invalid
touched fields */
background-color: #f8d7da; /* Light red background */
}
/* Style for valid inputs */
input.ng-valid.ng-touched {
border-color: #28a745; /* Green border for valid
touched fields */
}

.error-message {
color: #dc3545; /* Red color for error messages */
font-size: 0.9em;
margin-top: 5px;
padding-left: 5px;
}
button {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;

49
B64

font-size: 1em;
transition: background-color 0.2s;
}
button:hover:not(:disabled) {
background-color: #0056b3;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
h2 {
text-align: center;
color: #333;
margin-bottom: 25px;
}
</style>
</head>
<body ng-app="validationApp">

<div class="container" ng-controller="validationCtrl">


<h2>AngularJS Validation Form</h2>

<form name="myForm" novalidate>

<div class="form-group">
<label for="nameInput">Name:</label>
<input type="text"
id="nameInput"
name="myName"
ng-model="user.name"
required
ng-minlength="3"
placeholder="Enter your name (min 3
chars)">

<div ng-show="myForm.myName.$touched &&


myForm.myName.$invalid" class="error-message">
<span ng-
show="myForm.myName.$error.required">Name is required.</span>
<span ng-
show="myForm.myName.$error.minlength">Name must be at least 3
characters long.</span>
</div>
</div>

<div class="form-group">
<label for="emailInput">Email:</label>
<input type="email"

50
B64

id="emailInput"
name="myEmail"
ng-model="user.email"
required
placeholder="Enter a valid email address">

<div ng-show="myForm.myEmail.$touched &&


myForm.myEmail.$invalid" class="error-message">
<span ng-
show="myForm.myEmail.$error.required">Email is required.</span>
<span ng-
show="myForm.myEmail.$error.email">Please enter a valid email
address.</span>
</div>
</div>

<div class="form-group">
<label for="ageInput">Age:</label>
<input type="number"
id="ageInput"
name="myAge"
ng-model="user.age"
required
min="18"
max="100"
placeholder="Enter age (18-100)">

<div ng-show="myForm.myAge.$touched &&


myForm.myAge.$invalid" class="error-message">
<span ng-
show="myForm.myAge.$error.required">Age is required.</span>
<span ng-show="myForm.myAge.$error.min">Age
must be at least 18.</span>
<span ng-show="myForm.myAge.$error.max">Age
cannot be more than 100.</span>
<span ng-
show="myForm.myAge.$error.number">Please enter a valid
number.</span>
</div>
</div>

<button type="submit" ng-


disabled="myForm.$invalid">Submit</button>

</form>

</div>

51
B64

<script>
// Define the AngularJS application module
var app = angular.module('validationApp', []);

// Define the controller


app.controller('validationCtrl', function($scope) {
// You can initialize the model if needed
$scope.user = {
name: '',
email: '',
age: null
};
});
</script>

</body>
</html>

Output

52
B64

Experiment 11) Program to store student


information using Angular JS
Explanation
Objective: To create a simple single-page application using AngularJS (v1.x) to
add, display, and delete student records (Name, Roll No, Grade) dynamically in
a list.

Program Explanation
Implementation: Uses AngularJS (CDN) with ng-model for two-way data binding
between form inputs ($scope.newStudent object) and the view. An array
($scope.students) in the controller's scope holds the student list data. The
ng-repeat directive iterates through this array to display students in an HTML
table. ng-click triggers controller functions: addStudent() copies
$scope.newStudent to the array and clears the form, while
deleteStudent(index) uses the $index provided by ng-repeat to remove
a student via splice. Basic form validation (required) and ng-disabled
control the "Add Student" button's state.

File Structure
/Experiment_11_AngularJS_Student_Info
└── index.html (Contains HTML, CSS, AngularJS script, and CDN link)

Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>Experiment 11: AngularJS Student Info</title>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angula
r.min.js"></script>

<style>
body {
font-family: sans-serif;
padding: 20px;
background-color: #f8f9fa;

53
B64

}
.container {
background-color: #fff;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
max-width: 700px; /* Wider container */
margin: auto;
}
.form-container, .table-container {
margin-bottom: 30px;
}
.form-inline .form-group {
display: inline-block; /* Display form groups inline
*/
margin-right: 15px;
margin-bottom: 10px;
vertical-align: top;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #333;
}
input[type="text"],
input[type="number"] {
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 0.95em;
}
input.ng-invalid.ng-touched {
border-color: #dc3545;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
}
th, td {
border: 1px solid #dee2e6;
padding: 10px;
text-align: left;
}
th {
background-color: #e9ecef;
font-weight: bold;

54
B64

}
tr:nth-child(even) {
background-color: #f8f9fa;
}
button {
background-color: #007bff;
color: white;
padding: 8px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.9em;
transition: background-color 0.2s;
vertical-align: bottom; /* Align button with bottom
of inputs */
margin-top: 24px; /* Align with inputs */
}
button.delete-btn {
background-color: #dc3545;
padding: 5px 10px;
font-size: 0.8em;
margin-top: 0; /* Reset margin for table button */
}
button:hover:not(:disabled) {
background-color: #0056b3;
}
button.delete-btn:hover {
background-color: #c82333;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
h2, h3 {
color: #333;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
margin-bottom: 20px;
}
.error-message {
color: #dc3545;
font-size: 0.8em;
margin-top: 3px;
}
</style>
</head>
<body ng-app="studentApp">

55
B64

<div class="container" ng-controller="studentCtrl">


<h2>Experiment 11: Store Student Information
(AngularJS)</h2>

<div class="form-container">
<h3>Add New Student</h3>
<form name="addForm" ng-submit="addStudent()"
class="form-inline" novalidate>
<div class="form-group">
<label for="name">Name:</label>
<input type="text" id="name"
name="studentName" ng-model="newStudent.name" required
placeholder="Student Name">
<div ng-show="addForm.studentName.$touched
&& addForm.studentName.$invalid" class="error-message">
<span ng-
show="addForm.studentName.$error.required">Name is
required.</span>
</div>
</div>
<div class="form-group">
<label for="roll">Roll No:</label>
<input type="number" id="roll"
name="studentRoll" ng-model="newStudent.roll" required
placeholder="Roll Number">
<div ng-show="addForm.studentRoll.$touched
&& addForm.studentRoll.$invalid" class="error-message">
<span ng-
show="addForm.studentRoll.$error.required">Roll No is
required.</span>
<span ng-
show="addForm.studentRoll.$error.number">Enter a valid
number.</span>
</div>
</div>
<div class="form-group">
<label for="grade">Grade:</label>
<input type="text" id="grade"
name="studentGrade" ng-model="newStudent.grade" required
placeholder="e.g., A, B+">
<div ng-show="addForm.studentGrade.$touched
&& addForm.studentGrade.$invalid" class="error-message">
<span ng-
show="addForm.studentGrade.$error.required">Grade is
required.</span>
</div>
</div>
<div class="form-group">

56
B64

<button type="submit" ng-


disabled="addForm.$invalid">Add Student</button>
</div>
</form>
</div>

<div class="table-container">
<h3>Student List</h3>
<table>
<thead>
<tr>
<th>Name</th>
<th>Roll No</th>
<th>Grade</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="student in students track by
$index">
<td>{{ student.name }}</td>
<td>{{ student.roll }}</td>
<td>{{ student.grade }}</td>
<td>
<button class="delete-btn" ng-
click="deleteStudent($index)">Delete</button>
</td>
</tr>
<tr ng-if="students.length === 0">
<td colspan="4" style="text-align:
center; color: grey;">No students added yet.</td>
</tr>
</tbody>
</table>
</div>

</div>

<script>
// Define the AngularJS application module
var app = angular.module('studentApp', []);

// Define the controller


app.controller('studentCtrl', function($scope) {

// Initial array of students (can be empty or have


sample data)
$scope.students = [

57
B64

{ name: 'Amit Kumar', roll: 101, grade: 'A' },


{ name: 'Priya Sharma', roll: 102, grade: 'B+' }
];

// Object to hold data for the new student form


$scope.newStudent = { name: '', roll: null, grade: ''
};

// Function to add a new student


$scope.addStudent = function() {
// Check if form is valid (though button disables
it, good practice)
if ($scope.addForm.$valid) {
// Push a copy of newStudent to the students
array

$scope.students.push(angular.copy($scope.newStudent));

// Clear the form by resetting newStudent


$scope.newStudent = { name: '', roll: null,
grade: '' };

// Optional: Mark form as pristine


(untouched) after submission
$scope.addForm.$setPristine();
$scope.addForm.$setUntouched();
}
};

// Function to delete a student by index


$scope.deleteStudent = function(index) {
// Confirm before deleting (optional)
// if (confirm('Are you sure you want to delete
this student?')) {
$scope.students.splice(index, 1); // Remove 1
element at the given index
// }
};
});
</script>

</body>
</html>

58
B64

Output

59
B64

Experiment 12) Design and development of online


job portal using Node.js & React.js
Explanation
Objective: To design and outline the development of a full-stack online job portal
application using Node.js for the backend API and React.js for the frontend user
interface, allowing users to browse and view job listings.

Program Explanation
The application consists of two main parts:

1. Backend (Node.js/Express): This server-side component is responsible for


managing job data (potentially storing/retrieving from a database like
MongoDB), handling user authentication (optional for basic version), and
providing a RESTful API for the frontend to consume. It would typically use the
Express.js framework.
2. Frontend (React.js): This client-side component provides the user interface. It
fetches job data from the backend API, displays listings, allows users to search
or filter jobs (optional), view detailed job descriptions, and potentially apply. It's
built using React components, state management, and asynchronous API calls.

File Structure
/Experiment_12_Online_Job_Portal

├── backend/

│ ├── server.js (Main server file)

│ ├── package.json (Backend dependencies)

│ ├── routes/ (API route definitions, e.g., jobs.js, auth.js)

│ └── models/ (Database models, e.g., Job.js, User.js - Optional)

│ └── config/ (Configuration files, e.g., db connection, keys -


Optional)

└── frontend/ (Standard React App structure)

├── public/

│ └── index.html

├── src/

60
B64

│ ├── App.js (Main React application component)

│ ├── components/ (Reusable UI components, e.g., JobList, JobDetail)

│ ├── services/ (Functions for API calls - Optional)

│ ├── App.css

│ └── index.js

└── package.json (Frontend dependencies)

Code
// src/App.js (Structure Example)
import React, { useState, useEffect, useMemo } from 'react';
// import JobList from './components/JobList'; // Assuming
components are separated
// import JobDetail from './components/JobDetail';
// import apiService from './services/api'; // Assuming API
service file

function App() {
const [jobs, setJobs] = useState([]); // Initially empty,
fetched from API
const [selectedJobId, setSelectedJobId] = useState(null);
const [searchTerm, setSearchTerm] = useState('');
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

// Fetch jobs from backend API on component mount


useEffect(() => {
const fetchJobs = async () => {
try {
setLoading(true);
// const data = await apiService.getJobs(); // Replace
mock data with API call
// setJobs(data);
setJobs(MOCK_JOBS); // Using mock data for structure
example
setError(null);
} catch (err) {
setError('Failed to fetch jobs.');
console.error(err);
} finally {
setLoading(false);
}
};
fetchJobs();

61
B64

}, []); // Empty dependency array runs once on mount

// (handleViewDetails, handleBackToList, handleSearchChange,


filteredJobs logic remains similar)
// ... [Rest of the component logic from previewable code] ...

// Find the selected job object


const selectedJob = jobs.find(job => job.id ===
selectedJobId);

return (
<div className="container mx-auto max-w-3xl">
<h1 className="text-3xl font-bold text-center mb-8 text-
gray-800">Online Job Portal</h1>
{loading && <p className="text-center">Loading
jobs...</p>}
{error && <p className="text-center text-red-
500">{error}</p>}

{!loading && !error && !selectedJob ? (


<div> {/* Search and List View */}
{/* Search Input */}
<div className="mb-6 relative">
{/* ... search input JSX ... */}
</div>
{/* Job List */}
{/* <JobList jobs={filteredJobs}
onViewDetails={handleViewDetails} /> */}
<p>(Job List Component would render here)</p>
</div>
) : null}

{!loading && !error && selectedJob ? (


<div> {/* Detail View */}
{/* <JobDetail job={selectedJob}
onBack={handleBackToList} /> */}
<p>(Job Detail Component for '{selectedJob.title}'
would render here)</p>
<button onClick={handleBackToList}>Back</button> {/*
Example back button */}
</div>
) : null}

</div>
);
}
// Mock data needed for this snippet example if not fetching
const MOCK_JOBS = [ { id: 1, title: 'Sample Job', company:

62
B64

'Sample Co', location: 'Sample Location', description: '...' } ];

export default App;

// --- Other Components (JobList.js, JobDetail.js, JobItem.js) --


-
// Snippets for these would be similar to the previewable
version,
// potentially importing icons and using props passed from
App.js.
// backend/package.json (Example)
/*
{
"name": "job-portal-backend",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js" // If using nodemon
},
"dependencies": {
"express": "^4.17.1",
"cors": "^2.8.5", // For handling Cross-Origin Resource
Sharing
"mongoose": "^6.0.0" // Example if using MongoDB
// Add other dependencies like dotenv, bcrypt, jsonwebtoken
if needed
},
"devDependencies": {
"nodemon": "^2.0.0" // Optional for development
}
}
*/

// backend/models/Job.js (Example Mongoose Model - Optional)


/*
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const jobSchema = new Schema({


title: { type: String, required: true },
company: { type: String, required: true },
location: { type: String },
description: { type: String, required: true },
postedDate: { type: Date, default: Date.now }
// Add other fields like salary, requirements, etc.
});

63
B64

module.exports = mongoose.model('Job', jobSchema);


*/

// backend/routes/jobs.js (Example API Route)


const express = require('express');
const router = express.Router();
// const Job = require('../models/Job'); // Import model if using
DB

// Mock data for backend example


const mockBackendJobs = [
{ id: 101, title: 'Backend Dev', company: 'Server Side LLC',
location: 'Remote', description: 'Node.js expert needed.' },
{ id: 102, title: 'API Specialist', company: 'Connections
Ltd.', location: 'Cloud City', description: 'Build and maintain
REST APIs.' }
];

// GET /api/jobs - Fetch all jobs


router.get('/', async (req, res) => {
try {
// In real app: const jobs = await Job.find().sort({
postedDate: -1 });
console.log('API: Fetching jobs');
res.json(mockBackendJobs); // Sending mock data
} catch (err) {
console.error("API Error fetching jobs:", err);
res.status(500).json({ message: 'Server Error' });
}
});

// POST /api/jobs - Add a new job (Example structure)


router.post('/', async (req, res) => {
// Add validation and logic to create a new job in DB
console.log('API: Received new job data:', req.body);
// const newJob = new Job({...req.body});
// await newJob.save();
res.status(201).json({ message: 'Job created (mock)', data:
req.body });
});

module.exports = router;

// backend/server.js (Example Express Server Setup)


const express = require('express');

64
B64

const cors = require('cors');


// const mongoose = require('mongoose'); // If using MongoDB
// require('dotenv').config(); // If using .env file

const app = express();


const PORT = process.env.PORT || 5000; // Backend port

// Middleware
app.use(cors()); // Enable CORS for frontend requests
app.use(express.json()); // Parse JSON request bodies

// --- Database Connection (Example - if using MongoDB) ---


/*
const dbURI = process.env.MONGODB_URI ||
'mongodb://localhost:27017/jobportal';
mongoose.connect(dbURI, { useNewUrlParser: true,
useUnifiedTopology: true })
.then(() => console.log('MongoDB connected...'))
.catch(err => console.error('MongoDB connection error:', err));
*/

// --- API Routes ---


app.use('/api/jobs', require('./routes/jobs'));
// app.use('/api/auth', require('./routes/auth')); // If auth is
added

// Basic route
app.get('/', (req, res) => {
res.send('Job Portal Backend API Running');
});

app.listen(PORT, () => {
console.log(`Backend server running on port ${PORT}`);
});

65
B64

Output

66
B64

Experiment 13) Design and development of Online


Book Shop using Node.js & React.js
Explanation
Objective: To design and outline the development of a full-stack online book
shop application. This involves using Node.js to create a backend API for
managing book data and React.js to build the frontend user interface for
browsing and interacting with books.

Program Explanation
The application comprises two main parts:

1. Backend (Node.js/Express): This server-side component manages book


inventory data (potentially via a database like MongoDB), handles user accounts
(optional), processes cart and order logic (optional), and exposes a RESTful API.
It typically utilizes the Express.js framework.
2. Frontend (React.js): This client-side component interacts with the user. It
fetches book data from the backend API, displays books in a list or grid format,
shows detailed information for selected books, allows users to add items to a
shopping cart, and displays the cart status. It is built using React components,
state management, and asynchronous API calls.

File Structure
/Experiment_13_Online_Book_Shop

├── backend/

│ ├── server.js (Main server file)

│ ├── package.json (Backend dependencies)

│ ├── routes/ (API routes, e.g., books.js, cart.js, auth.js)

│ └── models/ (Database models, e.g., Book.js, User.js - Optional)

│ └── config/ (Configuration files - Optional)

└── frontend/ (Standard React App structure)

├── public/

│ └── index.html

├── src/

67
B64

│ ├── App.js (Main React application component)

│ ├── components/ (UI components, e.g., BookList, BookDetail, Header)

│ ├── services/ (API call functions - Optional)

│ ├── App.css

│ └── index.js

└── package.json (Frontend dependencies)

Code
// src/App.js (Structure Example)
import React, { useState, useEffect } from 'react';
// import Header from './components/Header';
// import BookList from './components/BookList';
// import BookDetail from './components/BookDetail';
// import apiService from './services/api'; // Example API
service

// Mock data (replace with API call in useEffect)


const MOCK_BOOKS = [ { id: 'b1', title: 'Sample Book', author:
'Sample Author', price: 9.99, description: '...', imageUrl: '...'
} ];

function App() {
const [books, setBooks] = useState([]);
const [selectedBookId, setSelectedBookId] = useState(null);
const [cartItemCount, setCartItemCount] = useState(0);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

// Fetch books from backend API on component mount


useEffect(() => {
const fetchBooks = async () => {
try {
setLoading(true);
// const data = await apiService.getBooks(); // API call
// setBooks(data);
setBooks(MOCK_BOOKS); // Using mock data
setError(null);
} catch (err) {
setError('Failed to fetch books.');
console.error(err);
} finally {
setLoading(false);
}
};

68
B64

fetchBooks();
}, []);

const handleViewDetails = (id) => setSelectedBookId(id);


const handleBackToList = () => setSelectedBookId(null);

const handleAddToCart = (book) => {


setCartItemCount(prevCount => prevCount + 1);
console.log(`Added ${book.title} to cart.`);
// Add more complex cart logic here (e.g., update cart state
array)
};

const selectedBook = books.find(book => book.id ===


selectedBookId);

return (
<div>
{/* <Header cartItemCount={cartItemCount} /> */}
<p>(Header Component with Cart: {cartItemCount} items)</p>
<main className="container mx-auto max-w-6xl px-4 py-4">
{loading && <p>Loading books...</p>}
{error && <p className="text-red-500">{error}</p>}
{!loading && !error ? (
selectedBook ? (
// <BookDetail book={selectedBook}
onBack={handleBackToList} onAddToCart={handleAddToCart} />
<div>
<p>(Book Detail Component for
'{selectedBook.title}')</p>
<button
onClick={handleBackToList}>Back</button>
</div>
) : (
// <BookList books={books}
onViewDetails={handleViewDetails} onAddToCart={handleAddToCart}
/>
<p>(Book List Component displaying
{books.length} books)</p>
)
) : null }
</main>
{/* Footer */}
</div>
);
}

export default App;

69
B64

// --- Other Components (Header.js, BookList.js, BookDetail.js,


BookItem.js) ---
// Snippets for these would be similar to the previewable
version,
// potentially importing icons and using props passed from
App.js.

Backend (Node.js/Express - Example Snippets)


// backend/package.json (Example)
/*
{
"name": "book-shop-backend",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.17.1",
"cors": "^2.8.5",
"mongoose": "^6.0.0" // Example if using MongoDB
}
}
*/

// backend/models/Book.js (Example Mongoose Model - Optional)


/*
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const bookSchema = new Schema({


title: { type: String, required: true },
author: { type: String, required: true },
price: { type: Number, required: true },
description: { type: String },
imageUrl: { type: String },
isbn: { type: String, unique: true }, // Example additional
field
stock: { type: Number, default: 0 }
});

module.exports = mongoose.model('Book', bookSchema);


*/

// backend/routes/books.js (Example API Route)


const express = require('express');

70
B64

const router = express.Router();


// const Book = require('../models/Book'); // Import model if
using DB

// Mock data for backend example


const mockBackendBooks = [
{ id: 'b1', title: 'The Midnight Library', author: 'Matt Haig',
price: 14.99 },
{ id: 'b2', title: 'Project Hail Mary', author: 'Andy Weir',
price: 18.50 },
// ... more books
];

// GET /api/books - Fetch all books


router.get('/', async (req, res) => {
try {
// In real app: const books = await Book.find();
console.log('API: Fetching books');
res.json(mockBackendBooks); // Sending mock data
} catch (err) {
console.error("API Error fetching books:", err);
res.status(500).json({ message: 'Server Error' });
}
});

// GET /api/books/:id - Fetch a single book by ID (Example)


router.get('/:id', async (req, res) => {
try {
// In real app: const book = await
Book.findById(req.params.id);
const book = mockBackendBooks.find(b => b.id ===
req.params.id);
if (!book) {
return res.status(404).json({ message: 'Book not found'
});
}
console.log(`API: Fetching book with ID: ${req.params.id}`);
res.json(book);
} catch (err) {
console.error("API Error fetching book:", err);
res.status(500).json({ message: 'Server Error' });
}
});

module.exports = router;

// backend/server.js (Example Express Server Setup)

71
B64

const express = require('express');


const cors = require('cors');
// const mongoose = require('mongoose');

const app = express();


const PORT = process.env.PORT || 5001; // Use a different port
from frontend

// Middleware
app.use(cors());
app.use(express.json());

// --- Database Connection (Example) ---


/*
mongoose.connect('mongodb://localhost:27017/bookshop')
.then(() => console.log('MongoDB connected...'))
.catch(err => console.error('MongoDB connection error:', err));
*/

// --- API Routes ---


app.use('/api/books', require('./routes/books'));
// Add other routes for cart, orders, users etc.

// Basic route
app.get('/', (req, res) => {
res.send('Book Shop Backend API Running');
});

app.listen(PORT, () => {
console.log(`Backend server running on port ${PORT}`);
});

72
B64

Output

73
B64

Experiment 14) Create a project on Grocery


delivery application
Explanation
Objective: To outline the development of a grocery application frontend using
React. This involves displaying grocery products fetched from a data source and
integrating with a third-party service like SnipCart for cart functionality.

Program Explanation
Implementation: The code uses React components (App, Product). The main
App component imports product data from a local products.json file. It then
maps through this data, rendering a Product component for each item within a
grid layout. The Product component displays details like image, name,
description, and price. Crucially, it includes an "Add to Cart" button with specific
snipcart-add-item class and data-item-* attributes, indicating reliance on
the external SnipCart service to handle the shopping cart and checkout process.

File Structure
/Experiment_14_Grocery_App

├── public/

│ └── index.html

├── src/

│ ├── App.jsx

│ ├── components/

│ │ └── Product/

│ │ └── index.js (Product component)

│ ├── assets/

│ │ └── products.json (Product data)

│ ├── App.css (Styling)

│ ├── index.css (Styling)

│ └── index.js (Renders the App component)

└── package.json (Defines dependencies)

74
B64

Code
src/assets/products.json:
[
{
"id": "t-shirt",
"name": "Fruits",
"price": 35.0,
"imageUrl": "https://www.lalpathlabs.com/blog/wp-
content/uploads/2019/01/Fruits-and-Vegetables.jpg",
"description": "A Basket of fruits",
"url": "/api/products/halfmoon"
},
{
"id": "wallet",
"name": "Vegitables",
"price": 20.0,
"imageUrl": "https://img.freepik.com/free-photo/bottom-view-
fruits-vegetables-radish-cherry-tomatoes-persimmon-tomatoes-kiwi-
cucumber-apples-red-cabbage-parsley-quince-aubergines-blue-
table_140725-146174.jpg",
"description": "A Basket of Veges",
"url": "/api/products/wallet"
},
{
"id": "cup",
"name": "Milk",
"price": 5.0,
"imageUrl": "https://encrypted-
tbn0.gstatic.com/images?q=tbn:ANd9GcSeujHMy6OLRZHTpsrUMVLsHyiolmZ
iZI4fMQ&usqp=CAU",
"description": "Healthy Milk",
"url": "/api/products/veiltail"
}
]

src/components/Product/index.js:
import "./index.css"; // Assuming corresponding CSS exists

export default function Product(props) {


const {id, imageUrl, name, description, price} = props; //
Destructuring props

return (
<div
key={id} // Key should ideally be on the element generated
by .map in parent
className={"product"} // Assuming 'product' class provides

75
B64

styling
>
<img
src={imageUrl}
alt={`Image of ${name}`} // Corrected alt text
interpolation
className={"image-product"} // Assuming 'image-product'
class provides styling
/>
<h3>{name}</h3>
<p>{description}</p>
<span>${price}</span> {/* Assuming price is number,
formatting might be needed */}
<div>
<button
className="snipcart-add-item" // SnipCart specific
class
data-item-id={id}
data-item-image={imageUrl}
data-item-name={name}
data-item-url="/" // SnipCart needs URL, using root for
example
data-item-price={price}
>
Add to Cart
</button>
</div>
</div>
);
}

src/App.jsx:
import "./index.css"; // Assuming global styles
import "./App.css"; // Assuming component styles
import products from "./assets/products.json"; // Importing local
JSON data
import Product from "./components/Product"; // Importing Product
component

export default function App() {


return (
<div className={"container"}> {/* Assuming 'container' class
provides layout */}
<main className={"main"}> {/* Assuming 'main' class
provides layout */}
<h1>
E-Commerce in React and SnipCart {/* Title from PDF */}
</h1>

76
B64

<div className={"grid"}> {/* Assuming 'grid' class


provides layout */}
{
products.map((product, i) => <Product {...product}
key={product.id || i}/>) // Pass product props, use product.id
for key if available
}
</div>
</main>
{/* SnipCart required div - API key included in PDF example
*/}
<div
id="snipcart"
data-api-
key="NWMwZWNkZGMtZjU2ZS00YzM3LWFlZjYtMmM5Zjk0MWViZDcxNjM3Njg0OTY0
ODg5NTk4MTM3"
hidden
>
</div>
{/* SnipCart script needs to be included in index.html,
not shown here */}
</div>
);
}

77
B64

Output

78

You might also like