user auth frontend

PHOTO EMBED

Sun Jul 23 2023 09:23:18 GMT+0000 (Coordinated Universal Time)

Saved by @nelson22

components > workoutdetails.js

import React from 'react'
import {useWorkoutContext} from '../hooks/useWorkoutContext';
import { useAuthContext } from '../hooks/useAuthContext';

const WorkoutDetails = ({workout}) => {
  const {user} = useAuthContext();
  const {dispatch} = useWorkoutContext();

  const handleClick = async () => {
    console.log("workout id =", workout._id);
    const response = await fetch(`/api/workouts/${workout._id}`, {
      method: 'DELETE',
      headers: {
        'Authorization': `Bearer ${user.token}`
      }
    })
    const json = await response.json();
    if(response.ok){
      dispatch({type: 'DELETE_WORKOUT', payload: json});
    }
  }
  return (
    <div className='workout-wrap'>
        <p className='workout-title'>{workout.title}</p>
        <p className='workout-details'><strong>Reps: </strong>{workout.reps}</p>
        <p className='workout-details'><strong>Load: </strong>{workout.load}</p>
        <p className='workout-details'><strong>Created at: </strong>{workout.createdAt}</p>
        <button className='delete' onClick={handleClick}>Delete Workout</button>
    </div>
  )
}

export default WorkoutDetails

----------------------------------------------------------------

Pages > Home.js

import React from 'react';
import { useEffect } from 'react';
import WorkoutDetails from '../components/WorkoutDetails';
import WorkoutForm from '../components/WorkoutForm';
import {useWorkoutContext} from '../hooks/useWorkoutContext';
import { useAuthContext } from '../hooks/useAuthContext';

const Home = () => {
  //const [workout, setWorkout] = useState(null)
  const {workouts, dispatch} = useWorkoutContext();
  const {user} = useAuthContext();
  useEffect(() => {
    const fetchWorkout = async () => {
      const response = await fetch('/api/workouts/', {
        headers: {
          'Authorization': `Bearer ${user.token}`
        }
          
      })
      const json = await response.json()
      if(response.ok){
        //setWorkout(json)
        dispatch({type: 'SETWORKOUTS', payload: json})
      }
    }
    if(user){
      fetchWorkout()
    }
  }, [user])
  return (
    <div className='container'>
      <div className='workout-main'>
        <h2 className='workout-hd'>Fill the form below to add your workout.</h2>
        <WorkoutForm></WorkoutForm>
        <h2 className='workout-hd'>Below are the lists of workouts to be done every week.</h2>
        {workouts && workouts.map((data) => (
          <WorkoutDetails key={data._id} workout={data}></WorkoutDetails>
        ))}
      </div>
    </div>
  )
}

export default Home

----------------------------------------------------------

CONTEXT > AuthContext.js

import { createContext, useEffect, useReducer } from "react";

export const AuthContext = createContext();

const initState = {
    user: null
}
const authReducer = (state, action) => {
    switch(action.type){
        case 'LOGIN':
            return { user: action.payload}
        case 'LOGOUT':
            return {user: null}
        default:
            return state
    }
}

export const AuthContextProvider = ({children}) => {
    const [state, dispatch] = useReducer(authReducer, initState);
    console.log("auth context = ", state);

    useEffect(() => {
        let user = JSON.parse(localStorage.getItem('user'));
        if(user){
            dispatch({type: 'LOGIN', payload: user});
        }
    }, []);

    return(
        <AuthContext.Provider value={{...state, dispatch}}>
            {children}
        </AuthContext.Provider>
    )
}

-----------------------------------------------------------

HOOKS > useAuthContext.js

import { AuthContext } from "../context/AuthContext";
import { useContext } from "react";

export const useAuthContext = () => {
    const context = useContext(AuthContext);

    if(!context){
        throw Error("useAuthContext context must be used inside AuthContextProvider");
    }

    return context
}

-----------------------------------------------------------

INDEX.JS

import { AuthContextProvider } from './context/AuthContext';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <AuthContextProvider>
      <App />
    </AuthContextProvider>
  </React.StrictMode>
);

-----------------------------------------------------------

HOOKS > useSignup.js

import { useState } from "react";
import {useAuthContext} from './useAuthContext';

export const useSignup = () => {
    const [error, setError] = useState(null);
    const [isLoading, setIsLoading] = useState(false);

    const {dispatch} = useAuthContext();

    const signup = async (email, password) => {
        setError(null);
        setIsLoading(true);

        const response = await fetch('/api/user/signup', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({email, password})
        });
        const json = await response.json()
        if(!response.ok){
            setIsLoading(false);
            setError(json.error);
        }
        if(response.ok){
            localStorage.setItem('user', JSON.stringify(json));

            dispatch({type: 'LOGIN', payload: json});
            setIsLoading(false);
            setError(null);
        }
    }

    return {signup, isLoading, error}
}

-----------------------------------------------------------

PAGES > Signup.js

import React, {useState} from 'react'
import { useSignup } from '../hooks/useSignup';

const Signup = () => {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');

    const {signup, isLoading, error} = useSignup();
    
    const handleSubmit = async (e) => {
        e.preventDefault();

        await signup(email, password);
        console.log(email, password);
    }
  
    return (
        <div className='flex-wrap'>
            <form className='signup-form'>
                <h2>Sign up</h2>
                <input type="text" placeholder="Enter your email" value={email} onChange={(e) => setEmail(e.target.value)} />
                <input type="password" placeholder="Enter your password" value={password} onChange={(e) => setPassword(e.target.value)} />
                <input type="submit" className="submit" value="Submit" onClick={(e) => handleSubmit(e)} />
                <p className='error'>{error && error}</p>
            </form>
        </div>
    )
}

export default Signup

-----------------------------------------------------------

HOOKS > useLogin.js

import { useState } from "react";
import {useAuthContext} from './useAuthContext';

export const useLogin = () => {
    const [error, setError] = useState(null);
    const [isLoading, setIsLoading] = useState(false);

    const {dispatch} = useAuthContext();

    const login = async (email, password) => {
        setError(null);
        setIsLoading(true);

        const response = await fetch('/api/user/login', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({email, password})
        });
        const json = await response.json()
        if(!response.ok){
            setIsLoading(false);
            setError(json.error);
        }
        if(response.ok){
            localStorage.setItem('user', JSON.stringify(json));

            dispatch({type: 'LOGIN', payload: json});
            setIsLoading(false);
            setError(null);
        }
    }

    return {login, isLoading, error}
}

-----------------------------------------------------------

PAGES > Login.js

import React, {useState} from 'react';
import { useLogin } from '../hooks/useLogin';

const Login = () => {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const {login, isLoading, error} = useLogin();

    const handleSubmit = async (e) => {
        e.preventDefault();
        await login(email, password);
        console.log(email, password);
    }
  
    return (
        <div className='flex-wrap'>
            <form className='login-form'>
                <h2>Login</h2>
                <input type="text" placeholder="Enter your email" value={email} onChange={(e) => setEmail(e.target.value)} />
                <input type="password" placeholder="Enter your password" value={password} onChange={(e) => setPassword(e.target.value)} />
                <input type="submit" disabled={isLoading} className="submit" value="Submit" onClick={(e) => handleSubmit(e)} />
                <p className='error'>{error && error}</p>
            </form>
        </div>
    )
}

export default Login

-----------------------------------------------------------

HOOKS > useLogout.js

import { useAuthContext } from "./useAuthContext";

export const useLogout = () => {
    const {dispatch} = useAuthContext();

    const logout = () => {
        localStorage.removeItem('user');

        dispatch({type: 'LOGOUT'});
    }

    return {logout}
}

-----------------------------------------------------------

COMPONENTS > Navbar.js

import React from 'react';
import { Link } from 'react-router-dom';
import { useLogout } from '../hooks/useLogout';
import { useAuthContext } from '../hooks/useAuthContext';

const Navbar = () => {
  const {user} = useAuthContext();
  const {logout} = useLogout();

  const handleClick = () => {
    logout();
  }
  return (
    <header className='header'>
        <Link to="/">
            Workout Buddy
        </Link>
        {user ? 
          <div>
            {console.log(user.email)}
            <span className='loggedin'>{user.email}</span>
            <Link onClick={handleClick} className='nav-items'>
                Logout
            </Link>
          </div>
          :
          <div>
            <Link to="/login" className='nav-items'>
                Login
            </Link>
            <Link to="/Signup" className='nav-items'>
                Signup
            </Link>
          </div>
        }
    </header>
  )
}

export default Navbar

------------------------------------------------------------

components > workoutforms.js

import { useState } from 'react'
import {useWorkoutContext} from '../hooks/useWorkoutContext';
import {useAuthContext} from '../hooks/useAuthContext';

const WorkoutForm = () => {
    const {dispatch} = useWorkoutContext();
    const [title, setTitle] = useState('');
    const [reps, setReps] = useState('');
    const [load, setLoad] = useState('');
    const [error, setError] = useState('');

    const {user} = useAuthContext();

    const handleSubmit = async (e) => {
        e.preventDefault();
        

        if(!user){
            setError('You must be logged in');
            return
        }
        const formData = {title, reps, load};
        const response = await fetch('/api/workouts/', {
            method: 'POST',
            body: JSON.stringify(formData),
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${user.token}`
            }
        })
        const json = await response.json();
        if(!response.ok){
            setError(json.error);
        }
        
        if(response.ok){
            dispatch({type: 'CREATE_WORKOUT', payload: json})
            setError('');
            setTitle('');
            setReps('');
            setLoad('');
            console.log("Workout added succcessfully!!!", json);
        }

    }

  return (
    <form onSubmit={handleSubmit} className="workout-form">
        <input type="text" className="form-input" placeholder="Enter Workout Title" onChange={e => setTitle(e.target.value)} value={title} /> <br />
        <input type="text" className="form-input" placeholder="Enter Workout Reps" onChange={e => setReps(e.target.value)} value={reps} /> <br />
        <input type="text" className="form-input" placeholder="Enter Workout Load" onChange={e => setLoad(e.target.value)} value={load} /> <br />
        <input type="submit" value="Submit" className='form-submit' />
        {error && <p>{error}</p>}
    </form>
  )
}

export default WorkoutForm

---------------------------------------------

app.js

import './App.css';
import {BrowserRouter, Routes, Route, Navigate} from 'react-router-dom';
import Home from './pages/Home';
import Navbar from './components/Navbar';
import Login from './pages/Login';
import Signup from './pages/Signup';
import { useAuthContext } from './hooks/useAuthContext';

function App() {
  const {user} = useAuthContext();
  return (
    <div className="App">
      <BrowserRouter>
        <Navbar />
        <Routes>
          <Route 
            path="/"
            element={user ? <Home /> : <Navigate to="/login" />}
          />
          <Route 
            path="/login"
            element={!user ? <Login /> : <Navigate to="/" />}
          />
          <Route 
            path="/signup"
            element={!user ? <Signup /> : <Navigate to="/" />}
          />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;
content_copyCOPY