diff --git a/public/assets/css/style.css b/public/assets/css/style.css index 7a190a5..930823b 100644 --- a/public/assets/css/style.css +++ b/public/assets/css/style.css @@ -40,6 +40,7 @@ a { color: white; padding-left: 5px; padding-right: 5px; + margin-top: 4px; text-decoration: none; text-align: center; align-items: center; @@ -200,8 +201,17 @@ tr:nth-child(odd) { h2 { color: #ffffff; - font: 16px "Verdana"; - font-size: 32px; + font: 32px "Verdana"; + margin: 0; + margin-top: 32px; + margin-bottom: 10px; +} + +h3 { + color: #CCCCCC; + font: 24px "Verdana"; + margin: 0; + margin-bottom: 30px; } p { diff --git a/public/client.js b/public/client.js index 12c6a1b..0b6605b 100644 --- a/public/client.js +++ b/public/client.js @@ -1,8 +1,6 @@ export async function postData(url, data, token = null) { - const elements = url.split("/"); - const end = elements[elements.length - 1]; - - const res = await fetch(end, token == null ? { + console.log("fetching here: " + url); + const res = await fetch(url, token == null ? { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) @@ -19,7 +17,7 @@ export async function postData(url, data, token = null) { if (resultObject.logout === true) { alert("Session expired; please log in again."); - window.location.href = "login.html"; + window.location.href = "/login"; return resultObject; } @@ -32,13 +30,13 @@ export async function verifyLogin() { token = JSON.stringify(localStorage.getItem("token")); } catch (error) { alert("You are not logged in."); - window.location.href = "login.html"; + window.location.href = "login"; console.log("Error encountered: " + error); return false; } if (!token) { alert("You are not logged in."); - window.location.href = "login.html"; + window.location.href = "/login"; console.log("Token was null"); return false; } diff --git a/public/delete.js b/public/delete.js index 53b2850..5ec9f89 100644 --- a/public/delete.js +++ b/public/delete.js @@ -5,5 +5,5 @@ document.getElementById("deleteButton").onclick = async e => { const resultObject = await postData("/delete", { username: true, actor: true }, window.localStorage.getItem("token")); window.localStorage.removeItem("token"); alert(resultObject.message); - window.location.href = "/login.html" + window.location.href = "/login"; }; diff --git a/public/home.html b/public/home.html index e9be5df..541df76 100644 --- a/public/home.html +++ b/public/home.html @@ -7,14 +7,16 @@

Home

- Search Players +

Welcome, %

+ Search Players
- Personal Information + Personal Information

+
diff --git a/public/index.html b/public/index.html index 4694b43..7a166ac 100644 --- a/public/index.html +++ b/public/index.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/public/info.html b/public/info.html index 57188cb..e9bdf47 100644 --- a/public/info.html +++ b/public/info.html @@ -27,7 +27,7 @@ - Return Home + Return Home diff --git a/public/info.js b/public/info.js index b12c21c..82621a0 100644 --- a/public/info.js +++ b/public/info.js @@ -6,7 +6,7 @@ const token = window.localStorage.getItem("token"); const infoForm = document.getElementById("infoForm"); async function fetchPersonalInformation() { - const userData = await postData("https://project.rochesterx.dev/getInfo", {}, token); + const userData = await postData("/getInfo", {}, token); console.log(userData); @@ -29,8 +29,9 @@ async function updatePersonalInformation(e) { dob: document.getElementById("dobField").value } console.log(userData.dob); - const resultObject = await postData("https://project.rochesterx.dev/setInfo", userData, token); + const resultObject = await postData("/setInfo", userData, token); alert(resultObject.message); + window.localStorage.setItem("token", resultObject.token); } infoForm.onsubmit = updatePersonalInformation; diff --git a/public/login.html b/public/login.html index bde8c65..df05ae9 100644 --- a/public/login.html +++ b/public/login.html @@ -14,7 +14,7 @@

Don't have an account?

- Register + Register
diff --git a/public/login.js b/public/login.js index c5650b7..3c2be49 100644 --- a/public/login.js +++ b/public/login.js @@ -10,7 +10,7 @@ if (loginForm) loginForm.onsubmit = async e => { }); alert(resultObject.message); if (resultObject.success) { - window.location.href = "home.html" + window.location.href = "/home" localStorage.setItem("token", resultObject.token); } }; diff --git a/public/logout.js b/public/logout.js index 365a10b..1f9c046 100644 --- a/public/logout.js +++ b/public/logout.js @@ -2,5 +2,5 @@ document.getElementById("logoutButton").onclick = async e => { console.log("here"); e.preventDefault(); localStorage.removeItem("token"); - window.location.href = "login.html" + window.location.href = "/login" }; diff --git a/public/player.html b/public/player.html new file mode 100644 index 0000000..91ab253 --- /dev/null +++ b/public/player.html @@ -0,0 +1,42 @@ + + + + [Player name] + + + + +
+

[Player Name]

+ + + + + + + + + + + + + + + + + + + + +
NameIDSalaryTeamPosition
[Name][ID][Salary][Team][Position]
+ + + +
+ + Return to Player Search +
+ + + + diff --git a/public/player.js b/public/player.js new file mode 100644 index 0000000..ad41ad0 --- /dev/null +++ b/public/player.js @@ -0,0 +1,37 @@ +import { postData, verifyLogin } from "./client.js"; +import { formatSalary } from "./utils.js"; + +const searchForm = document.getElementById("searchForm"); + +const token = window.localStorage.getItem("token"); + +const tableHeader = document.getElementById("header"); +const tableBody = document.getElementById("results"); +const table = document.getElementById("table"); +const nomatch = document.getElementById("nomatch"); + +populatePlayerData(); + +async function populatePlayerData() { + const [, , id] = window.location.pathname.split("/"); + const result = await postData("/getPlayer", { id: id }, window.localStorage.getItem("token")); + if (result.success === false) { + console.log("Invalid ID"); + window.location.href = "/search"; + return; + } + + const player = result.match; + for (const [attribute, value] of Object.entries(player)) { + console.log(`.attribute-${attribute}`); + document.querySelectorAll(`.attribute-${attribute}`).forEach(element => { + if (element.classList.contains("format-salary")) { + element.textContent = formatSalary(value); + return; + } + element.textContent = value; + }) + }; + + console.log(player); +} diff --git a/public/register.html b/public/register.html index bb97e00..ea6f265 100644 --- a/public/register.html +++ b/public/register.html @@ -18,7 +18,7 @@

Already have an account?

- Login + Login
diff --git a/public/register.js b/public/register.js index 6193db0..7bba4f1 100644 --- a/public/register.js +++ b/public/register.js @@ -4,13 +4,13 @@ const registerForm = document.getElementById("registerForm"); if (registerForm) registerForm.onsubmit = async e => { e.preventDefault(); - let resultObject = await postData("http://project.rochesterx.dev/register", { + let resultObject = await postData("/register", { username: registerForm.regUser.value, password: registerForm.regPass.value, role: registerForm.regRole.value }); alert(resultObject.message); if (resultObject.success === true) { - window.location.href = "login.html"; + window.location.href = "/login"; } }; diff --git a/public/search.html b/public/search.html index 1e6fd43..2fb76fc 100644 --- a/public/search.html +++ b/public/search.html @@ -33,7 +33,7 @@
- Return Home + Return Home diff --git a/public/search.js b/public/search.js index d767bbc..73a575d 100644 --- a/public/search.js +++ b/public/search.js @@ -1,4 +1,5 @@ import { postData, verifyLogin } from "./client.js"; +import { formatSalary } from "./utils.js"; const searchForm = document.getElementById("searchForm"); @@ -15,7 +16,7 @@ if (searchForm)searchForm.onsubmit = async e => { e.preventDefault(); if (!verifyLogin()) return; - let resultObject = await postData("https://project.rochesterx.dev/getPlayers", { + let resultObject = await postData("/getPlayers", { player: document.getElementById("query").value }, token); @@ -42,7 +43,7 @@ if (searchForm)searchForm.onsubmit = async e => { //} row.innerHTML = ` ${player.player_id} - ${player.player_name} + ${player.player_name} ${formatSalary(player.salary)} ${player.team_name} ${player.position} @@ -56,7 +57,6 @@ function updateTableVisibility() { if (!tableBody) return; const rows = tableBody.querySelectorAll("tr"); - console.log(rows); if (rows == null) return; if (rows.length != 0) { table.style.display = ""; @@ -64,45 +64,3 @@ function updateTableVisibility() { table.style.display = "none"; } } - -function formatText(text) { - if (text == null) return "—"; - - if (typeof(text) === "string") { - return text; - } - else { - return "Unknown format"; - } -} -function formatSalary(text) { - if (text == null) return "—"; - - try { - var millions = (parseInt(text, 10) / 1000000).toFixed(2); - return `$${millions} million`; - } catch (e) { - return "Unknown format" - } - -} -function formatDate(date) { - if (date == null) return "—"; - - if (typeof(date) === "string") { - return date.split("T")[0]; - } - else { - return "Unknown format"; - } -} -function formatDateTime(date) { - if (date == null) return "—"; - - if (typeof(date) === "string") { - return date.split("T")[0] + " at " + date.split("T")[1].split(".")[0]; - } - else { - return "Unknown format"; - } -} diff --git a/public/sections.html b/public/sections.html index 3b75f43..8264e7b 100644 --- a/public/sections.html +++ b/public/sections.html @@ -77,7 +77,7 @@
- Return Home + Return Home diff --git a/public/sections.js b/public/sections.js index eb974cf..200914c 100644 --- a/public/sections.js +++ b/public/sections.js @@ -1,6 +1,6 @@ import { postData, verifyLogin } from "./client.js"; -if (!verifyLogin("professor")) window.location.href = "home.html" +if (!verifyLogin("professor")) window.location.href = "/home" const sectionsHead = document.querySelector("#sections"); diff --git a/public/utils.js b/public/utils.js new file mode 100644 index 0000000..5d9d394 --- /dev/null +++ b/public/utils.js @@ -0,0 +1,41 @@ +export function formatText(text) { + if (text == null) return "—"; + + if (typeof(text) === "string") { + return text; + } + else { + return "Unknown format"; + } +} +export function formatSalary(text) { + if (text == null) return "—"; + + try { + var millions = (parseInt(text, 10) / 1000000).toFixed(2); + return `$${millions} million`; + } catch (e) { + return "Unknown format" + } + +} +export function formatDate(date) { + if (date == null) return "—"; + + if (typeof(date) === "string") { + return date.split("T")[0]; + } + else { + return "Unknown format"; + } +} +export function formatDateTime(date) { + if (date == null) return "—"; + + if (typeof(date) === "string") { + return date.split("T")[0] + " at " + date.split("T")[1].split(".")[0]; + } + else { + return "Unknown format"; + } +} diff --git a/public/variables.js b/public/variables.js new file mode 100644 index 0000000..259499f --- /dev/null +++ b/public/variables.js @@ -0,0 +1,17 @@ +import { postData } from "./client.js"; + +populateuserData(); +async function populateuserData() { + const user = await postData("/getInfo", {}, window.localStorage.getItem("token")); + + for (const [attribute, value] of Object.entries(user)) { + document.querySelectorAll(`.user-${attribute}`).forEach(element => { + if (attribute === "FirstName" && value === "") { + var text = element.textContent; + element.textContent = text.replace("%", user.Username); + } + var text = element.textContent; + element.textContent = text.replace("%", value); + }); + } +} diff --git a/server.js b/server.js index 41b0ef2..2dbb861 100644 --- a/server.js +++ b/server.js @@ -11,6 +11,13 @@ const dev = process.argv.length > 2 && process.argv[2] == "-dev"; const app = express(); app.use(express.json()); +app.use((req, res, next) =>{ + if (req.path.endsWith(".html")) { + res.redirect(req.path.replace(".html", "")); + return; + } + next(); +}) app.use(express.static("public")) app.use(cors({ origin: [ @@ -103,11 +110,25 @@ app.post("/getPlayers", authenticate, async (req, res) => { const result = await pool.request() .input("query", sql.VarChar, player) - .query(`SELECT * FROM [Player, IMPORTANT] WHERE player_name LIKE '%' + @query + '%'`); + .query(`SELECT * FROM Player WHERE player_name LIKE '%' + @query + '%'`); res.status(200).json({ query: player, matches: result.recordset }); }); +app.post("/getPlayer", authenticate, async (req, res) => { + const { id } = req.body; + + const result = await pool.request() + .input("query", sql.VarChar, id) + .query(`SELECT * FROM Player WHERE player_id = @query`); + + if (result.recordset.length !== 1) { + res.status(400).json({ success: false }) + return; + } + res.status(200).json({ success: true, match: result.recordset[0] }); +}); + app.post("/getInfo", authenticate, async (req, res) => { const userData = req.user; @@ -123,54 +144,6 @@ app.post("/getCourses", authenticate, async (req, res) => { res.status(200).json(courses); }); -app.post("/createSection", authenticate, async (req, res) => { - let { subject, number, days, startDate, endDate, startTime, endTime, term } = req.body; - startTime = new Date("1970-01-01T" + startTime); - endTime = new Date("1970-01-01T" + endTime); - console.log(req.user); - try { - await pool.request() - .input("subject", sql.VarChar(3), subject) - .input("number", sql.Int, number) - .input("professor", sql.Int, req.user.Id) - .input("term", sql.VarChar(10), term) - .input("startDate", sql.Date, startDate) - .input("endDate", sql.Date, endDate) - .input("startTime", sql.Time(0), startTime) - .input("endTime", sql.Time(0), endTime) - .input("days", sql.Int, days) - .query(` - INSERT INTO Sections ( - Subject, - Number, - ProfessorID, - Term, - Days, - StartDate, - EndDate, - StartTime, - EndTime - ) VALUES ( - @subject, - @number, - @professor, - @term, - @days, - @startDate, - @endDate, - @startTime, - @endTime - ) - `); - } catch (err) { - if (err.message.includes("Violation of UNIQUE KEY constraint")) { - res.status(500).send({ success: false, message: `Username "${username}" is already taken.` }); - } - res.status(500).send({ success: false, message: err.message }); - } - res.status(200).send({ success: true, message: "Section created successfully."}); -}) - app.post("/setInfo", authenticate, async (req, res) => { const { firstName, lastName, dob } = req.body; @@ -192,7 +165,18 @@ app.post("/setInfo", authenticate, async (req, res) => { res.status(500).json({ message: "Update request failed" }) } - res.status(200).json({ message: "Information updated successfully" }); + var updatedUser = req.user; + updatedUser.FirstName = firstName; + updatedUser.LastName = lastName; + updatedUser.DOB = dob; + + const token = jwt.sign(updatedUser, JWT_SECRET); + console.log("Issued token: " + JSON.stringify(token)) + res.status(200).send({ + success: true, + message: "Information updated successfully", + token + }); }); app.post("/delete", authenticate, async (req, res) => { @@ -219,6 +203,7 @@ app.post("/delete", authenticate, async (req, res) => { async function authenticate(req, res, next) { try { const authenticationHeader = req.headers["authorization"]; + console.log("authenticationheader: " + authenticationHeader); const token = authenticationHeader.split(" ")[1]; console.log(JSON.stringify(authenticationHeader)); @@ -231,10 +216,34 @@ async function authenticate(req, res, next) { console.log(decoded.Username + " authenticated"); } catch (error) { console.log("Authentication header missing"); + console.log(error); res.status(401).json({ message: "You are not logged in", error: error, logout: true }); return; } next(); } +app.get("/player/:id", (req, res) => { + res.sendFile(__dirname + "/public/player.html"); +}) + +app.get("/search", (req, res) => { + res.sendFile(__dirname + "/public/search.html"); +}) + +app.get("/home", (req, res) => { + res.sendFile(__dirname + "/public/home.html"); +}) + +app.get("/info", (req, res) => { + res.sendFile(__dirname + "/public/info.html"); +}) + +app.get("/register", (req, res) => { + res.sendFile(__dirname + "/public/register.html"); +}) + +app.get("/login", (req, res) => { + res.sendFile(__dirname + "/public/login.html"); +}) app.listen(serverPort, "0.0.0.0", () => console.log(`Running ${dev ? "dev " : ""}server on port ${serverPort}`));