Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REACT_APP_SERVER_URL=http://localhost:5005
# VITE_LIVE_SERVER=https://bookworm-backend.adaptable.app
VITE_LIVE_SERVER=http://localhost:5005
DEV_SERVER=http://localhost:5005
4 changes: 3 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
REACT_APP_SERVER_URL=http://localhost:5005
REACT_APP_SERVER_URL=http://localhost:5005
# update live server string when working locally - change to localhost:5005
VITE_LIVE_SERVER=
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ dist
dist-ssr
*.local

.env

# Editor directories and files
.vscode/*
!.vscode/extensions.json
Expand Down
2,215 changes: 2,182 additions & 33 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@fluentui/react-components": "^9.26.1",
"axios": "^1.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
88 changes: 64 additions & 24 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import {
FluentProvider,
teamsLightTheme,
Button,
Input
} from "@fluentui/react-components";
import "./App.css";
import { Routes, Route } from "react-router-dom";
import Navbar from "./components/Navbar";
Expand All @@ -14,30 +20,64 @@ import IsAnon from "./components/IsAnon";
function App() {
return (
<div className="App">
<Navbar />

<Routes>
<Route path="/" element={<HomePage />} />

<Route
path="/projects"
element={ <IsPrivate> <ProjectListPage /> </IsPrivate> }
/>

<Route
path="/projects/:projectId"
element={ <IsPrivate> <ProjectDetailsPage /> </IsPrivate> }
/>

<Route
path="/projects/edit/:projectId"
element={ <IsPrivate> <EditProjectPage /> </IsPrivate> }
/>

<Route path="/signup" element={<IsAnon> <SignupPage /> </IsAnon>} />
<Route path="/login" element={<IsAnon> <LoginPage /> </IsAnon>} />

</Routes>
<FluentProvider theme={teamsLightTheme}>
<Navbar />

<Button appearance="primary">FLUENT UI FOR STEPHEN</Button>

<Routes>
<Route path="/" element={<HomePage />} />

<Route
path="/projects"
element={
<IsPrivate>
{" "}
<ProjectListPage />{" "}
</IsPrivate>
}
/>

<Route
path="/projects/:projectId"
element={
<IsPrivate>
{" "}
<ProjectDetailsPage />{" "}
</IsPrivate>
}
/>

<Route
path="/projects/edit/:projectId"
element={
<IsPrivate>
{" "}
<EditProjectPage />{" "}
</IsPrivate>
}
/>

<Route
path="/signup"
element={
<IsAnon>
{" "}
<SignupPage />{" "}
</IsAnon>
}
/>
<Route
path="/login"
element={
<IsAnon>
{" "}
<LoginPage />{" "}
</IsAnon>
}
/>
</Routes>
</FluentProvider>
</div>
);
}
Expand Down
16 changes: 6 additions & 10 deletions src/components/AddProject.jsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
import { useState } from "react";
import axios from "axios";

const API_URL = "http://localhost:5005";
const API_URL = import.meta.env.VITE_LIVE_SERVER;

function AddProject(props) {
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");


const handleSubmit = (e) => {
e.preventDefault();
const requestBody = { title, description };

// Get the token from the localStorage
const storedToken = localStorage.getItem('authToken');
const storedToken = localStorage.getItem("authToken");

// Send the token through the request "Authorization" Headers
axios
.post(
`${API_URL}/api/projects`,
requestBody,
{ headers: { Authorization: `Bearer ${storedToken}` } }
)
.post(`${API_URL}/api/projects`, requestBody, {
headers: { Authorization: `Bearer ${storedToken}` },
})
.then((response) => {
// Reset the state
setTitle("");
Expand All @@ -31,7 +28,6 @@ function AddProject(props) {
.catch((error) => console.log(error));
};


return (
<div className="AddProject">
<h3>Add Project</h3>
Expand Down Expand Up @@ -59,4 +55,4 @@ function AddProject(props) {
);
}

export default AddProject;
export default AddProject;
25 changes: 10 additions & 15 deletions src/components/AddTask.jsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,44 @@
import { useState } from "react";
import axios from "axios";

const API_URL = "http://localhost:5005";

const API_URL = import.meta.env.VITE_LIVE_SERVER;

function AddTask(props) {
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");


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

// We need the project id when creating the new task
const { projectId } = props;
// Create an object representing the body of the POST request
const requestBody = { title, description, projectId };

// Get the token from the localStorage
const storedToken = localStorage.getItem('authToken');
const storedToken = localStorage.getItem("authToken");

// Send the token through the request "Authorization" Headers
// Send the token through the request "Authorization" Headers
axios
.post(
`${API_URL}/api/tasks`,
requestBody,
{ headers: { Authorization: `Bearer ${storedToken}` } }
)
.post(`${API_URL}/api/tasks`, requestBody, {
headers: { Authorization: `Bearer ${storedToken}` },
})
.then((response) => {
// Reset the state to clear the inputs
setTitle("");
setDescription("");

// Invoke the callback function coming through the props
// from the ProjectDetailsPage, to refresh the project details
props.refreshProject();
})
.catch((error) => console.log(error));
};


return (
<div className="AddTask">
<h3>Add New Task</h3>

<form onSubmit={handleSubmit}>
<label>Title:</label>
<input
Expand All @@ -67,4 +62,4 @@ function AddTask(props) {
);
}

export default AddTask;
export default AddTask;
73 changes: 39 additions & 34 deletions src/context/auth.context.jsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,62 @@
import React, { useState, useEffect } from "react";
import axios from "axios";

const API_URL = "http://localhost:5005";
const API_URL = import.meta.env.VITE_LIVE_SERVER;

const AuthContext = React.createContext();

function AuthProviderWrapper(props) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [user, setUser] = useState(null);

const storeToken = (token) => {
localStorage.setItem("authToken", token);
}
const authenticateUser = () => {
};

const authenticateUser = () => {
// Get the stored token from the localStorage
const storedToken = localStorage.getItem("authToken");

// If the token exists in the localStorage
if (storedToken) {
// We must send the JWT token in the request's "Authorization" Headers
axios.get(
`${API_URL}/auth/verify`,
{ headers: { Authorization: `Bearer ${storedToken}`} }
)
.then((response) => {
// If the server verifies that JWT token is valid ✅
const user = response.data;
// Update state variables
setIsLoggedIn(true);
setIsLoading(false);
setUser(user);
})
.catch((error) => {
// If the server sends an error response (invalid token) ❌
// Update state variables
setIsLoggedIn(false);
setIsLoading(false);
setUser(null);
});

axios
.get(`${API_URL}/auth/verify`, {
headers: { Authorization: `Bearer ${storedToken}` },
})
.then((response) => {
// If the server verifies that JWT token is valid ✅
const user = response.data;
// Update state variables
setIsLoggedIn(true);
setIsLoading(false);
setUser(user);
})
.catch((error) => {
// If the server sends an error response (invalid token) ❌
// Update state variables
setIsLoggedIn(false);
setIsLoading(false);
setUser(null);
});
} else {
// If the token is not available
setIsLoggedIn(false);
setIsLoading(false);
setUser(null);
}
}
};

const removeToken = () => {
// Upon logout, remove the token from the localStorage
localStorage.removeItem("authToken");
}
};

const logOutUser = () => {
removeToken();
authenticateUser();
}

};

useEffect(() => {
// Run the function after the initial render,
Expand All @@ -68,11 +66,18 @@ function AuthProviderWrapper(props) {

return (
<AuthContext.Provider
value={{ isLoggedIn, isLoading, user, storeToken, authenticateUser, logOutUser }}
value={{
isLoggedIn,
isLoading,
user,
storeToken,
authenticateUser,
logOutUser,
}}
>
{props.children}
</AuthContext.Provider>
)
);
}

export { AuthProviderWrapper, AuthContext };
export { AuthProviderWrapper, AuthContext };
Loading