diff --git a/src/App.js b/src/App.js index 4442af9..f636ebe 100644 --- a/src/App.js +++ b/src/App.js @@ -4,14 +4,18 @@ import "./App.css"; import { Routes, Route } from "react-router-dom"; import Homepage from "./pages/Homepage"; import PostPage from "./pages/PostPage"; +import LoginPage from "./pages/LoginPage"; +import NavBar from "./component/NavBar"; export default function App() { return (
+ {/* more pages to be added here later */} } /> } /> + } />
); diff --git a/src/component/NavBar.js b/src/component/NavBar.js new file mode 100644 index 0000000..f56bab1 --- /dev/null +++ b/src/component/NavBar.js @@ -0,0 +1,39 @@ +import { Link } from "react-router-dom"; +import { useSelector, useDispatch } from "react-redux"; +import { getUser } from "../store/auth/selectors"; +import { logout } from "../store/auth/slice"; + +const NavBar = () => { + const user = useSelector(getUser); + const dispatch = useDispatch(); + + return ( +
+ +

Coders!

+ +
+ {user ? ( +
+

Welcome {user.name}!

+ +
+ ) : ( + + + + )} +
+
+ ); +}; + +export default NavBar; diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js new file mode 100644 index 0000000..bcbb483 --- /dev/null +++ b/src/pages/LoginPage.js @@ -0,0 +1,56 @@ +// src/pages/LoginPage.js +import React, { useState } from "react"; +import { useDispatch } from "react-redux"; +import { login } from "../store/auth/thunks"; +import { useNavigate } from "react-router-dom"; + +export default function LoginPage() { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const dispatch = useDispatch(); + const navigate = useNavigate(); + + function handleSubmit(event) { + event.preventDefault(); + + // Make a POST request + // Create a thunk for this! + dispatch(login(email, password, navigate)); + + // TODO + console.log("TODO login with:", email, password); + setEmail(""); + setPassword(""); + } + + return ( +
+

Login

+
+

+ +

+

+ +

+

+ +

+
+
+ ); +} diff --git a/src/store/auth/selectors.js b/src/store/auth/selectors.js new file mode 100644 index 0000000..1260f49 --- /dev/null +++ b/src/store/auth/selectors.js @@ -0,0 +1 @@ +export const getUser = (reduxState) => reduxState.auth.user; diff --git a/src/store/auth/slice.js b/src/store/auth/slice.js new file mode 100644 index 0000000..da83880 --- /dev/null +++ b/src/store/auth/slice.js @@ -0,0 +1,28 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const initialState = { + loading: false, + token: null, + user: null, +}; + +export const authSlice = createSlice({ + name: "auth", + initialState, + reducers: { + startLoading: (state) => { + state.loading = true; + }, + saveLoginData: (state, action) => { + state.token = action.payload.token; + state.user = action.payload.user; + }, + logout: (state) => { + return { ...initialState }; + }, + }, +}); + +export const { startLoading, saveLoginData, logout } = authSlice.actions; + +export default authSlice.reducer; diff --git a/src/store/auth/thunks.js b/src/store/auth/thunks.js new file mode 100644 index 0000000..7d27d32 --- /dev/null +++ b/src/store/auth/thunks.js @@ -0,0 +1,35 @@ +import axios from "axios"; +import { saveLoginData, startLoading } from "./slice"; + +import { API_URL } from "../../config"; + +export const login = + (email, password, navigate) => async (dispatch, getState) => { + try { + // dispatch => set loading to true + dispatch(startLoading()); + + // Make POST to /login + const response = axios.post(`${API_URL}/login`, { + email, + password, + }); + + const token = response.data.jwt; + + const profileResponse = axios.get(`${API_URL}/me`, { + headers: { + authorization: `Bearer ${token}`, + }, + }); + + navigate("/"); + + console.log("me response", profileResponse.data); + // store it in redux => dispatch something. + + dispatch(saveLoginData({ token, user: profileResponse.data })); + } catch (e) { + console.log(e.message); + } + }; diff --git a/src/store/index.js b/src/store/index.js index 98aa5e1..5b27baa 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2,11 +2,13 @@ import { configureStore } from "@reduxjs/toolkit"; import feedReducer from "./feed/slice"; import postPageReducer from "./postPage/slice"; +import authReducer from "./auth/slice"; const store = configureStore({ reducer: { feed: feedReducer, postPage: postPageReducer, + auth: authReducer, }, });