diff --git a/sports-matcher/client/.eslintrc.json b/sports-matcher/client/.eslintrc.json
index 3cdde28..456e459 100644
--- a/sports-matcher/client/.eslintrc.json
+++ b/sports-matcher/client/.eslintrc.json
@@ -35,6 +35,7 @@
"semi": [
"error",
"always"
- ]
+ ],
+ "no-unused-vars": "warn"
}
}
\ No newline at end of file
diff --git a/sports-matcher/client/src/Layout.js b/sports-matcher/client/src/Layout.js
index 7f2a32e..ccc66d2 100644
--- a/sports-matcher/client/src/Layout.js
+++ b/sports-matcher/client/src/Layout.js
@@ -1,7 +1,7 @@
import "./styles/Layout.css";
import "./styles/extra.css";
-import React from "react";
-import { NavLink, Route, Routes } from "react-router-dom";
+import { useEffect, useState } from "react";
+import { NavLink, Route, Routes, useNavigate } from "react-router-dom";
import Welcome from "./pages/Welcome";
import Navbar from "react-bootstrap/Navbar";
import { Container, Nav, NavbarBrand } from "react-bootstrap";
@@ -10,11 +10,56 @@ import NavbarCollapse from "react-bootstrap/esm/NavbarCollapse";
import Dashboard from "./pages/Dashboard";
import Admin from "./pages/NewAdmin";
import Login from "./pages/Login";
+import { apiClient } from "./utils/httpClients";
+import { globalContext } from "./context.js";
-export default class Layout extends React.Component {
- render() {
- return (
-
+
+export default function layout() {
+ const navigate = useNavigate();
+ const [state, setState] = useState({
+ user: null,
+ });
+
+ useEffect(async () => {
+ await updateAuthStatus();
+ });
+
+ async function updateAuthStatus() {
+ const getUserResponse = await apiClient.get("/user");
+ if (getUserResponse !== 200) {
+ setState({ user: null });
+ } else {
+ setState({ user: getUserResponse.data });
+ }
+ }
+
+ let indentityDisplay = (
+
+ );
+
+ if (state.user) {
+ indentityDisplay = (
+
+ );
+ }
+
+ return (
+
+
@@ -26,6 +71,7 @@ export default class Layout extends React.Component {
Home
+ {indentityDisplay}
@@ -41,7 +87,7 @@ export default class Layout extends React.Component {
-
- );
- }
+
+
+ );
}
\ No newline at end of file
diff --git a/sports-matcher/client/src/components/MatchInfoCard.js b/sports-matcher/client/src/components/MatchInfoCard.js
index f99832f..f7deb91 100644
--- a/sports-matcher/client/src/components/MatchInfoCard.js
+++ b/sports-matcher/client/src/components/MatchInfoCard.js
@@ -9,7 +9,6 @@ export default class MatchInfoCard extends React.Component {
getParticipants() {
let participants = [];
- console.log(this.props);
this.props.match.participants.forEach(user => {
participants.push(user.firstName);
});
diff --git a/sports-matcher/client/src/components/MatchInfoCardDisplay.js b/sports-matcher/client/src/components/MatchInfoCardDisplay.js
index 3dd3f7b..cb19099 100644
--- a/sports-matcher/client/src/components/MatchInfoCardDisplay.js
+++ b/sports-matcher/client/src/components/MatchInfoCardDisplay.js
@@ -1,7 +1,7 @@
import React from "react";
import propTypes from "prop-types";
import MatchInfoCard from "./MatchInfoCard";
-
+import "../styles/MatchInfoCardDisplay.css";
export default class MatchInfoCardDisplay extends React.Component {
constructor(props) {
super(props);
diff --git a/sports-matcher/client/src/components/SportInfoCard.js b/sports-matcher/client/src/components/SportInfoCard.js
new file mode 100644
index 0000000..14477e9
--- /dev/null
+++ b/sports-matcher/client/src/components/SportInfoCard.js
@@ -0,0 +1,26 @@
+import React from "react";
+import { Card } from "react-bootstrap";
+import propTypes from "prop-types";
+export default class SportInfoCard extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+
-
-
- Login
- Welcome back!
-
- E-mail
-
-
-
- Password
-
-
-
-
-
-
+
+ {errorMsg}
+
+
+
+ Login
+ Welcome back!
+
+ E-mail
+ {
+ this.setState({ email: e.target.value });
+ }} />
+
+
+ Password
+ {
+ this.setState({ password: e.target.value });
+ }} />
+
+
+
+
+
+
);
}
diff --git a/sports-matcher/client/src/pages/Logout.js b/sports-matcher/client/src/pages/Logout.js
new file mode 100644
index 0000000..517d95c
--- /dev/null
+++ b/sports-matcher/client/src/pages/Logout.js
@@ -0,0 +1,36 @@
+import React from "react";
+import { useNavigate } from "react-router-dom";
+import { apiClient } from "../utils/httpClients";
+
+export default class Logout extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ async componentDidMount() {
+ const logoutResponse = await apiClient.get("/user/logout");
+ let navigation = useNavigate();
+ if (logoutResponse.status === 401) {
+ navigation("/dashboard", { replace: true });
+ } else {
+ this.redirectTimer = setTimeout(() => {
+ navigation("/", { replace: true });
+ }, 2000);
+ }
+ }
+
+ async componentWillUnmount() {
+ clearTimeout(this.redirectTimer);
+ }
+
+ render() {
+ return (
+
+
+
You are now logged out. See you later!
+
We will redirect you shortly...
+
+
+ );
+ }
+}
\ No newline at end of file
diff --git a/sports-matcher/client/src/pages/SIgnup.js b/sports-matcher/client/src/pages/SIgnup.js
new file mode 100644
index 0000000..c603579
--- /dev/null
+++ b/sports-matcher/client/src/pages/SIgnup.js
@@ -0,0 +1,88 @@
+import React from "react";
+import { Button, Card, Form } from "react-bootstrap";
+import { apiClient } from "../utils/httpClients";
+import { guard } from "../utils/routing";
+
+export default class Signup extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ user: null,
+ alertShow: false,
+ alertKey: null,
+ alertMsg: null
+ }
+ this.state.user = {
+ email: null,
+ firstName: null,
+ lastName: null,
+ phone: null,
+ password: null
+ }
+ }
+
+ async registerUser() {
+ const res = await apiClient.post("/user", this.state);
+ if (res.status === 200) {
+ this.warnUser("You are successfully signed up!", "success")
+ } else if (res === 409) {
+ this.warnUser("This user already exists. Try logging in instead.", "danger")
+ } else if (res === 400) {
+ this.warnUser("Missing required fields.", "danger")
+ } else {
+ this.warnUser("Internal server error. Please try again later.", "danger")
+ }
+ }
+
+ setUserState(event) {
+ newUser = this.state.user;
+ newUser[event.target.controlId] = event.target.value
+ this.setState({user: newUser})
+ }
+
+ warnUser(msg, key) {
+ this.setState({alertMsg: msg})
+ this.setState({show: true})
+ }
+
+ render() {
+ return (
+
+
+ {this.state.alertMsg}
+
+
+
+ Login
+ Welcome to Sports Matcher!
+
+ First name
+
+
+
+ Last name
+
+
+
+ E-mail
+
+
+
+ Phone number
+
+
+
+ Password
+
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/sports-matcher/client/src/styles/MatchInfoCardDisplay.css b/sports-matcher/client/src/styles/MatchInfoCardDisplay.css
new file mode 100644
index 0000000..d6f7190
--- /dev/null
+++ b/sports-matcher/client/src/styles/MatchInfoCardDisplay.css
@@ -0,0 +1,4 @@
+.horizontal-scroller{
+ display: flex;
+ overflow-x: auto;
+}
\ No newline at end of file
diff --git a/sports-matcher/client/src/utils/httpClients.js b/sports-matcher/client/src/utils/httpClients.js
index e512953..36a9ea2 100644
--- a/sports-matcher/client/src/utils/httpClients.js
+++ b/sports-matcher/client/src/utils/httpClients.js
@@ -1,6 +1,10 @@
import axios from "axios";
export const apiClient = axios.create({
- baseURL: process.env.REACT_APP_API_HOST,
+ baseURL: (process.env.REACT_APP_API_HOST || "") + "/api/",
timeout: 5000,
+ withCredentials: process.env.NODE_ENV === "development",
+ validateStatus: function (status) {
+ return status === 401 || status == 200;
+ }
});
\ No newline at end of file
diff --git a/sports-matcher/client/src/utils/routing.js b/sports-matcher/client/src/utils/routing.js
index 94c328e..46caad9 100644
--- a/sports-matcher/client/src/utils/routing.js
+++ b/sports-matcher/client/src/utils/routing.js
@@ -1,7 +1,6 @@
-import { useNavigate } from "react-router-dom";
import { apiClient } from "./httpClients";
-export function guard(evaluator, redirect, navigateOptions, onRedirect) {
+export function guard(navigator, evaluator, redirect, navigateOptions, onRedirect) {
if (!evaluator) throw new Error("evaluator required.");
if (!redirect) throw new Error("redirect required.");
if (!navigateOptions) {
@@ -9,16 +8,15 @@ export function guard(evaluator, redirect, navigateOptions, onRedirect) {
replace: true
};
}
- let navigate = useNavigate();
let redirecting = !evaluator();
if (redirecting) {
if (onRedirect) onRedirect();
- navigate(redirect, navigateOptions);
+ navigator(redirect, navigateOptions);
}
}
-export async function needUser() {
+export async function needUser(navigator) {
let userDataResponse = await apiClient.get("/user");
- guard(() => userDataResponse.status === 200, "/login");
+ guard(navigator, () => userDataResponse.status === 200, "/login");
return userDataResponse.data;
}
\ No newline at end of file
diff --git a/sports-matcher/server/.eslintrc.json b/sports-matcher/server/.eslintrc.json
index 0806fb5..e296e45 100644
--- a/sports-matcher/server/.eslintrc.json
+++ b/sports-matcher/server/.eslintrc.json
@@ -14,7 +14,7 @@
4
],
"linebreak-style": [
- "error",
+ "warn",
"unix"
],
"quotes": [
@@ -24,6 +24,7 @@
"semi": [
"error",
"always"
- ]
+ ],
+ "no-unused-vars": "warn"
}
}
\ No newline at end of file
diff --git a/sports-matcher/server/server.js b/sports-matcher/server/server.js
index dcb9da6..6e74fd5 100644
--- a/sports-matcher/server/server.js
+++ b/sports-matcher/server/server.js
@@ -27,9 +27,9 @@ try {
if (process.env.NODE_ENV === "development") {
+ console.log("We are running in development mode.");
mongoose.set("bufferCommands", false); // We want to know if there are connection issues immediately for development. Disables globally.
-
- server.use(cors());
+ server.use(cors({ credentials: true, origin: "http://localhost:3000" }));
}
// Docs: https://www.npmjs.com/package/body-parser
@@ -38,10 +38,10 @@ server.use(bodyParser.urlencoded({ extended: true }));
server.use(userSession);
-server.use("/user", UserController);
-server.use("/match", MatchController);
-server.use("/sport", SportController);
-server.use("/rental", rentalController);
+server.use("/api/user", UserController);
+server.use("/api/match", MatchController);
+server.use("/api/sport", SportController);
+server.use("/api/rental", rentalController);
server.listen(port, () => {
console.log(`Server listening on port ${port}.`);