Commit 266d9fcc authored by Ajay R's avatar Ajay R

CRUD Operation using open API

parent 7828acd0
This diff is collapsed.
......@@ -3,11 +3,15 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.9.3",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"bootstrap": "^5.3.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.9.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
......
import logo from './logo.svg';
import './App.css';
import "./App.css";
import Create from "./components/Create";
import Navbar from "./components/Navbar";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Read from "./components/Read";
import Update from "./components/Update";
import { showUser } from "./features/userDetailSlice";
import { useEffect } from "react";
import { useDispatch } from "react-redux";
function App() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(showUser());
}, []);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<BrowserRouter>
<Navbar />
<Routes>
<Route exact path="/" element={<Create />} />
<Route exact path="/read" element={<Read />} />
<Route exact path="/edit/:id" element={<Update />} />
</Routes>
</BrowserRouter>
</div>
);
}
......
// api/schema.js
const { gql } = require('apollo-server');
const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
}
type Query {
users: [User]
}
type Mutation {
createUser(input: UserInput!): User
}
input UserInput {
name: String!
email: String!
}
`;
module.exports = typeDefs;
import { configureStore } from "@reduxjs/toolkit";
import userDetail from "../features/userDetailSlice";
export const store = configureStore({
reducer: {
app: userDetail,
},
});
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { createUser } from "../features/userDetailSlice";
const Create = () => {
const [users, setUsers] = useState({});
const navigate = useNavigate();
const dispatch = useDispatch();
const getUserData = (e) => {
setUsers({ ...users, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
console.log("users...", users);
dispatch(createUser(users));
navigate("/read");
};
return (
<div>
<h2 className="my-2">Fill the data</h2>
<form className="w-50 mx-auto my-5" onSubmit={handleSubmit}>
<div class="mb-3">
<label class="form-label">Name</label>
<input
type="text"
name="name"
class="form-control"
onChange={getUserData}
required
/>
</div>
<div class="mb-3">
<label class="form-label">Email</label>
<input
type="email"
name="email"
class="form-control"
onChange={getUserData}
required
/>
</div>
<div class="mb-3">
<label class="form-label">Age</label>
<input
type="text"
name="age"
class="form-control"
onChange={getUserData}
required
/>
</div>
<div class="mb-3">
<input
class="form-check-input"
name="gender"
value="Male"
type="radio"
onChange={getUserData}
required
/>
<label class="form-check-label">Male</label>
</div>
<div class="mb-3">
<input
class="form-check-input"
name="gender"
value="Female"
type="radio"
onChange={getUserData}
/>
<label class="form-check-label">Female</label>
</div>
<button type="submit" class="btn btn-primary">
Submit
</button>
</form>
</div>
);
};
export default Create;
.modalBackground {
position: fixed;
background-color: #e8e8e8;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 99;
opacity: 1;
}
.modalContainer {
background-color: white;
box-shadow: 0px 0px 0px #888;
padding: 10px;
border-radius: 10px;
height: 400px;
width: 400px;
}
import React from "react";
import { useSelector } from "react-redux";
import "./CustomModal.css";
const CustomModal = ({ id, setShowPopup }) => {
const allusers = useSelector((state) => state.app.users);
const singleUser = allusers.filter((ele) => ele.id === id);
console.log("singleuser", singleUser);
return (
<div className="modalBackground">
<div className="modalContainer">
<button onClick={() => setShowPopup(false)}>Close</button>
<h2>{singleUser[0].name}</h2>
<h3>{singleUser[0].email}</h3>
<h4>{singleUser[0].age}</h4>
<p>{singleUser[0].gender}</p>
</div>
</div>
);
};
export default CustomModal;
import { useSelector } from "react-redux";
import { Link } from "react-router-dom";
const Navbar = () => {
const allusers = useSelector((state) => state.app.users);
return (
<div>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<div className="container-fluid ">
<div className="collapse navbar-collapse">
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
<li className="nav-item">
<Link to="/" className="nav-link">
Create Post
</Link>
</li>
<li className="nav-item">
<Link to="/read" className="nav-link">
All Post ({allusers.length})
</Link>
</li>
</ul>
</div>
</div>
</nav>
</div>
);
};
export default Navbar;
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
import { deleteUser } from "../features/userDetailSlice";
import CustomModal from "./CustomModal";
const Read = () => {
const dispatch = useDispatch();
const [id, setId] = useState();
const [showPopup, setShowPopup] = useState(false);
const { users, loading } = useSelector((state) => state.app);
if (loading) {
return <h2>Loading</h2>;
}
return (
<div>
{showPopup && (
<CustomModal
id={id}
showPopup={showPopup}
setShowPopup={setShowPopup}
/>
)}
<h2>All data</h2>
<div>
{users &&
users.map((ele) => (
<div key={ele.id} className="card w-50 mx-auto my-2">
<div className="card-body">
<h5 className="card-title">{ele.name}</h5>
<h6 className="card-subtitle mb-2 text-muted">{ele.email}</h6>
<p className="card-text">{ele.gender}</p>
<button
className="card-link"
onClick={() => [setId(ele.id), setShowPopup(true)]}
>
View
</button>
<Link to={`/edit/${ele.id}`} className="card-link">
Edit
</Link>
<Link
onClick={() => dispatch(deleteUser(ele.id))}
className="card-link"
>
Delete
</Link>
</div>
</div>
))}
</div>
</div>
);
};
export default Read;
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
import { updateUser } from "../features/userDetailSlice";
const Update = () => {
const { id } = useParams();
const dispatch = useDispatch();
const navigate = useNavigate();
const [updateData, setUpdateData] = useState();
const { users } = useSelector((state) => state.app);
useEffect(() => {
if (id) {
const singleUser = users.filter((ele) => ele.id === id);
setUpdateData(singleUser[0]);
}
}, []);
const newData = (e) => {
setUpdateData({ ...updateData, [e.target.name]: e.target.value });
};
console.log("updated data", updateData);
const handleUpdate = (e) => {
e.preventDefault();
dispatch(updateUser(updateData));
navigate("/read");
};
return (
<div>
<h2 className="my-2">Edit the data</h2>
<form className="w-50 mx-auto my-5" onSubmit={handleUpdate}>
<div class="mb-3">
<label class="form-label">Name</label>
<input
type="text"
name="name"
class="form-control"
value={updateData && updateData.name}
onChange={newData}
/>
</div>
<div class="mb-3">
<label class="form-label">Email</label>
<input
type="email"
name="email"
class="form-control"
value={updateData && updateData.email}
onChange={newData}
/>
</div>
<div class="mb-3">
<label class="form-label">Age</label>
<input
type="text"
name="age"
class="form-control"
value={updateData && updateData.age}
onChange={newData}
/>
</div>
<div class="mb-3">
<input
class="form-check-input"
name="gender"
value="Male"
type="radio"
checked={updateData && updateData.gender === "Male"}
onChange={newData}
/>
<label class="form-check-label">Male</label>
</div>
<div class="mb-3">
<input
class="form-check-input"
name="gender"
value="Female"
type="radio"
checked={updateData && updateData.gender === "Female"}
onChange={newData}
/>
<label class="form-check-label">Female</label>
</div>
<button type="submit" class="btn btn-primary">
Submit
</button>
</form>
</div>
);
};
export default Update;
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
//create action
export const createUser = createAsyncThunk(
"createUser",
async (data, { rejectWithValue }) => {
console.log("data", data);
const response = await fetch(
"https://641dd63d945125fff3d75742.mockapi.io/crud",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
}
);
try {
const result = await response.json();
return result;
} catch (error) {
return rejectWithValue(error);
}
}
);
//read action
export const showUser = createAsyncThunk(
"showUser",
async (args, { rejectWithValue }) => {
const response = await fetch(
"https://641dd63d945125fff3d75742.mockapi.io/crud"
);
try {
const result = await response.json();
console.log(result);
return result;
} catch (error) {
return rejectWithValue(error);
}
}
);
//delete action
export const deleteUser = createAsyncThunk(
"deleteUser",
async (id, { rejectWithValue }) => {
const response = await fetch(
`https://641dd63d945125fff3d75742.mockapi.io/crud/${id}`,
{ method: "DELETE" }
);
try {
const result = await response.json();
console.log(result);
return result;
} catch (error) {
return rejectWithValue(error);
}
}
);
//update action
export const updateUser = createAsyncThunk(
"updateUser",
async (data, { rejectWithValue }) => {
console.log("updated data", data);
const response = await fetch(
`https://641dd63d945125fff3d75742.mockapi.io/crud/${data.id}`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
}
);
try {
const result = await response.json();
return result;
} catch (error) {
return rejectWithValue(error);
}
}
);
export const userDetail = createSlice({
name: "userDetail",
initialState: {
users: [],
loading: false,
error: null,
},
reducers: {
},
extraReducers: {
[createUser.pending]: (state) => {
state.loading = true;
},
[createUser.fulfilled]: (state, action) => {
state.loading = false;
state.users.push(action.payload);
},
[createUser.rejected]: (state, action) => {
state.loading = false;
state.error = action.payload.message;
},
[showUser.pending]: (state) => {
state.loading = true;
},
[showUser.fulfilled]: (state, action) => {
state.loading = false;
state.users = action.payload;
},
[showUser.rejected]: (state, action) => {
state.loading = false;
state.error = action.payload;
},
[deleteUser.pending]: (state) => {
state.loading = true;
},
[deleteUser.fulfilled]: (state, action) => {
state.loading = false;
const { id } = action.payload;
if (id) {
state.users = state.users.filter((ele) => ele.id !== id);
}
},
[deleteUser.rejected]: (state, action) => {
state.loading = false;
state.error = action.payload;
},
[updateUser.pending]: (state) => {
state.loading = true;
},
[updateUser.fulfilled]: (state, action) => {
state.loading = false;
state.users = state.users.map((ele) =>
ele.id === action.payload.id ? action.payload : ele
);
},
[updateUser.rejected]: (state, action) => {
state.loading = false;
state.error = action.payload.message;
},
},
});
export default userDetail.reducer;
export const { searchUser } = userDetail.actions;
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { store } from "./app/store";
import { Provider } from "react-redux";
import "bootstrap/dist/css/bootstrap.min.css";
import reportWebVitals from "./reportWebVitals";
const root = ReactDOM.createRoot(document.getElementById('root'));
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment