article

Showing posts with label ReactJS. Show all posts
Showing posts with label ReactJS. Show all posts

Thursday, January 16, 2025

ReactJS 18 Node Express CRUD | React Query | MongoDB Atlas | TailwindCSS (Create Read Update and Delete)

ReactJS 18 Node Express CRUD | React Query | MongoDB Atlas | TailwindCSS (Create Read Update and Delete)
https://expressjs_com/
Express JS
Fast, unopinionated, minimalist web framework for Node.js

$ npm install express --savev PS C:\nodeproject> npm install express --save
https://expressjs.com/en/starter/hello-world.html

mongoose
mongoosejs/docs/
npm install mongoose --save

cors
CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
npmjs-com/package/cors
PS C:\nodeproject>npm i cors

run PS C:\nodeproject> node index.js
index.js
//index.js
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const UserModel = require('./User')
  
const app = express()
const port = 3001
 
app.use(cors())
app.use(express.json())
  
main().catch(err => console.log(err));
 
async function main() {
    try {                     //"mongodb+srv://"username":"password"@cluster0.x45tgvn.mongodb.net/"databasename"?retryWrites=true&w=majority&appName=Cluster0"
        await mongoose.connect('mongodb+srv://cairocoders:123456@cluster0.x45tgvn.mongodb.net/expressdb?retryWrites=true&w=majority&appName=Cluster0', {});
        console.log("CONNECTED TO DATABASE SUCCESSFULLY");
    } catch (error) {
        console.error('COULD NOT CONNECT TO DATABASE:', error.message);
    }
}
 
app.get('/hello', (req, res) => {
  res.send('Hello World!')
})
 
app.get('/users', (req, res) => {
    UserModel.find()
    .then(users => res.json(users))
    .catch(err => res.json(err))
})
  
  
app.get('/users/get/:id', (req, res) => {
    const id = req.params.id
    UserModel.findById({_id: id})
    .then(post => res.json(post))
    .catch(err => console.log(err))
})
  
app.post('/users/create', (req, res) => {
    UserModel.create(req.body)
    .then(user => res.json(user))
    .catch(err => res.json(err))
})
  
app.put('/users/update/:id', (req, res) => {
    const id = req.params.id;
    UserModel.findByIdAndUpdate({_id: id}, {
        name: req.body.name,
        email: req.body.email,
        age: req.body.age
    }).then(user => res.json(user))
    .catch(err => res.json(err))
})
  
app.delete('/users/delete/:id', (req, res) => {
    const id = req.params.id;
    UserModel.findByIdAndDelete({_id: id})
    .then(response => res.json(response))
    .catch(err => res.json(err))
})
  
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
User.js
//User.js
const mongoose = require('mongoose')
  
const UserSchema = new mongoose.Schema({
    name: String,
    email: String,
    age: Number
})
  
const UserModel = mongoose.model("users", UserSchema)
  
module.exports = UserModel;
react.dev
Create react project
Run the following command in your terminal: vite_dev/guide/
npm create vite@latest
tanstack/react-query
Hooks for fetching, caching and updating asynchronous data in React, Solid, Svelte and Vue

npm i @tanstack/react-query

react-query-devtools
npm i @tanstack/react-query-devtools

Tailwind CSS with Vite
tailwindcss_com/docs/guides/vite

Install npm i uuid

C:\react-js\my-app\src\App.jsx
//src\App.jsx
import { Route, Routes } from "react-router-dom" 
import UserLists from "./pages/UserLists"
import User from "./pages/User"
import EditUser from "./pages/EditUser"

function App() { tailwindcss_com/docs/guides/vite
  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
        <div className="flex items-center justify-between gap-1 mb-5">
            <h1 className="text-4xl font-bold">React.js 18 Node Express CRUD (Create Read Update and Delete) | React Query MongoDB Atlas</h1>
        </div> 
        <Routes>
          <Route path="/" element={<UserLists />} />
          <Route path="/user/:id" element={<User />} />
          <Route path="/user/:id/edit" element={<EditUser />} />
        </Routes>
    </div>
  )
}

export default App
C:\react-js\my-app\src\main.jsx
//src\main.jsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from '@tanstack/react-query-devtools' //npm i @tanstack/react-query-devtools
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { BrowserRouter } from "react-router-dom";
import App from './App.jsx'

// create a client
const queryClient = new QueryClient();

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <BrowserRouter>
      <QueryClientProvider client={queryClient}>
        <App />
        <ReactQueryDevtools initialIsOpen={false} />
      </QueryClientProvider>
    </BrowserRouter>
  </StrictMode>,
);
C:\react-js\my-app\src\pages\UserLists.jsx
//src\pages\UserLists.jsx
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; //npm i @tanstack/react-query 
import { useNavigate } from "react-router-dom";
import { deleteUser, fetchUsers } from "../api/users";
import AddUser from "../components/AddUser";

const UserLists = () => {
    const navigate = useNavigate();
    const queryClient = useQueryClient();

    const {
      isLoading,
      isError,
      data: users,  
      error,
    } = useQuery({
      queryKey: ["users"],
      queryFn: fetchUsers,
    });

    //console.log(users);

    const deleteUserMutation = useMutation({
      mutationFn: deleteUser,
      onSuccess: () => {
        queryClient.invalidateQueries({ queryKey: ['users']});
      }
    });

    const handleDelete = (id) => {
      deleteUserMutation.mutate(id)
    }

    if (isLoading) return "loading...";
    if (isError) return `Error: ${error.message}`;

  return (
    <div className="overflow-x-auto py-10">
        <AddUser />
        <table className="table table-zebra">
            <thead className="text-sm text-gray-700 uppercase bg-gray-50">
                <tr>
                    <th className="py-3 px-6">#</th>
                    <th className="py-3 px-6">Name</th>
                    <th className="py-3 px-6">Email</th>
                    <th className="py-3 px-6">Age</th>
                    <th className="py-3 px-6 text-center">Actions</th>
                </tr>
            </thead>
            <tbody>
                {users.map((user) => (
                    <tr key={user._id} className="bg-white border-b">
                        <td className="py-3 px-6">{user._id}</td>
                        <td className="py-3 px-6">{user.name}</td>
                        <td className="py-3 px-6">{user.email}</td>
                        <td className="py-3 px-6">{user.age}</td>
                        <td className="flex justify-center gap-1 py-3">
                            <button
                                onClick={() => navigate(`/user/${user._id}`)}
                                className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
                                Read
                            </button>
                            <button className="focus:outline-none text-white bg-yellow-400 hover:bg-yellow-500 focus:ring-4 focus:ring-yellow-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:focus:ring-yellow-900"
                                onClick={() => navigate(`/user/${user._id}/edit`)}
                            >
                                Edit
                            </button>
                            <button onClick={() => handleDelete(user._id)} className="focus:outline-none text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900">
                                Delete</button>
                        </td>
                    </tr>
                ))}
            </tbody>
        </table>
    </div>
  );
};

export default UserLists;
C:\react-js\my-app\src\pages\User.jsx
//src\pages\User.jsx
import { useQuery } from "@tanstack/react-query"; //npm i @tanstack/react-query
import { useNavigate, useParams } from "react-router-dom";
import { fetchUser } from "../api/users";

const User = () => {
  const navigate = useNavigate();
  const { id } = useParams();
  const {
    isLoading,
    isError,
    data: user,
    error,
  } = useQuery({
    queryKey: ["users", id],
    queryFn: () => fetchUser(id),
  });

  if (isLoading) return "loading...";
  if (isError) return `Error: ${error.message}`;


  return (
    <div className="overflow-x-auto py-10">
      <button onClick={() => navigate("/")}>back to list users</button>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
      <p>{user.age}</p>
    </div>
  )
}

export default User
C:\react-js\my-app\src\pages\User.jsx
//src\pages\User.jsx
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useNavigate, useParams } from "react-router-dom";
import { fetchUser, updateUser } from "../api/users";
import UserForm from "../components/UserForm"

const EditUser = () => {
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const { id } = useParams();
  const {
    isLoading,
    isError,
    data: user,
    error,
  } = useQuery({
    queryKey: ["users", id],
    queryFn: () => fetchUser(id),
  });
  const updateUserMutation = useMutation({
    mutationFn: updateUser,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['users']});
      navigate("/")
    }
  })

  if (isLoading) return "loading...";
  if (isError) return `Error: ${error.message}`;

  const handleSubmit = (updatedUser) => {
    updateUserMutation.mutate({id, ...updatedUser})
  }


  return (
    <div className="overflow-x-auto py-10">
      <UserForm onSubmit={handleSubmit} initialValue={user} />
    </div>
  )
}

export default EditUser
C:\react-js\my-app\src\components\AddUser.jsx
//src\components\AddUser.jsx
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { createUser } from "../api/users"
import UserForm from "./UserForm"
import { v4 as uuidv4 } from 'uuid'; //npm i uuid 

const AddUser = () => {
  const queryClient = useQueryClient();

  const createUserMutation = useMutation({
    mutationFn: createUser,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['users']});
      console.log("success!")
    }
  });

  const handleAddPost = (user) => {
    createUserMutation.mutate({
      id: uuidv4(),
      ...user
    })
  }

  return (
    <div className="max-w-md mx-auto mt-5">
      <h1 className="text-2xl text-center mb-2">Add New User</h1>
      <UserForm onSubmit={handleAddPost} initialValue={{}} />
    </div>
  )
}

export default AddUser
C:\react-js\my-app\src\components\UserForm.jsx
//src\components\UserForm.jsx
import { useState } from "react"

const UserForm = ({ onSubmit, initialValue }) => {
  const [user, setUser] = useState({
    name: initialValue.name || "",
    email: initialValue.email || "",
    age: initialValue.age || ""
  });

  const handleChangeInput = (e) => {
    setUser({
      ...user,
      [e.target.name]: e.target.value
    })
  }

  const renderField = (label) => (
    <div>
      <label className="block text-sm font-medium text-gray-900">{label}</label>
      <input onChange={handleChangeInput} type="text" name={label.toLowerCase()} value={user[label.toLowerCase()]} 
        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-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-500blue-500"
      />
    </div>
  );

  const handleSubmit = (e) => {
    e.preventDefault();
    onSubmit(user);
    setUser({
      name: "",
      email: "",
      age: ""
    })

  }

  return (
    <form onSubmit={handleSubmit}>
      <div className="mb-5">{renderField('Name')}</div>
      <div className="mb-5">{renderField('Email')}</div>
      <div className="mb-5">{renderField('Age')}</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>
  )
}

export default UserForm
C:\react-js\my-app\src\api\users.jsx
//src\api\users.jsx
export async function fetchUsers() {
  const response = await fetch('http://localhost:3001/users');
  return response.json()
}

export async function fetchUser(id) {
  const response = await fetch(`http://localhost:3001/users/get/${id}`);
  return response.json()
}

export async function createUser(newUser) {
  const response = await fetch(`http://localhost:3001/users/create`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(newUser)
  });
  return response.json()
}

export async function updateUser(updatedUser) {
  const response = await fetch(`http://localhost:3001/users/update/${updatedUser.id}`, {
    method: "PUT",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(updatedUser)
  });
  return response.json()
}

export async function deleteUser(id) {
  const response = await fetch(`http://localhost:3001/users/delete/${id}`, {
    method: "DELETE",
  });
  return response.json()
}
Run
C:\react-js\my-app> npm run dev

Monday, January 6, 2025

React.js Data Fetching With React SWR

React.js Data Fetching With React SWR
React JS
https://react.dev/learn/start-a-new-react-project

npx create-next-app@latest
npx create-react-app@latest {project name}
Create Project
C:\react-js>npx create-react-app@latest my-app

Run
C:\react-js\my-app> npm start
npm i react-router-dom
https://www.npmjs.com/package/react-router-dom

Install React SWR:
npm i swr
https://www.npmjs.com/package/swr
src\App.js
//src\App.js
import { BrowserRouter, Routes, Route } from "react-router-dom"; //npm i react-router-dom https://www.npmjs.com/package/react-router-dom
import Home from "./elements/Home";
import PostList from "./elements/PostList";
import PostDetails from "./elements/PostDetails";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/postswr" element={<PostList />} />
        <Route path="/post-detail/:postId" element={<PostDetails />} />
      </Routes>
    </BrowserRouter>
  );
}
 
export default App;
src\elements\Home.js
//src\elements\Home.js
import React  from 'react';
import Posts from './Posts'
import { Suspense } from "react";

function Home() {

  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
        <div className="flex items-center justify-between gap-1 mb-5">
            <h1 className="text-4xl font-bold">Basic example fetch dummy data</h1>
        </div> 
        <div className="overflow-x-auto py-10">
            <Suspense fallback="Loading...">
                <Posts/> 
            </Suspense>
        </div>
    </div>
  )
}

export default Home
src\elements\Posts.js
//src\elements\Posts.js
import { useEffect, useState } from "react";
const base_url = 'https://dummyjson.com';

function Post() {
    const [posts, setPosts] = useState([]);
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState(null);
    useEffect(() => {
        const fetchData = async (url) => {
            setIsLoading(true);
            try {
                const data = await fetch(base_url + url)
                .then(res => res.json());
                setPosts(data ? data.posts : []);
            } catch(error) {
                setError('Failed to load');
            }
            
            setIsLoading(false);
        }
        fetchData('/posts');
    }, []);

    return (
        <div className='w-1/2 py-10 m-auto flex justify-between items-center align-middle flex-wrap gap-10'>
            {
                error ? <div>{error}</div> : null
            }
            {
                isLoading ? <div>loading...</div> : null
            }
            {
                posts ? posts.map(post => {
                    return (
                        <div key={post.id} className='btn-primary p-2 bg-blue-500 text-white text-lg rounded-lg hover:shadow-lg disabled:opacity-50'>
                            <h3><a>{post.title}</a></h3>
                            <p>{post.body}</p>
                            <span>Views: {post.views}</span>
                            <div>Tags: {post.tags.map(tag => <span key={tag}>{tag}</span>)}</div>
                        </div>
                    )
                }) : null
            }
        </div>
    );
}

export default Post;
src\elements\PostList.js
//src\elements\PostList.js
import React from "react";
import { Link } from "react-router-dom";
import useSWR from 'swr'; //npm i swr https://www.npmjs.com/package/swr

function PostList()
{
    const base_url = 'https://dummyjson.com';

    const fetcher = (url) => {
        return fetch(base_url + url).then(res => res.json());
    };

    const { data, error, isLoading } = useSWR('/posts', fetcher);

    const style = {margin: '2px', background: '#000000', padding: '2px 7px', borderRadius: '6px'};

    return (
        <div className="w-screen py-20 flex justify-center flex-col items-center">
            <div className="flex items-center justify-between gap-1 mb-5">
                <h1 className="text-4xl font-bold">React.js Data Fetching With React SWR</h1>
            </div> 
            <div className="overflow-x-auto py-1">
                <div className='w-1/2 py-10 m-auto flex justify-between items-center align-middle flex-wrap gap-10'>
                    {
                        error ? <div>failed to load</div> : null
                    }

                    {
                        isLoading ? <div>loading...</div> : null
                    }

                    {
                        data ? data.posts.map(post => {
                            return (
                                <div key={post.id} className='btn-primary p-2 bg-blue-500 text-white text-lg rounded-lg hover:shadow-lg disabled:opacity-50'>
                                    <h3><Link to={`/post-detail/${post.id}`}>{post.title}</Link></h3>
                                    <p>{post.body}</p>
                                    <span>Views: {post.views}</span>
                                    <div>Tags: {post.tags.map(tag => <span key={tag} style={style}>{tag}</span>)}</div>
                                </div>
                            )
                        }) : null
                    }
                </div>
            </div>
        </div>        
    )
}

export default PostList
src\elements\PostDetails.js
//src\elements\PostDetails.js
import React from "react";
import { useParams } from 'react-router-dom';
import useSWR from 'swr';

const base_url = 'https://dummyjson.com';

function PostDetails()
{
    let { postId } = useParams();

    const fetcher = async ([url, postId]) => {

        const res = await fetch(base_url + url + `/${postId}`);

        if (!res.ok) {
            const error = new Error('An error occurred while fetching the data.')
            error.status = res.status
            throw error
          }
         
          return res.json()
    }

    const { data: post, error,  isLoading } = useSWR(['/posts', postId], fetcher);

    const style = {margin: '2px', background: '#d7d4d4', padding: '2px 7px', borderRadius: '6px'};

    return (
        <div className='w-1/2 py-10 m-auto flex justify-between items-center align-middle flex-wrap gap-10'>
            {
                error ? <div>{error.message}</div> : null
            }

            {
                isLoading ? <div>loading...</div> : null
            }

            {
                post && (
                    <div className='btn-primary p-2 bg-blue-500 text-white text-lg rounded-lg hover:shadow-lg disabled:opacity-50'>
                            <h3>{post.title}</h3>
                            <p>{post.body}</p>
                            <span>Views: {post.views}</span>
                            <div>Tags: {post.tags.map(tag => <span key={tag} style={style}>{tag}</span>)}</div>
                            <div>Likes: 👍 {post.reactions.likes}</div>
                            <div>Deslikes: 👎 {post.reactions.likes}</div>
                        </div>
                )
            }
        </div>
    )
}

export default PostDetails;
Run C:\react-j\my-app>npm start
http://localhost:3000/

Monday, November 25, 2024

React.js WordPress Rest API Pagination with Featured Image and View Single Page | Tailwind CSS

React.js WordPress Rest API Pagination with Featured Image and View Single Page | Tailwind CSS
React JS
https://react.dev/learn/start-a-new-react-project

npx create-next-app@latest
npx create-react-app@latest {project name}
Create Project
C:\react-js>npx create-react-app@latest my-app
Run
C:\react-js\my-app> npm start

Install tailwindcss https://tailwindcss.com/docs/guides/create-react-app
npm install -D tailwindcss
npx tailwindcss
init Install

react-router-dom
https://www.npmjs.com/package/react-router-dom Install axios
src\App.js
//src\App.js 
import { BrowserRouter, Routes, Route } from "react-router-dom"; //npm i react-router-dom https://www.npmjs.com/package/react-router-dom
import Home from "./elements/Home";
import ViewPage from "./elements/ViewPage";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/posts/:slug" element={<ViewPage />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;
src\elements\Home.js
//src\elements\Home.js
import React  from 'react';
import Posts from './Posts'
import { Suspense } from "react";
import { IoSearch } from "react-icons/io5"; //https://www.npmjs.com/package/react-icons npm install react-icons --save

function Home() {

  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
        <div className="flex items-center justify-between gap-1 mb-5">
            <h1 className="text-4xl font-bold">React.js WordPress Rest API Pagination with Featured Image and View Single Page | Tailwind CSS</h1>
        </div> 
        <div className="overflow-x-auto py-10">
            <div className="mb-2 w-full text-right">
                <div className="relative flex flex-1">
                <input
                    type="text"
                    className="w-full border border-gray-200 py-2 pl-10 text-sm outline-2 rounded-sm"
                    placeholder="Search..."
                />
                <IoSearch className="absolute left-3 top-2 h-5 w-5 text-gray-500" />
                </div>
            </div>
            <Suspense fallback="Loading...">
                <Posts/>
            </Suspense>
        </div>
    </div>
  )
}

export default Home
src\elements\Posts.js
//src\elements\Posts.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';

export default function Posts() {
    const [posts, setPosts] = useState([]);

    const [currentPage, setCurrentPage] = useState(1);
    const [totalPages, setTotalPages] = useState(1);

    const perPage = 3;

    useEffect(() => {
        let url = `http://localhost:8888/cairocoders/wp-json/wp/v2/posts?per_page=${perPage}&page=${currentPage}&_embed`;
        axios.get(url).then((res) => {
            const { data, headers } = res;
            setTotalPages(Number(headers['x-wp-totalpages']));
            setPosts(data);
            //console.log("Headers", headers['x-wp-totalpages']);
        });
    }, [currentPage])
    //console.log('posts', posts);

  return (
    <div>
      <div className="grid md:grid-cols-3 gap-5 mt-10">
        {posts.map((post, index) => (
          <div key={index} className="max-w-sm border border-gray-200 rounded-md shadow">
            <div className="relative aspect-video">
              <img src={post._embedded["wp:featuredmedia"][0].media_details.sizes.full.source_url}
                alt={post.title.rendered}
                sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
                className="rounded-t-md object-cover"/>
            </div>
            <div className="p-5">
              <h1>
                <a
                  href={`/posts/${post.slug}`}>
                  {post.title.rendered}
                </a>         
              </h1>
            </div>
          </div>
        ))}
      </div>
      { posts.length > 0 && (
        <div className='w-1/2 py-10 m-auto flex justify-between items-center align-middle flex-wrap gap-10'>
          <button className='btn-primary p-2 bg-blue-500 text-white text-lg rounded-lg hover:shadow-lg disabled:opacity-50'
            disabled={currentPage === 1}
            onClick={() => setCurrentPage(currentPage - 1)}
          >
          Previous
          </button>

          <span className='text-lg'>{currentPage} of {totalPages}</span>

          <button className='btn-primary p-2 bg-blue-500 text-white text-lg rounded-lg hover:shadow-lg disabled:opacity-50'
            disabled={currentPage === totalPages}
            onClick={() => setCurrentPage(currentPage + 1)}
          >
          Next
          </button>
        </div>
        )
      }
    </div>                          
 );
}
src\elements\ViewPage.js
//src\elements\ViewPage.js
import axios from 'axios';
import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom';

const Single = () => {
    const { slug } = useParams();
    const [post, setPost] = useState({});

    useEffect(()=>{
        // axios 
        let url = "http://localhost:8888/cairocoders/wp-json/wp/v2/posts?_embed&slug="+slug;
        axios.get(url).then(res => {
            console.log('res', res);
            //console.log(res.data[0].id);
            setPost(res.data);
        }).catch(err => {
            console.log('error:', err.message);
        });
    }, []);
    return (
    <div className="min-h-screen flex items-center justify-center bg-slate-100">
      <div className="bg-white rounded-sm shadow p-8">
            {
                post.length ? (
                <div>
                  <h1 className="text-2xl font-bold mb-5">{post[0].title.rendered}</h1>
                    <div className="mb-4">            
                      <div 
                        dangerouslySetInnerHTML={{ __html: post[0]['content']['rendered'] }}
                      />   
                    </div>
                </div>
                ) : ('Loading....')
            
            }
      </div>
    </div>
    )
}
export default Single;
themes\cairocoders\functions.php
//themes\cairocoders\functions.php
<?php
/**
 * Theme functions and definitions
 *
 * @package cairocoders
 */

add_action('rest_api_init', 'register_rest_images' );

function register_rest_images(){
    register_rest_field( array('post'),
        'fimg_url',
        array(
            'get_callback'    => 'get_rest_featured_image',
            'update_callback' => null,
            'schema'          => null,
        )
    );
}

function get_rest_featured_image( $object, $field_name, $request ) {
    if( $object['featured_media'] ){
        $img = wp_get_attachment_image_src( $object['featured_media'], 'app-thumb' );
        return $img[0];
    }
    return false;
}
Run C:\react-j\my-app>npm start
http://localhost:3000/

Thursday, November 21, 2024

React.js + WordPress Load Posts with Featured Image and View Single Page | Tailwind CSS

React.js + WordPress Load Posts with Featured Image and View Single Page | Tailwind CSS

React JS
https://react.dev/learn/start-a-new-react-project

npx create-next-app@latest
npx create-react-app@latest {project name}
Create Project
C:\react-js>npx create-react-app@latest my-app
Run
C:\react-js\my-app> npm start

Install tailwindcss https://tailwindcss.com/docs/guides/create-react-app
npm install -D tailwindcss
npx tailwindcss
init Install

react-router-dom
https://www.npmjs.com/package/react-router-dom Install axios
src\App.js
//src\App.js 
import { BrowserRouter, Routes, Route } from "react-router-dom"; //npm i react-router-dom https://www.npmjs.com/package/react-router-dom
import Home from "./elements/Home";
import ViewPage from "./elements/ViewPage";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/posts/:slug" element={<ViewPage />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;
src\elements\Home.js
//src\elements\Home.js
import React  from 'react';
import Posts from './Posts'
import { Suspense } from "react";
import { IoSearch } from "react-icons/io5"; //https://www.npmjs.com/package/react-icons npm install react-icons --save

function Home() {

  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
        <div className="flex items-center justify-between gap-1 mb-5">
            <h1 className="text-4xl font-bold">React.js + WordPress Load Posts with Featured Image and View Single Page | Tailwind CSS</h1>
        </div> 
        <div className="overflow-x-auto py-10">
            <div className="mb-2 w-full text-right">
                <div className="relative flex flex-1">
                <input
                    type="text"
                    className="w-full border border-gray-200 py-2 pl-10 text-sm outline-2 rounded-sm"
                    placeholder="Search..."
                />
                <IoSearch className="absolute left-3 top-2 h-5 w-5 text-gray-500" />
                </div>
            </div>
            <Suspense fallback="Loading...">
                <Posts/>
            </Suspense>
        </div>
    </div>
  )
}

export default Home
src\elements\Posts.js
//src\elements\Posts.js
import React, { useEffect, useState } from 'react';

export default function Posts() {
    const [posts, setPosts] = useState([]);
    useEffect(() => {
        async function loadPosts() {
            const response = await fetch('http://localhost:8888/cairocoders/wp-json/wp/v2/posts?_embed');
            if(!response.ok) {
                // oups! something went wrong
                return;
            }
    
            const posts = await response.json();
            setPosts(posts);
        }
    
        loadPosts();
   }, [])
  return (
      <div className="grid md:grid-cols-3 gap-5 mt-10">
        {posts.map((post, index) => (
          <div key={index} className="max-w-sm border border-gray-200 rounded-md shadow">
            <div className="relative aspect-video">
              <img src={post._embedded["wp:featuredmedia"][0].media_details.sizes.full.source_url}
                alt={post.title.rendered}
                fill
                priority
                sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
                className="rounded-t-md object-cover"/>
            </div>
            <div className="p-5">
              <h1>
                <a
                  href={`/posts/${post.slug}`}>
                  {post.title.rendered}
                </a>         
              </h1>
            </div>
          </div>
        ))}
      </div>
 );
}
src\elements\ViewPage.js
//src\elements\ViewPage.js
import React from 'react';
import { useEffect, useState } from 'react';
import { useParams } from "react-router-dom"; 

export default function Posts() {
    const {slug}=useParams();

    const [posts, setData] = useState(null);

    useEffect(()=>{
        fetchPost();
    },[slug]);
     
    const fetchPost=async()=>{
        try{
          const response = await fetch("http://localhost:8888/cairocoders/wp-json/wp/v2/posts?_embed&slug="+slug);
            if(!response.ok) {
                // oups! something went wrong
                return;
            }

            const posts = await response.json();
            //console.log(posts);
            setData(posts);
        }catch(err){
            console.log("Something Wrong");
        }
    }

    return (
    <div className="min-h-screen flex items-center justify-center bg-slate-100">
      <div className="bg-white rounded-sm shadow p-8">
        {posts && posts.map((post, index) => (
        <div key={index}>
          <h1 className="text-2xl font-bold mb-5">{post.title.rendered}</h1>
            <div className="mb-4">            
              <div 
                dangerouslySetInnerHTML={{ __html: post['content']['rendered'] }}
              />   
            </div>
        </div>
        ))}
     </div>
    </div>
  );
}
themes\cairocoders\functions.php
//themes\cairocoders\functions.php
<?php
/**
 * Theme functions and definitions
 *
 * @package cairocoders
 */

add_action('rest_api_init', 'register_rest_images' );

function register_rest_images(){
    register_rest_field( array('post'),
        'fimg_url',
        array(
            'get_callback'    => 'get_rest_featured_image',
            'update_callback' => null,
            'schema'          => null,
        )
    );
}

function get_rest_featured_image( $object, $field_name, $request ) {
    if( $object['featured_media'] ){
        $img = wp_get_attachment_image_src( $object['featured_media'], 'app-thumb' );
        return $img[0];
    }
    return false;
}
Run C:\react-j\my-app>npm start
http://localhost:3000/

Sunday, July 28, 2024

React.js 18 Node Express CRUD (Create Read Update and Delete) | MySQL Tailwind CSS

React.js 18 Node Express CRUD (Create Read Update and Delete) | MySQL Tailwind CSS

https://expressjs.com/
Express JS
Fast, unopinionated, minimalist web framework for Node.js

Install
$ npm install express --savev PS C:\nodeproject> npm install express --save
https://expressjs.com/en/starter/hello-world.html

mysql
https://www.npmjs.com/package/mysql
$ npm install mysql
PS C:\nodeproject>npm install mysql

cors
CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
https://www.npmjs.com/package/cors
PS C:\nodeproject>npm i cors

bcrypt
https://www.npmjs.com/package/bcrypt
A library to help you hash passwords.
npm install bcrypt

run PS C:\nodeproject> node index.js
index.js
//index.js
const express = require('express')
const bodyParser = require('body-parser');
const cors = require('cors');
const bycrypt = require('bcrypt'); //npm install bcrypt https://www.npmjs.com/package/bcrypt
const db = require('./db');

const app = express()

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(cors({
      origin: 'http://localhost:3000',
      credentials: true
}));

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.post("/api/adduser", async (req, res) => {
  const sql ="INSERT INTO users (name,email,username,password) VALUES (?, ?, ?, ?)";

  const hashedPassword =  await bycrypt.hash(req.body.password, 10);
  
  const values = [req.body.name, req.body.email, req.body.username, hashedPassword];

  db.query(sql, values, (err, result) => {
    if (err)
      return res.json({ message: "Something unexpected has occured" + err });
    return res.json({ success: "New User added successfully" });
  });

});

app.get("/api/users", (req, res) => {
  const sql = "SELECT * FROM users";
  db.query(sql, (err, result) => {
    if (err) res.json({ message: "Server error" });
    return res.json(result);
  });
});

app.get("/api/getuser/:id", (req, res) => {
  const id = req.params.id;
  const sql = "SELECT * FROM users WHERE id= ?";
  db.query(sql, [id], (err, result) => {
    if (err) res.json({ message: "Server error" });
    return res.json(result);
  });
});

app.put("/api/edit/:id", (req, res) => {
  const id = req.params.id;
  const sql ="UPDATE users SET name=?, email=?, username=? WHERE id=?";
   
  const values = [
    req.body.name,
    req.body.email,
    req.body.username,
    id,
  ];
  db.query(sql, values, (err, result) => {
    if (err)
      return res.json({ message: "Something unexpected has occured" + err });
    return res.json({ success: "User updated successfully" });
  });
});

app.delete("/api/delete/:id", (req, res) => {
  const id = req.params.id;
  const sql = "DELETE FROM users WHERE id=?";
  const values = [id];
  db.query(sql, values, (err, result) => {
    if (err)
      return res.json({ message: "Something unexpected has occured" + err });
    return res.json({ success: "Student successfully Deleted" });
  });
});

app.listen(3001, () => {console.log('Server started on port 3001')});
db.js
//db.js
const mysql = require("mysql");
 
const db = mysql.createPool({
    socketPath: '/Applications/MAMP/tmp/mysql/mysql.sock',
    connectionLimit: 10,
    host: "localhost",
    user: "root",
    password: "root",
    database: "nodeexpressDB"
});
 
// Ping database to check for common exception errors.
db.getConnection((err, connection) => {
    if (err) {
        if (err.code === 'PROTOCOL_CONNECTION_LOST') {
            console.error('Database connection was closed.');
        }
        if (err.code === 'ER_CON_COUNT_ERROR') {
            console.error('Database has too many connections.');
        }
        if (err.code === 'ECONNREFUSED') {
            console.error('Database connection was refused.');
        }
    }
  
    if (connection) connection.release();
  
    return;
});
 
module.exports = db;
React JS
https://react.dev/learn/start-a-new-react-project

npx create-next-app@latest
npx create-react-app@latest {project name}
Create Project
C:\react-js>npx create-react-app@latest my-app
Run
C:\react-js\my-app> npm start

Install tailwindcss https://tailwindcss.com/docs/guides/create-react-app npm install -D tailwindcss npx tailwindcss init Install react-router-dom https://www.npmjs.com/package/react-router-dom Install axios
npm install axios
https://www.npmjs.com/package/axios
C:\react-js\my-app\src\App.js
//src\App.js
import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom"; //npm i react-router-dom https://www.npmjs.com/package/react-router-dom
import Home from "./elements/Home";
import Create from "./elements/Create";
import Read from "./elements/Read";
import Edit from "./elements/Edit";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
         <Route path="/create" element={<Create />} />
         <Route path="/read/:id" element={<Read />} />
         <Route path="/edit/:id" element={<Edit />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;
C:\react-js\my-app\src\elements\Home.jsx
//C:\react-js\my-app\src\elements\Home.jsx
import ListUser from './ListUser'
import { Link } from 'react-router-dom'
import { Suspense } from "react";

function Home() {

  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
        <div className="flex items-center justify-between gap-1 mb-5">
            <h1 className="text-4xl font-bold">React.js 18 Node Express CRUD (Create Read Update and Delete) | MySQL Tailwind CSS</h1>
        </div> 
        <div className="overflow-x-auto py-10">
            <div className="mb-2 w-full text-right">
                <Link
                to="/create"
                className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-4 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
                Add New User
                </Link>
            </div>
            <Suspense fallback="Loading...">
                <ListUser/>
            </Suspense>
        </div>
    </div>
  )
}

export default Home
C:\react-js\my-app\src\elements\ListUser.jsx
//C:\react-js\my-app\src\elements\ListUser.jsx
import axios from 'axios'; //npm install axios https://www.npmjs.com/package/react-axios
import { useEffect, useState } from "react";
import { Link } from 'react-router-dom'

export default function ListUser() {
    const [users, setUsers] = useState([]);
  
    useEffect(() => {
        getUsers();
    }, []);
   
    function getUsers() { 
        axios.get('http://localhost:3001/api/users').then(function(response) {
            console.log(response.data);
            setUsers(response.data);
        });
    }

    const deleteUser = (id) => {
        axios.delete(`http://localhost:3001/api/delete/${id}`).then(function(response){
            console.log(response.data);
            getUsers();
        });
    }

    return (
        <table className="table table-zebra">
            <thead className="text-sm text-gray-700 uppercase bg-gray-50">
                <tr>
                    <th className="py-3 px-6">#</th>
                    <th className="py-3 px-6">Name</th>
                    <th className="py-3 px-6">Email</th>
                    <th className="py-3 px-6">Username</th>
                    <th className="py-3 px-6 text-center">Actions</th>
                </tr>
            </thead>
            <tbody>
                {users.map((user, key) =>
                    <tr key={key} className="bg-white border-b">
                        <td className="py-3 px-6">{user.id}</td>
                        <td className="py-3 px-6">{user.name}</td>
                        <td className="py-3 px-6">{user.email}</td>
                        <td className="py-3 px-6">{user.username}</td>
                        <td className="flex justify-center gap-1 py-3">
                            <Link
                                to={`/read/${user.id}`} 
                                className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
                                Read
                            </Link>
                            <Link className="focus:outline-none text-white bg-yellow-400 hover:bg-yellow-500 focus:ring-4 focus:ring-yellow-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:focus:ring-yellow-900" 
                                to={`edit/${user.id}/`}>
                                Edit
                            </Link>
                            <button onClick={() => deleteUser(user.id)} className="focus:outline-none text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900">
                                Delete</button>
                        </td>
                    </tr>
                )}
            </tbody>
        </table>
    )
}
C:\react-js\my-app\src\elements\Create.jsx
//C:\react-js\my-app\src\elements\Create.jsx
import React, { useState } from "react";
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import {useNavigate} from 'react-router-dom'

const Addnewuser = () => {
    const [inputs, setInputs] = useState([]);
   
    const handleChange = (event) => {
        const name = event.target.name;
        const value = event.target.value;
        setInputs(values => ({...values, [name]: value}));
    }
  
    const navigate = useNavigate()
 
    const handleSubmit = (event) => {
        event.preventDefault();
  
        axios.post('http://localhost:3001/api/adduser', inputs).then(function(response){
            console.log(response.data);
            navigate('/')
        });
    }

    return (
    <div className="max-w-md mx-auto mt-5">
        <h1 className="text-2xl text-center mb-2">Add New User</h1>
        <div>
        <form onSubmit={handleSubmit}>
        <div className="mb-5">
          <label htmlFor="name" className="block text-sm font-medium text-gray-900">
            Name
          </label>
          <input
            type="text"
            name="name"
            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-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-500blue-500"
            placeholder="Name..."
            onChange={handleChange}
          />
        </div>
        <div className="mb-5">
          <label htmlFor="email" className="block text-sm font-medium text-gray-900">
            Email
          </label>
          <input
            type="email"
            name="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-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-500blue-500"
            placeholder="email..."
            onChange={handleChange}
          />
        </div>
        <div className="mb-5">
          <label htmlFor="username" className="block text-sm font-medium text-gray-900">
            Username
          </label>
          <input
            type="text"
            name="username"
            id="username"
            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-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-500blue-500"
            placeholder="Username..."
            onChange={handleChange}
          />
        </div>
        <div className="mb-5">
          <label htmlFor="password" className="block text-sm font-medium text-gray-900">
            Password
          </label>
          <input
            type="password"
            name="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-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-500blue-500"
            placeholder="Password..."
            onChange={handleChange}
          />
        </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">
        Add New User</button> 
        </form>
        </div>
    </div>
  );
};
     
export default Addnewuser;
C:\react-js\my-app\src\elements\Read.jsx
//C:\react-js\my-app\src\elements\Read.jsx
import React, { useState, useEffect } from 'react';
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import { useParams } from "react-router-dom"; 

export default function ViewUser() {
    const {id}=useParams();
    
    console.log(id);
    
    const[user,setUser]=useState([]);
     
    useEffect(()=>{
        fetchUser();
    },[id]);
     
    const fetchUser=async()=>{
        try{
        const result=await axios.get("http://localhost:3001/api/getuser/"+id);
          console.log(result.data[0]);
          setUser(result.data[0])
     
        }catch(err){
            console.log("Something Wrong");
        }
    }
    
    return (
    <div className="max-w-2xl mx-auto mt-5">
      <h1 className="text-2xl text-center mb-2">View User</h1>
      <table className="table table-zebra">
          <thead className="text-sm text-gray-700 uppercase bg-gray-50">
            <tr>
              <th>S No.</th>
              <th>Name</th>
              <th>Email</th>         
              <th>Username</th>      
            </tr>
          </thead>
          <tbody>
            <tr>
                <td>{user.id}</td>
                <td>{user.name}</td>
                <td>{user.email}</td>
                <td>{user.username}</td>
            </tr>
          </tbody>
      </table>
    </div>
  );
}
C:\react-js\my-app\src\elements\Edit.jsx
//C:\react-js\my-app\src\elements\Edit.jsx
import React, { useState, useEffect } from 'react';
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import { useParams, useNavigate } from "react-router-dom"; 

export default function Edituser() {
    const [inputs, setInputs] = useState([]);
    const {id}=useParams();
    //console.log(id);
   
    useEffect(() => {
        getUser();
    }, []);
   
    function getUser() {
        axios.get(`http://localhost:3001/api/getuser/${id}`).then(function(response) {
            console.log(response.data[0]);
            setInputs(response.data[0]);
        });
    }
  
    const handleChange = (event) => {
        const name = event.target.name;
        const value = event.target.value;
        setInputs(values => ({...values, [name]: value}));
    }
  
    const navigate = useNavigate()
 
    const handleSubmit = (event) => {
        event.preventDefault();
   
        axios.put(`http://localhost:3001/api/edit/${id}`, inputs).then(function(response){
            console.log(response.data);
            navigate('/')
        });
           
    }
    return (
    <div className="max-w-md mx-auto mt-5">
      <h1 className="text-2xl text-center mb-2">Edit Form</h1>
            <form onSubmit={handleSubmit}> 
                <div className="mb-3 mt-3">
                    <label className="block text-sm font-medium text-gray-900"> ID:</label>
                    <input type="text" id="id" name="id" value={id} disabled />
                </div>
                <div className="mb-3 mt-3">
                    <label className="block text-sm font-medium text-gray-900"> Full Name:</label>
                    <input type="text" 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-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-500blue-500" 
                    placeholder="Enter Your Full Name" name="name"
                    value={inputs.name || ''} 
                    onChange={handleChange}/>
                </div>
                <div className="mb-3 mt-3">
                    <label className="block text-sm font-medium text-gray-900">Email:</label>
                    <input type="text" 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-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-500blue-500" 
                    id="email" placeholder="Enter email" name="email"
                    value={inputs.email || ''} 
                    onChange={ handleChange}/>
                </div>
                <div className="mb-3 mt-3">
                    <label className="block text-sm font-medium text-gray-900">Username:</label>
                    <input type="text" 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-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-500blue-500" 
                    id="username" placeholder="Enter username" name="username"
                    value={inputs.username || ''} 
                    onChange={ handleChange}/>
                </div>
                <button type="submit" name="update"  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">
                    Update</button>
            </form>
    </div>
  );
}
Run C:\react-j\my-app>npm start
http://localhost:3000/

Monday, September 11, 2023

MERN MongoDB Express React Node CRUD (Create Read Update and Delete)

MERN MongoDB Express React Node CRUD (Create Read Update and Delete)

https://expressjs.com/
Express JS
Fast, unopinionated, minimalist web framework for Node.js

Install
$ npm install express --savev PS C:\nodeproject> npm install express --save
https://expressjs.com/en/starter/hello-world.html

https://mongoosejs.com/docs/
npm install mongoose --save

cors
CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
https://www.npmjs.com/package/cors
PS C:\nodeproject>npm i cors

run PS C:\nodeproject> node index.js
//index.js
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const UserModel = require('./User')

const app = express()
app.use(cors())
app.use(express.json())


mongoose.connect('mongodb://127.0.0.1/nodeexpressdb',{
    useNewUrlParser: true, 
    useUnifiedTopology: true
})
.then(db => console.log('DB is connected'))
.catch(err => console.log(err));

app.get('/', (req, res) => {
    UserModel.find()
    .then(users => res.json(users))
    .catch(err => res.json(err))
})


app.get('/get/:id', (req, res) => {
    const id = req.params.id
    UserModel.findById({_id: id})
    .then(post => res.json(post))
    .catch(err => console.log(err))
})

app.post('/create', (req, res) => {
    UserModel.create(req.body)
    .then(user => res.json(user))
    .catch(err => res.json(err))
})

app.put('/update/:id', (req, res) => {
    const id = req.params.id;
    UserModel.findByIdAndUpdate({_id: id}, {
        name: req.body.name,
        email: req.body.email,
        age: req.body.age
    }).then(user => res.json(user))
    .catch(err => res.json(err))
})

app.delete('/deleteuser/:id', (req, res) => {
    const id = req.params.id;
    UserModel.findByIdAndDelete({_id: id})
    .then(response => res.json(response))
    .catch(err => res.json(err))
})

app.listen(3001, () => {
    console.log("Server is Running");
})
User.js
//User.js
const mongoose = require('mongoose')

const UserSchema = new mongoose.Schema({
    name: String,
    email: String,
    age: Number
})

const UserModel = mongoose.model("users", UserSchema)

module.exports = UserModel;
React JS
https://create-react-app.dev/

Create Project
C:\react-js>npx create-react-app my-app

Run
C:\react-js\my-app> npm start

C:\react-js\my-app\src\App.js
//C:\react-js\my-app\src\App.js
import {BrowserRouter, Routes, Route} from 'react-router-dom'
import Users from './components/Users'
import CreateUser from './components/CreateUser'
import UpdateUser from './components/UpdateUser'

function App() {

  return (
    <BrowserRouter>
      <Routes>
        <Route path='/' element={<Users />}></Route>
		<Route path='/create' element={<CreateUser />}></Route>
		<Route path='/edit/:id' element={<UpdateUser />}></Route>
      </Routes>
    </BrowserRouter>
  )
}

export default App
C:\react-js\my-app\src\components\Users.js
//C:\react-js\my-app\src\components\Users.js
import axios from "axios";
import React, { useEffect, useState } from 'react'
import { Link, useParams, useNavigate } from "react-router-dom";

function Users() {
	const {id} = useParams()
	
	  const [data, setData] = useState([])
	  const navigate = useNavigate()
	 
	  useEffect(()=> {
		axios.get('http://localhost:3001/')
		.then(res => {
			console.log(res);
		  setData(res.data);
		})
		.catch(err => console.log(err));
	  }, [])
  
    const handleDelete = (id) => {
        axios.delete('http://localhost:3001/deleteuser/'+id)
        .then(res => {
			console.log(res)
			navigate('/')
        }).catch(err => console.log(err))
    }
    
  return (
    <div className="d-flex vh-100 bg-primary justify-content-center align-items-center">
      <div className="w-50 bg-white rounded p-3">
        <Link to="/create" className="btn btn-success btn-sm">
          Add +
        </Link>
        <table className="table">
          <thead>
            <tr>
              <th>Name</th>
              <th>Email</th>
              <th>Age</th>
              <th>Action</th>
            </tr>
          </thead>
          <tbody>
            {
				data.map((user, index) => {
                    return <tr key={index}>
                        <td>{user.name}</td>
                        <td>{user.email}</td>
                        <td>{user.age}</td>
                        <td>
                            <Link to={`/edit/${user._id}`} className="btn btn-sm btn-success me-2">Update</Link>
                            <button onClick={() => handleDelete(user._id)} className="btn btn-sm btn-danger">Delete</button>
                        </td>
                    </tr>
                })
            }
          </tbody>
        </table>
      </div>
    </div>
  );
}

export default Users;
C:\react-js\my-app\src\components\CreateUser.js
//C:\react-js\my-app\src\components\CreateUser.js
import axios from "axios";
import { useState } from "react";
import { useNavigate } from "react-router-dom";

function CreateUser() {

    const [name, setName] = useState()
    const [email, setEmail] = useState()
    const [age, setAge] = useState()

    const navigate = useNavigate()

    const handleSubmit = (e) => {
        e.preventDefault()
        axios.post('http://localhost:3001/create', {name, email, age})
        .then(res => {
            console.log(res);
            navigate('/')
        })
        .catch(err => console.log(err))
    }

  return (
    <div className="d-flex vh-100 bg-primary justify-content-center align-items-center">
      <div className="w-50 bg-white rounded p-3">
        <form onSubmit={handleSubmit}>
          <h2>Add User</h2>
          <div className="mb-2">
            <label htmlFor="">Name</label>
            <input
              type="text"
              placeholder="Enter Name"
              className="form-control"
              onChange={(e) => setName(e.target.value)}
            />
          </div>
          <div className="mb-2">
            <label htmlFor="">Email</label>
            <input
              type="email"
              placeholder="Enter Email"
              className="form-control"
              onChange={(e) => setEmail(e.target.value)}
            />
          </div>
          <div className="mb-2">
            <label htmlFor="">Age</label>
            <input
              type="text"
              placeholder="Enter Age"
              className="form-control"
              onChange={(e) => setAge(e.target.value)}
            />
          </div>
          <button className="btn btn-success">Submit</button>
        </form>
      </div>
    </div>
  );
}

export default CreateUser;
C:\react-js\my-app\src\components\UpdateUser.js
//C:\react-js\my-app\src\components\UpdateUser.js
import axios from "axios";
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";

function UpdateUser() {
    const {id} = useParams()
   
    const [name, setName] = useState()
    const [email, setEmail] = useState()
    const [age, setAge] = useState()
    
	useEffect(()=> {
		const fetchData = async() => {
			try {
				const response = await axios.get("http://localhost:3001/get/"+id);
				console.log(response);
				setName(response.data.name)
				setEmail(response.data.email)
				setAge(response.data.age)
			} catch(err) {
				console.log(err)
			}
		}
		fetchData();
	}, [])
	
    const navigate = useNavigate()

    const handleUpdate = (e) => {
        e.preventDefault()
        axios.put('http://localhost:3001/update/'+id, {name, email, age})
        .then(res => {
            console.log(res);
            navigate('/')
        })
        .catch(err => console.log(err))
    }

    return ( 
        <div className="d-flex vh-100 bg-primary justify-content-center align-items-center">
      <div className="w-50 bg-white rounded p-3">
        <form onSubmit={handleUpdate}>
          <h2>Update User</h2>
          <div className="mb-2">
            <label htmlFor="">Name</label>
            <input
              type="text"
              placeholder="Enter Name"
              className="form-control"
              value={name}
              onChange={(e) => setName(e.target.value)}
            />
          </div>
          <div className="mb-2">
            <label htmlFor="">Email</label>
            <input
              type="email"
              placeholder="Enter Email"
              className="form-control"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
            />
          </div>
          <div className="mb-2">
            <label htmlFor="">Age</label>
            <input
              type="text"
              placeholder="Enter Age"
              className="form-control"
              value={age}
              onChange={(e) => setAge(e.target.value)}
            />
          </div>
          <button className="btn btn-success">Update</button>
        </form>
      </div>
    </div>
     );
}

export default UpdateUser;
Install axios
https://github.com/axios/axios

Installing the Axios Client
$ npm install axios
C:\reactdev\myreactdev>npm install axios

Install React Router Dom
https://www.npmjs.com/package/react-router-dom
C:\react-js\myreactdev>npm i react-router-dom --save

//react-js\my-app\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">
  </head>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
Run C:\react-j\my-app>npm start
http://localhost:3000/

Saturday, September 9, 2023

React JS Node Express JS Upload File with Mysql Insert data

React JS Node Express JS Upload File with Mysql Insert data

https://expressjs.com/
Express JS
Fast, unopinionated, minimalist web framework for Node.js

Install
$ npm install express --savev PS C:\nodeproject> npm install express --save
https://expressjs.com/en/starter/hello-world.html

cors
CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
https://www.npmjs.com/package/cors
PS C:\nodeproject>npm i cors

mysql
https://github.com/mysqljs/mysql
$ npm install mysql
PS C:\nodeproject>npm install mysql

run PS C:\nodeproject> node index.js
//node index.js
const express = require('express')
const mysql = require("mysql");
const cors = require('cors')
const multer = require('multer') //http://expressjs.com/en/resources/middleware/multer.html npm install --save multer

const app = express()
app.use(cors())
app.use(express.json())

const con = mysql.createConnection({
    user: "root",
    host: "localhost",
    password: "",
    database: "nodejsdb"
})

con.connect(function(err) {
    if(err) {
        console.log("Error in Connection");
    } else {
        console.log("Connected");
    }
})

const storage = multer.diskStorage({
  destination: function(req, file, cb) {
    return cb(null, "./public/images")
  },
  filename: function (req, file, cb) {
    return cb(null, `${Date.now()}_${file.originalname}`)
  }
})

const upload = multer({storage})

//app.post('/upload', upload.single('file'), (req, res) => {
//  console.log(req.body)
//  console.log(req.file)
//  return res.json({Status: "Success"});
//})

app.post('/create',upload.single('file'), (req, res) => {
    const sql = "INSERT INTO employee (`name`,`email`,`address`, `salary`,`image`) VALUES (?)"; 
    const values = [
        req.body.name,
        req.body.email,
        req.body.address,
        req.body.salary, 
		req.file.filename
    ]
    con.query(sql, [values], (err, result) => {
        if(err) return res.json({Error: "Error singup query"});
        return res.json({Status: "Success"});
    })
})

app.listen(3001, () => {
  console.log("Server is running")
})
run postman post: http://localhost:3001/create React JS
https://create-react-app.dev/

Create Project
C:\react-js>npx create-react-app my-app

Run
C:\react-js\my-app> npm start

C:\react-js\my-app\src\App.js
//C:\react-js\my-app\src\App.js
import React, { useState } from "react"
import axios from 'axios'

function App() {
	const [name, setName] = useState("");
	const [email, setEmail] = useState("");
	const [address, setAddress] = useState("");
	const [salary, setSalary] = useState("");
	const [file, setFile] = useState()
	const [msg, setMsg] = useState("");
	  
	const upload = () => {
		const formData = new FormData()
		formData.append("name", name);
		formData.append("email", email);
		formData.append("address", address);
		formData.append("salary", salary);
		formData.append('file', file)
		axios.post('http://localhost:3001/create',formData )
		.then((response) => {
			console.log(response);
			if(response.data.Status === 'Success') {
				setMsg("File Successfully Uploaded");
			}else{
				setMsg("Error");
			}
		})
		.catch(er => console.log(er))
	}
	return (
    <div className="container" style={{paddingTop: 60}}>
	<div className="row"><h1>React JS Node Express JS Upload File with Mysql Insert data</h1>
		<div className="col-12">
			<label className="form-label">Name</label>
			<input type="text" className="form-control" placeholder='Enter Name' autoComplete='off'
			onChange={(e) => setName(e.target.value)}/> 
		</div>
		<div className="col-12">
			<label className="form-label">Email</label>
			<input type="text" className="form-control" placeholder='Enter Email' autoComplete='off'
			onChange={(e) => setEmail(e.target.value)}/> 
		</div>
		<div className="col-12">
			<label className="form-label">Address</label>
			<input type="text" className="form-control" placeholder='Enter Address' autoComplete='off'
			onChange={(e) => setAddress(e.target.value)}/> 
		</div>
		<div className="col-12">
			<label className="form-label">Salary</label>
			<input type="text" className="form-control" placeholder='Enter salary' autoComplete='off'
			onChange={(e) => setSalary(e.target.value)}/> 
		</div>
				
		<div className="col-12">
		  <label className="form-label">Upload File</label>
		  <input className="form-control form-control-lg" type="file" onChange={(e) => setFile(e.target.files[0])}/>
		</div>
		
      <button type="button" className="btn btn-primary btn-lg" onClick={upload} style={{marginTop: '20px'}}>Upload</button>
	  <h1 style={{fontSize: '15px', textAlign: 'center', marginTop: '20px'}}>{msg}</h1>
    </div>
	</div>
  )
}

export default App;
Run C:\react-j\my-app>npm start
http://localhost:3000/

React JS Node Express Upload File

React JS Node Express Upload File

https://expressjs.com/
Express JS
Fast, unopinionated, minimalist web framework for Node.js

Install
$ npm install express --savev PS C:\nodeproject> npm install express --save
https://expressjs.com/en/starter/hello-world.html

cors
CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
https://www.npmjs.com/package/cors
PS C:\nodeproject>npm i cors

run PS C:\nodeproject> node index.js
//index.js
const express = require('express')
const cors = require('cors')
const multer = require('multer') //http://expressjs.com/en/resources/middleware/multer.html npm install --save multer

const app = express()
app.use(cors())
app.use(express.json())

const storage = multer.diskStorage({
  destination: function(req, file, cb) {
    return cb(null, "./public/images")
  },
  filename: function (req, file, cb) {
    return cb(null, `${Date.now()}_${file.originalname}`)
  }
})

const upload = multer({storage})

app.post('/upload', upload.single('file'), (req, res) =>> {
  console.log(req.body)
  console.log(req.file)
  return res.json({Status: "Success"});
})

app.listen(3001, () => {
  console.log("Server is running")
})
run postman post: http://localhost:3001/upload React JS
https://create-react-app.dev/

Create Project
C:\react-js>npx create-react-app my-app

Run
C:\react-js\my-app> npm start

C:\react-js\my-app\src\App.js
//C:\react-js\my-app\src\App.js 
import React, { useState } from "react"
import axios from 'axios'

function App() {
  const [file, setFile] = useState()
  const [msg, setMsg] = useState("");
  
  const upload = () => {
    const formData = new FormData()
    formData.append('file', file)
    axios.post('http://localhost:3001/upload',formData )
    .then((response) => {
        console.log(response);
        if(response.data.Status === 'Success') {
            setMsg("File Successfully Uploaded");
        }else{
            setMsg("Error");
        }
    })
    .catch(er => console.log(er))
  }
   return (
    <div className="container" style={{paddingTop: 60}}>
		<div className="row d-flex justify-content-center align-items-center h-100">
		  <label className="form-label">Upload File</label>
		  <input className="form-control form-control-lg" type="file" onChange={(e) => setFile(e.target.files[0])}/>
		</div>
		
      <button type="button" className="btn btn-primary btn-lg" onClick={upload} style={{marginTop: '20px'}}>Upload</button>
	  <p><h1 style={{fontSize: '15px', textAlign: 'center', marginTop: '20px'}}>{msg}</h1></p>
    </div>
  )
}

export default App;
Run C:\react-j\my-app>npm start
http://localhost:3000/

Monday, September 4, 2023

React JS Node Express Employee Management System | Mysql bcrypt jsonwebtoken

React JS Node Express Employee Management System | Mysql bcrypt jsonwebtoken

https://expressjs.com/
Express JS
Fast, unopinionated, minimalist web framework for Node.js

Install
$ npm install express --save
PS C:\nodeproject> npm install express --save
https://expressjs.com/en/starter/hello-world.html

run PS C:\nodeproject> node index.js

//C:\nodeproject> node index.js
const express = require("express");
const mysql = require("mysql");
const cors = require("cors");

const bcrypt = require('bcrypt'); // https://www.npmjs.com/package/bcrypt npm i bcrypt
var jwt = require('jsonwebtoken'); //https://github.com/auth0/node-jsonwebtoken npm install jsonwebtoken

const app = express();
const port = 3001

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

const con = mysql.createConnection({
    user: "root",
    host: "localhost",
    password: "",
    database: "nodejsdb"
})

con.connect(function(err) {
    if(err) {
        console.log("Error in Connection");
    } else {
        console.log("Connected");
    }
})

app.get('/getEmployee', (req, res) => {
    const sql = "SELECT * FROM employee";
    con.query(sql, (err, result) => {
        if(err) return res.json({Error: "Get employee error in sql"});
        return res.json({Status: "Success", Result: result})
    })
})

app.get('/get/:id', (req, res) => {
    const id = req.params.id;
    const sql = "SELECT * FROM employee where id = ?";
    con.query(sql, [id], (err, result) => {
        if(err) return res.json({Error: "Get employee error in sql"});
        return res.json({Status: "Success", Result: result})
    })
})

app.put("/update/:id", (req, res) => {
  const userId = req.params.id;
  const q = "UPDATE employee SET `name`= ?, `email`= ?, `salary`= ?, `address`= ? WHERE id = ?";
 
  const values = [
    req.body.name,
    req.body.email,
    req.body.salary,
    req.body.address,
  ];
 
  con.query(q, [...values,userId], (err, data) => {
    if (err) return res.send(err);
    return res.json(data);
	//return res.json({Status: "Success"})
  });
});

app.delete('/delete/:id', (req, res) => {
    const id = req.params.id;
    const sql = "Delete FROM employee WHERE id = ?";
    con.query(sql, [id], (err, result) => {
        if(err) return res.json({Error: "delete employee error in sql"});
        return res.json({Status: "Success"})
    })
})

app.get('/adminCount', (req, res) => {
    const sql = "Select count(id) as admin from users";
    con.query(sql, (err, result) => {
        if(err) return res.json({Error: "Error in runnig query"});
        return res.json(result);
    })
})

app.get('/employeeCount', (req, res) => {
    const sql = "Select count(id) as employee from employee";
    con.query(sql, (err, result) => {
        if(err) return res.json({Error: "Error in runnig query"});
        return res.json(result);
    })
})

app.get('/salary', (req, res) => {
    const sql = "Select sum(salary) as sumOfSalary from employee";
    con.query(sql, (err, result) => {
        if(err) return res.json({Error: "Error in runnig query"});
        return res.json(result);
    })
})

app.post('/create', (req, res) => {
    const name = req.body.name;
    const email = req.body.email;
    const address = req.body.address;
    const salary = req.body.salary;
 
    con.query("INSERT INTO employee (name, email, address, salary) VALUES (?, ?, ?, ?)", [name, email, address, salary], 
        (err, result) => {
            if(result){
                res.send(result);
            }else{
                res.send({message: "ENTER CORRECT DETAILS!"})
            }
        }
    )
})

app.get('/hash', (req, res) => {	
    bcrypt.hash("123456", 10, (err, hash) => {
        if(err) return res.json({Error: "Error in hashing password"});
        const values = [
            hash
        ]
        return res.json({result: hash});
    } )
})

app.post('/login', (req, res) => {
    const sql = "SELECT * FROM users Where email = ?";
    con.query(sql, [req.body.email], (err, result) => {
        if(err) return res.json({Status: "Error", Error: "Error in runnig query"});
        if(result.length > 0) {
            bcrypt.compare(req.body.password.toString(), result[0].password, (err, response)=> {
                if(err) return res.json({Error: "password error"});
                if(response) {
					const token = jwt.sign({role: "admin"}, "jwt-secret-key", {expiresIn: '1d'});
					return res.json({Status: "Success", Token: token})
                } else {
                    return res.json({Status: "Error", Error: "Wrong Email or Password"});
                }
            })
        } else {
            return res.json({Status: "Error", Error: "Wrong Email or Password"});
        }
    })
})

app.post('/register',(req, res) => {
    const sql = "INSERT INTO users (`name`,`email`,`password`) VALUES (?)"; 
    bcrypt.hash(req.body.password.toString(), 10, (err, hash) => {
        if(err) return res.json({Error: "Error in hashing password"});
        const values = [
            req.body.name,
            req.body.email,
            hash,
        ]
        con.query(sql, [values], (err, result) => {
            if(err) return res.json({Error: "Error query"});
            return res.json({Status: "Success"});
        })
    } )
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
Install Requirements

mysql
https://github.com/mysqljs/mysql
$ npm install mysql
PS C:\nodeproject>npm install mysql

cors
CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
https://www.npmjs.com/package/cors
PS C:\nodeproject>npm i cors

bcrypt
A library to help you hash passwords.
https://www.npmjs.com/package/bcrypt
$ npm i bcrypt
PS C:\nodeproject>npm i bcrypt

jsonwebtoken
An implementation of JSON Web Tokens.
https://github.com/auth0/node-jsonwebtoken
$ npm install jsonwebtoken
PS C:\nodeproject>npm install jsonwebtoken

React JS
https://create-react-app.dev/

Create Project
C:\react-js>npx create-react-app my-app

Run
C:\react-js\my-app> npm start

C:\react-js\my-app\src\App.js
//C:\react-js\my-app\src\App.js
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Login from "./components/login";
import SignUp from "./components/signup";
import {RequireToken} from './components/Auth.js'

import Dashboard from "./components/dashboard";
import Home from "./components/home";
import Employee from "./components/employee";
import Profile from "./components/profile";
import AddEmployee from "./components/addemployee";
import EditEmployee from './components/editemployee'

function App() {
  return (
    <div className="app">
        <BrowserRouter>
            <Routes>
              <Route path="/login" element={<Login />} />
              <Route path="/signup" element={<SignUp />} />
              
              <Route path='/' element={
                  <RequireToken>
                    <Dashboard />
                  </RequireToken>
                  }>
                  <Route path='' element={<Home />}></Route>
                  <Route path='/employee' element={<Employee />}></Route>
                  <Route path='/profile' element={<Profile />}></Route>
                  <Route path='/create' element={<AddEmployee />}></Route>
                  <Route path='/employeeedit/:id' element={<EditEmployee />}></Route>
              </Route>
            </Routes>
        </BrowserRouter>
    </div>
  );
}
  
export default App;
C:\react-js\my-app\src\components\signup.js
//C:\react-js\my-app\src\components\signup.js
import { useState } from "react";
import Axios from "axios";

const SignUp = () => {
   
    const [email, setEmail] = useState("");
    const [name, setName] = useState("");
    const [password, setPassword] = useState("");
    const [registerStatus, setRegisterStatus] = useState("");

    const register = (e) => {
        e.preventDefault();
        Axios.post("http://localhost:3001/register", {
          email: email,
          name: name,
          password: password,
        }).then((response) => {
          console.log(response);
          if(response.data.message){
            setRegisterStatus(response.data.message);
          }else{
            setRegisterStatus("ACCOUNT CREATED SUCCESSFULLY");
          }
        })
    }

  let imgs = [
    'https://as2.ftcdn.net/v2/jpg/03/39/70/91/1000_F_339709132_H9HSSTtTmayePcbARkTSB2qoZTubJ6bR.jpg',
  ];
  return (
        <div className="container" style={{paddingTop: 60}}>
          <div className="container-fluid h-custom">
            <div className="row d-flex justify-content-center align-items-center h-100">
              <div className="col-md-8 col-lg-6 col-xl-4 offset-xl-1">
                <form>
                  <div className="d-flex flex-row align-items-center justify-content-center justify-content-lg-start">
                    <p className="lead fw-normal mb-0 me-3">Create Your Account</p>
                  </div>
                  <p><h1 style={{fontSize: '15px', textAlign: 'center', marginTop: '20px'}}>{registerStatus}</h1></p>
                  <div className="form-outline mb-4">
                    <input
                        type="text"
                        className="form-control form-control-lg"
                        placeholder="Enter Name"
                        onChange={(e) => {setName(e.target.value)}} placeholder="Enter your Name" required
                    />
                    <label className="form-label">Name</label>
                  </div>
                  <div className="form-outline mb-4">
                    <input
                      type="email"
                      className="form-control form-control-lg"
                      onChange={(e) => {setEmail(e.target.value)}} placeholder="Enter your Email Address" required
                    />
                    <label className="form-label">Email address</label>
                  </div>
                  <div className="form-outline mb-3">
                    <input
                      type="password"
                      className="form-control form-control-lg"
                      onChange={(e) => {setPassword(e.target.value)}} placeholder="Enter your Password" required
                    />
                    <label className="form-label">Password</label>
                  </div>
   
                  <div className="d-flex justify-content-between align-items-center">
                    <div className="form-check mb-0">
                      <input className="form-check-input me-2" type="checkbox" value=""/>
                      <label className="form-check-label">
                        Remember me
                      </label>
                    </div>
                    <a href="#" className="text-body">Forgot password?</a>
                  </div>
   
                  <div className="text-center text-lg-start mt-4 pt-2">
                    <button type="button" className="btn btn-primary btn-lg" onClick={register}>Sign Up</button>
                    <p className="small fw-bold mt-2 pt-1 mb-0">Login to your account <a href="login" className="link-danger">Login</a></p>
                  </div>
   
                </form>
              </div>
              <div className="col-md-9 col-lg-6 col-xl-5">
                <img src={imgs[0]} className="img-fluid"/>
              </div>
            </div>
          </div>
        </div>
  );
};
  
export default SignUp;
C:\react-js\my-app\src\components\login.js
//C:\react-js\my-app\src\components\login.js
import React, {useState} from "react";
import axios from "axios";
import { useNavigate } from 'react-router-dom'
import loginimg from './login.png';
import {setToken} from './Auth.js'

const Login = () => {
	const [email, setEmail] = useState("");
	const [password, setPassword] = useState("");
   
	const [error, setError] = useState('')
	const navigate = useNavigate()
	
	const login = (e) => {
		e.preventDefault();
		axios.post("http://localhost:3001/login", {
		  email: email,
		  password: password,
		})
		.then(res => {
			console.log(res);
			if(res.data.Status === 'Success') {
        console.log(res.data.Token);
        setToken(res.data.Token)
				navigate('/');
			} else {
				setError(res.data.Error);
			}
		})
		.catch(err => console.log(err));
	}
   
  return (
        <div className="container" style={{paddingTop: 60}}>
          <div className="container-fluid h-custom">
            <div className="row d-flex justify-content-center align-items-center h-100">
              <div className="col-md-9 col-lg-6 col-xl-5">
                <img src={loginimg} alt="" className="img-fluid"/>
              </div>
              <div className="col-md-8 col-lg-6 col-xl-4 offset-xl-1">
                <form>
                  <div className="d-flex flex-row align-items-center justify-content-center justify-content-lg-start">
                    <p className="lead fw-normal mb-0 me-3">Login to your account</p>
                  </div>
                    <h1 style={{color: 'red', fontSize: '15px', textAlign: 'center', marginTop: '20px'}}>{error && error}</h1>
                  <div className="form-outline mb-4">
                    <input
                      type="email"
                      className="form-control form-control-lg"
                      placeholder="Enter a valid email address"
                      onChange={(e) => {setEmail(e.target.value)}} required
                    />
                    <label className="form-label">Email address</label>
                  </div>
                  <div className="form-outline mb-3">
                    <input
                      type="password"
                      className="form-control form-control-lg"
                      placeholder="Enter password"
                      onChange={(e) => {setPassword(e.target.value)}} required
                    />
                    <label className="form-label">Password</label>
                  </div>
   
                  <div className="d-flex justify-content-between align-items-center">
                    <div className="form-check mb-0">
                      <input className="form-check-input me-2" type="checkbox" value=""/>
                      <label className="form-check-label">
                        Remember me
                      </label>
                    </div>
                    <a href="/#" className="text-body">Forgot password?</a>
                  </div>
   
                  <div className="text-center text-lg-start mt-4 pt-2">
                    <button type="button" className="btn btn-primary btn-lg" onClick={login}>Login</button>
                    <p className="small fw-bold mt-2 pt-1 mb-0">Login to your account <a href="signup" className="link-danger">Sign Up</a></p>
                  </div>
   
                </form>
              </div>
            </div>
          </div>
        </div>
  );
};
  
export default Login;
C:\react-js\my-app\src\components\Auth.js
//C:\react-js\my-app\src\components\Auth.js
import React, { } from "react";
 
import {
    Navigate ,
    useLocation
  } from "react-router-dom";
export const setToken = (token) =>{
    // set token in localStorage
    localStorage.setItem('Token', token)
}
export const fetchToken = (token) =>{
    // fetch the token
    return localStorage.getItem('Token')
}
export function RequireToken({children}) {
     
    let auth = fetchToken()
    let location = useLocation();
   
    if (!auth) {
       
      return <Navigate to="/login" state={{ from: location }} />;
    }
   
    return children;
}
C:\react-js\my-app\src\components\dashboard.js
//C:\react-js\my-app\src\components\dashboard.js
import React, {  } from 'react'
import { Link, Outlet, useNavigate } from 'react-router-dom'

function Dashboard() {

    const navigate = useNavigate();
    const signOut = () => {
        localStorage.removeItem('Token')
        navigate("/login");
    }
	return (
		<div className="container-fluid">
			<div className="row flex-nowrap">
				<div className="col-auto col-md-3 col-xl-2 px-sm-2 px-0 bg-dark">
					<div className="d-flex flex-column align-items-center align-items-sm-start px-3 pt-2 text-white min-vh-100">
						<a href="/" className="d-flex align-items-center pb-3 mb-md-1 mt-md-3 me-md-auto text-white text-decoration-none">
							<span className="fs-5 fw-bolder d-none d-sm-inline">Admin Dashboard</span>
						</a>
						<ul className="nav nav-pills flex-column mb-sm-auto mb-0 align-items-center align-items-sm-start" id="menu">
							<li>
								<Link to="/" data-bs-toggle="collapse" className="nav-link text-white px-0 align-middle">
									<span className="ms-1 d-none d-sm-inline">Dashboard</span> 
								</Link>
							</li>
							<li>
								<Link to="/employee" className="nav-link px-0 align-middle text-white">
									<span className="ms-1 d-none d-sm-inline">Manage Employees</span> 
								</Link>
							</li>
							<li>
								<Link to="profile" className="nav-link px-0 align-middle text-white">
									<span className="ms-1 d-none d-sm-inline">Profile</span>
								</Link>
							</li>
							<li>
								<button type = 'button' className="btn btn-success" onClick= {signOut}>Sign Out</button>
							</li>
						</ul>
					</div>
				</div>
				<div className="col p-0 m-0">
					<div className='p-2 d-flex justify-content-center shadow'>
						<h4>Employee Management System</h4>						
					</div>
					<Outlet />
				</div>
			</div>
		</div>
	)
}

export default Dashboard
C:\react-js\my-app\src\components\home.js
//C:\react-js\my-app\src\components\home.js
import React, { useEffect, useState } from 'react'
import axios from 'axios'

function Home() {
  const [adminCount, setAdminCount] = useState()
  const [employeeCount, setEmployeeCount] = useState()
  const [salary, setSalary] = useState()

  useEffect(() => {
    axios.get('http://localhost:3001/adminCount')
		.then(res => {
			setAdminCount(res.data[0].admin)
		}).catch(err => console.log(err));

    axios.get('http://localhost:3001/employeeCount')
		.then(res => {
			setEmployeeCount(res.data[0].employee)
		}).catch(err => console.log(err));

    axios.get('http://localhost:3001/salary')
		.then(res => {
			setSalary(res.data[0].sumOfSalary)
		}).catch(err => console.log(err));

  } , [])
  
  return (
    <div>
      <div className='p-3 d-flex justify-content-around mt-3'>
        <div className='px-3 pt-2 pb-3 border shadow-sm w-25'>
          <div className='text-center pb-1'>
            <h4>Admin</h4>
          </div>
          <hr />
          <div>
            <h5>Total: {adminCount}</h5>
          </div>
        </div>
        <div className='px-3 pt-2 pb-3 border shadow-sm w-25'>
          <div className='text-center pb-1'>
            <h4>Employee</h4>
          </div>
          <hr />
          <div>
            <h5>Total: {employeeCount}</h5>
          </div>
        </div>
        <div className='px-3 pt-2 pb-3 border shadow-sm w-25'>
          <div className='text-center pb-1'>
            <h4>Salary</h4>
          </div>
          <hr />
          <div>
            <h5>Total: {salary}</h5>
          </div>
        </div>
      </div>
    </div>
  )
}

export default Home
C:\react-js\my-app\src\components\employee.js
//C:\react-js\my-app\src\components\employee.js
import axios from 'axios'
import React, { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'

function Employee() {
  const [data, setData] = useState([])

  useEffect(()=> {
    axios.get('http://localhost:3001/getEmployee')
    .then(res => {
      if(res.data.Status === "Success") {
        setData(res.data.Result);
      } else {
        alert("Error")
      }
    })
    .catch(err => console.log(err));
  }, [])

  const handleDelete = (id) => {
    axios.delete('http://localhost:3001/delete/'+id)
    .then(res => {
      if(res.data.Status === "Success") {
        window.location.reload(true);
      } else {
        alert("Error")
      }
    })
    .catch(err => console.log(err));
  }

  return (
    <div className='px-5 py-3'>
      <div className='d-flex justify-content-center mt-2'>
        <h3>Employee List</h3>
      </div>
      <Link to="/create" className='btn btn-success'>Add Employee</Link>
      <div className='mt-3'>
        <table className="table table-striped">
          <thead>
            <tr>
              <th>Name</th>
              <th>Email</th>
              <th>Address</th>
              <th>Salary</th>
              <th>Action</th>
            </tr>
          </thead>
          <tbody>
            {data.map((employee, index) => {
              return <tr key={index}>
                  <td>{employee.name}</td>
                  <td>{employee.email}</td>
                  <td>{employee.address}</td>
                  <td>{employee.salary}</td>
                  <td>
                    <Link to={`/employeeedit/`+employee.id} className='btn btn-primary btn-sm me-2'>edit</Link>
                    <button onClick={e => handleDelete(employee.id)} className='btn btn-sm btn-danger'>delete</button>
                  </td>
              </tr>
            })}
          </tbody>
        </table>
      </div>
    </div>
  )
}

export default Employee
C:\react-js\my-app\src\components\addemployee.js
//C:\react-js\my-app\src\components\addemployee.js
import axios from 'axios';
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom';

function AddEmployee() {
	const [name, setName] = useState("");
	const [email, setEmail] = useState("");
	const [address, setaddress] = useState("");
	const [salary, setsalary] = useState("");
	const [registerStatus, setRegisterStatus] = useState("");
	
	const navigate = useNavigate()

	const create = (e) => {
		e.preventDefault();
		axios.post("http://localhost:3001/create", {
		  name: name,
		  email: email,
		  address: address,
		  salary: salary,
		}).then((response) => {
		  // setRegisterStatus(response);
		  console.log(response);
		  if(response.data.message){
			setRegisterStatus(response.data.message);
		  }else{
			navigate('/employee')
			alert("Success");
		  }
		})
		.catch(err => console.log(err));
	}

	return (
		<div className='d-flex flex-column align-items-center pt-4'>
			<h2>Add Employee</h2>
			<form className="row g-3 w-50">
				<h1 style={{fontSize: '15px', textAlign: 'center', marginTop: '20px'}}>{registerStatus}</h1>
				<div className="col-12">
					<label className="form-label">Name</label>
					<input type="text" className="form-control" placeholder='Enter Name' autoComplete='off'
					onChange={(e) => {setName(e.target.value)}}/>
				</div>
				<div className="col-12">
					<label className="form-label">Email</label>
					<input type="email" className="form-control" placeholder='Enter Email' autoComplete='off'
					onChange={(e) => {setEmail(e.target.value)}}/>
				</div>
				<div className="col-12">
					<label className="form-label">Salary</label>
					<input type="text" className="form-control" placeholder="Enter Salary" autoComplete='off'
					onChange={(e) => {setsalary(e.target.value)}}/>
				</div>
				<div className="col-12">
					<label className="form-label">Address</label>
					<input type="text" className="form-control" placeholder="1234 Main St" autoComplete='off'
					onChange={(e) => {setaddress(e.target.value)}}/>
				</div>
				<div className="col-12">
					<button type="submit" className="btn btn-primary" onClick={create}>Create</button>
				</div>
			</form>
		</div>

	)
}

export default AddEmployee
C:\react-js\my-app\src\components\editemployee.js
//C:\react-js\my-app\src\components\editemployee.js
import axios from 'axios';
import React, { useState, useEffect } from 'react'
import { useLocation, useNavigate, useParams } from "react-router-dom";

function EditEmployee() {
    const {id} = useParams();
    const [employee, setemployee] = useState({
        name: "",
        email: "",
        address: "",
        salary: "",
    });

    const location = useLocation();
    const navigate = useNavigate();
 
    const employeeId = location.pathname.split("/")[2];
    //alert(employeeId);
    const handleChange = (e) => {
        setemployee((prev) => ({ ...prev, [e.target.name]: e.target.value }));
    };
 
    useEffect(() => {
        axios.get("http://localhost:3001/get/"+id)
        .then(res => {
            console.log(res.data.Result[0])
            setemployee(res.data.Result[0]);
        })
        .catch(err => console.log(err))
    }, []);

    const handleUpdate = async (e) => {
        e.preventDefault();
 
        try {
            await axios.put(`http://localhost:3001/update/${employeeId}`, employee);
            navigate("/");
        } catch (err) {
            console.log(err);
        }
    };

	return (
		<div className='d-flex flex-column align-items-center pt-4'>
			<h2>Edit Employee</h2>
			<form className="row g-3 w-50">
				<div className="col-12">
                    <input type="text" className="form-control" id="id" name="id" value={id} disabled />
					<label className="form-label">Name</label>
					<input type="text" className="form-control" placeholder='Enter Name' autoComplete='off'
					name="name" value={employee.name} onChange={handleChange}/>
				</div>
				<div className="col-12">
					<label className="form-label">Email</label>
					<input type="email" className="form-control" placeholder='Enter Email' autoComplete='off'
					name="email" value={employee.email} onChange={handleChange}/>
				</div>
				<div className="col-12">
					<label className="form-label">Salary</label>
					<input type="text" className="form-control" placeholder="Enter Salary" autoComplete='off'
					name="salary" value={employee.salary} onChange={handleChange}/>
				</div>
				<div className="col-12">
					<label className="form-label">Address</label>
					<input type="text" className="form-control" placeholder="1234 Main St" autoComplete='off'
					name="address" value={employee.address} onChange={handleChange}/>
				</div>
				<div className="col-12">
					<button type="submit" className="btn btn-primary" onClick={handleUpdate}>Update</button>
				</div>
			</form>
		</div>

	)
}

export default EditEmployee
C:\react-js\my-app\src\components\profile.js
//C:\react-js\my-app\src\components\profile.js
import React, { } from "react";
 
export default function Profile(){
    return(
      <div className="container" style={{paddingTop: 60}}>
        <div className="row">
            <div style = {{minHeight: 800, marginTop: 20 }}>
                <h1>Profile Page</h1>
                <p>Hi, this is your profile</p>
            </div>
        </div>  
      </div>
    )
}
Install axios
https://github.com/axios/axios

Installing the Axios Client
$ npm install axios
C:\reactdev\myreactdev>npm install axios

Install React Router Dom
https://www.npmjs.com/package/react-router-dom
C:\react-js\myreactdev>npm i react-router-dom --save
//react-js\my-app\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">
  </head>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html
Run C:\react-j\my-app>npm start
http://localhost:3000/

Related Post