Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

Web Application - Project Day 1

Server

CREATE SERVER APP

npm init

npm i express express-session mongodb mongoose nodemon axios cors apollo-


server-express graphql graphql-tools

"dependencies": {
"apollo-server-express": "^3.13.0",
"axios": "^1.7.2",
"cors": "^2.8.5",
"express": "^4.19.2",
"express-session": "^1.18.0",
"graphql": "^16.9.0",
"graphql-tools": "^9.0.1",
"mongodb": "^6.8.0",
"mongoose": "^8.4.4",
"nodemon": "^3.1.4",
"superagent": "^9.0.2"
}

Server Folder Structure


.
└── server/
├── node_modules/
├── model/
│ ├── userSchema.js
│ └── blogSchema.js
├── routes/
│ ├── userRoutes.js
│ └── blogRoutes.js
├── index.js
├── package.json
├── resolvers.js
└── schema.js
Create API End Points

/users
1) Create a User / users/create
2) Update Password /users/changePass
3) Login a User. /users/login

Index.js

const express = require('express');


const mongoose = require('mongoose');
const {ApolloServer,gql} = require('apollo-server-express');
const typeDefs = require('./schema');
const cors = require('cors'); // Import CORS
const resolvers = require('./resolvers');
const userApiFromRouter = require('./routes/usersRoute')
const app = express();
const port = 3001
const url= ‘Your Url';

// CORS middleware
app.use(cors());

app.use(express.json())//parsing
mongoose.connect(url,{useNewUrlParser:true,
useUnifiedTopology:true}).then(()=>{console.log('DB connected')})
.catch((err)=>{console.log(err)});

const server = new ApolloServer({typeDefs,resolvers});

app.use(‘/users',userApiFromRouter); //api

async function StartServer(){


await server.start();
server.applyMiddleware({app});//run my express code
app.listen(port,()=>{
console.log('server live 3001');
})
}
StartServer();
UserSchema.js

//this is my Mongodb Schema /model/userSchema.js


const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
name:{type:String,required:true},
email:{type:String,required:true},
password:{type:String,required:true}})
module.exports= mongoose.model('User',userSchema);

schema.js

//schema.js
//create a schema using GQL
const { gql } = require('apollo-server-express');
const typeDefs = gql`
type User {
id:ID !,
name:String!,
email:String!,
password:String!
}
type Query {
getUser(id:ID!):User
getUsers:[User]
}
input createUserInput{
name:String!,
email:String!,
password:String!
}

type Mutation{
createUser(input:createUserInput!):User
changePass(id:ID!,password:String!):User
}
`;
module.exports= typeDefs;//export out

resolvers.js

//resolvers.js
const User = require('./model/userSchema');//parent
const resolvers ={
Query:{
getUser: async(_,{id})=>{return await User.findById(id);},
getUsers: async()=>{return await User.find();},
},
Mutation:{
createUser: async (_,{input})=>{
const {name,email,password}= input;
try{
if(!name || !email || !password){
throw new Error("Please enter all the
fields");
}
const newUser = new User({name,email,password});
return await newUser.save();
}catch(err){ throw Error(`Error Creating User: ${err}
`)}
},
changePass:async(_,{id,password})=>{

try{

const usernew= await User.findByIdAndUpdate(id,


{password:password},{new:true});
if(!usernew){
throw new Error("User not found");
}
console.log(usernew);
return usernew;
}catch(err){throw Error(`Error Occured :${err}`)}

},
},
User:{
email:(parent)=> parent.email || '',
name:(parent)=> parent.name || '',
password:(parent)=> parent.password || ''
},
};module.exports=resolvers;//export resolvers

userRoute.js

const express = require('express')


const router = express.Router()
const {ApolloServer,gql} = require('apollo-server-express');
const typeDefs = require('../schema');
const resolvers = require('../resolvers');
const server = new ApolloServer({typeDefs,resolvers});
router.get('/',async (req,res)=>{
try{
const {data,errors}= await server.executeOperation({
query:gql`query{ getUsers{id name email password} }`
});if(errors){
console.log(errors)
return res.status(500).send(errors);
}res.status(201).send(data)
}catch(err){
console.log()
res.status(500).send({message:err})
}
})

router.post('/', async (req,res)=>{


//req -> name,email,password
const {name,email,password}= req.body;
try{
const {data,error} = await server.executeOperation({
query:gql`mutation {
createUser(input:{name:"${name}",
email:"${email}",password:"${password}"}){
name
email
}
}`
});
if(error){return res.status(500).send({message:error})}
res.status(201).send(data)
}catch(err){
res.status(500).send({message:err});
}
})

router.put('/changepass/:id', async(req,res)=>{
const id = req.params.id;
const {password}= req.body;
try{
const {data,error} = await server.executeOperation({
query:gql`mutation{
changePass(id:"${id}",password:"${password}"){
id
name
password
}
} `
});
if(error){ return res.status(500).send({message:error})};
res.status(201).send({message:data});
}catch(err){res.status(500).send({message:err})};
})

module.exports =router
Client

CREATE Client APP

npx create-react-app client

npm install react-router-dom


npm install axios
npm install -D tailwindcss
npx tailwindcss init

Refer Document
https://tailwindcss.com/docs/guides/create-react-app
index.js

import React from 'react';


import ReactDOM from 'react-dom/client';
import './index.css';
import Navbar from './components/navbar';
import { BrowserRouter as Router, Routes,Route } from 'react-
router-dom';
import Register from './components/Register';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<div>
<Router>
<Navbar/>
<Routes>
<Route path="/about" element={<h1>About</h1>}/>
<Route path="/register" element={<Register/>}/>
</Routes>
</Router>

</div>
);

Register.js

import React, { useState } from "react";


import axios from "axios"; // Import Axios

export default function Register() {


const [formData, setForm] = useState({
name: "",
email: "",
password: ""
});

const handleChange = (e) => {


const { id, value } = e.target;
setForm((prevFormData) => ({
...prevFormData,
[id]: value
}));
};

const handleSubmit = async (e) => {


e.preventDefault(); // Prevent default form submission

try {
const response = await axios.post("http://
localhost:3001/users/create", formData);
console.log("Form data submitted successfully!",
response.data);

// Optionally, reset the form after submission


setForm({
name: "",
email: "",
password: ""
});

} catch (error) {
console.error("Error submitting form:", error);
// Handle error, e.g., show error message to user
}
};

return (
<form className="max-w-sm mx-auto py-5"
onSubmit={handleSubmit}>
<div className="mb-5">
<label htmlFor="name" className="block mb-2 text-
sm font-medium text-gray-900 dark:text-white">Your Name</label>
<input
type="text"
id="name"
className="bg-gray-50 border border-gray-300
text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-
blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600
dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500
dark:focus:border-blue-500"
value={formData.name}
onChange={handleChange}
/>
</div>
<div className="mb-5">
<label htmlFor="email" className="block mb-2 text-
sm font-medium text-gray-900 dark:text-white">Your email</label>
<input
type="email"
id="email"
className="bg-gray-50 border border-gray-300
text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-
blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600
dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500
dark:focus:border-blue-500"
placeholder="name@flowbite.com"
required
value={formData.email}
onChange={handleChange}
/>
</div>
<div className="mb-5">
<label htmlFor="password" className="block mb-2
text-sm font-medium text-gray-900 dark:text-white">Your password</
label>
<input
type="password"
id="password"
className="bg-gray-50 border border-gray-300
text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-
blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600
dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500
dark:focus:border-blue-500"
value={formData.password}
onChange={handleChange}
required
/>
</div>

<button
type="submit"
className="text-white bg-blue-700 hover:bg-
blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-
medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center
dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Submit
</button>
</form>
);
}

Navbar.js

import React from "react";


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

export default function Navbar(){


return(
<div>

<nav class="bg-blue-600 border-gray-200 dark:bg-gray-900">


<div class="max-w-screen-xl flex flex-wrap items-center justify-
between mx-auto p-4">
<a href="" class="flex items-center space-x-3 rtl:space-x-
reverse">
<img src="https://png.pngtree.com/png-vector/20230304/
ourmid/pngtree-colorful-blog-speech-bubble-vector-png-
image_6633021.png"
class="h-10 w-14" alt="Blogging SIte" />
<span class="self-center text-2xl font-semibold
whitespace-nowrap text-white">Bloggy</span>
</a>
<button data-collapse-toggle="navbar-default" type="button"
class="inline-flex items-center p-2 w-10 h-10 justify-center text-
sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100
focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-
gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600" aria-
controls="navbar-default" aria-expanded="false">
<span class="sr-only">Open main menu</span>
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://
www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
<path stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1
13h15"/>
</svg>
</button>
<div class="hidden w-full md:block md:w-auto" id="navbar-
default">
<ul class=" text-white font-medium flex flex-col p-4 md:p-0
mt-4 border border-gray-100 md:flex-row md:space-x-8 rtl:space-
x-reverse md:mt-0 md:border-0 ">

<li>
<Link to='/about'> About</Link>
</li>
<li>
<Link to='/register'> Register</Link>
</li>
<li>
<Link to='/login'>Login</Link>
</li>

</ul>
</div>
</div>
</nav>

</div>
)
}
Login Auth

index.js (Server Entry Point)

const session = require('express-session'); // Add session


middleware
app.use(session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: false,
}));

Schema.js(Server )

getUser(email:String!):[User]

Resolvers.js(Server )

getUser: async(_,{email})=>{return await


User.find({email:email});},

userSchema.js(Server )

// Example login route


router.post('/login', async (req, res) => {
const { email, password } = req.body;
try {
const { data, errors } = await server.executeOperation({
query: gql`query { getUser(email: "${email}"){ id name
password } }`
});

// Handle GraphQL query errors


if (errors) {
console.error(errors);
return res.status(500).send(errors);
}
const user = data.getUser;
if (!user) {
return res.status(401).send({ message: 'Invalid
credentials' });
}
res.status(200).json({ message: 'Login successful',
user });
} catch (err) {
console.error('Error in login:', err);
res.status(500).json({ message: 'Internal server
error' });
}
});

// Example logout route


router.post('/logout', async (req, res) => {
try {
res.status(200).send({ message: 'Logged out
successfully' });
} catch (err) {
res.status(500).send({ message: err.message });
}
});

Login.js (Client Component)

import React, { useState } from "react";


import axios from "axios"; // Import Axios

export default function Login() {


const [formData, setForm] = useState({
email: "",
password: ""
});

const handleChange = (e) => {


const { id, value } = e.target;
setForm((prevFormData) => ({
...prevFormData,
[id]: value
}));
};
const handleSubmit = async (e) => {
e.preventDefault(); // Prevent default form submission

try {
const response = await axios.post("http://
localhost:3001/users/login", formData);
console.log("Login successful!", response.data);
alert(response.data);
} catch (error) {
console.error("Error logging in:", error);
}
};

return (
<form className="max-w-sm mx-auto py-5"
onSubmit={handleSubmit}>
<div className="mb-5">
<label htmlFor="email" className="block mb-2 text-
sm font-medium text-gray-900 dark:text-white">Your email</label>
<input
type="email"
id="email"
className="bg-gray-50 border border-gray-300
text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-
blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600
dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500
dark:focus:border-blue-500"
placeholder="name@flowbite.com"
required
value={formData.email}
onChange={handleChange}
/>
</div>
<div className="mb-5">
<label htmlFor="password" className="block mb-2
text-sm font-medium text-gray-900 dark:text-white">Your password</
label>
<input
type="password"
id="password"
className="bg-gray-50 border border-gray-300
text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-
blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600
dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500
dark:focus:border-blue-500"
value={formData.password}
onChange={handleChange}
required
/>
</div>
<button
type="submit"
className="text-white bg-blue-700 hover:bg-
blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-
medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center
dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Login
</button>
</form>
);
}
navbar.js (Client Component)

const handleLogout = async () => {


try {
await axios.post("http://localhost:3001/users/logout");
} catch (error) {
console.error("Error logging out:", error);
}
};

<li><button onClick={handleLogout} className="text-


white">Logout</button></li>

You might also like