summaryrefslogtreecommitdiff
path: root/frontend/admin
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/admin')
-rw-r--r--frontend/admin/admin-style.css53
-rw-r--r--frontend/admin/admin.js110
-rw-r--r--frontend/admin/index.html17
-rw-r--r--frontend/admin/panel.html95
4 files changed, 275 insertions, 0 deletions
diff --git a/frontend/admin/admin-style.css b/frontend/admin/admin-style.css
new file mode 100644
index 0000000..9c866ff
--- /dev/null
+++ b/frontend/admin/admin-style.css
@@ -0,0 +1,53 @@
+#unauthorised {
+
+}
+
+#authorised {
+
+}
+
+.admin-machine-container {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ background-color: lightgrey;
+ gap: 16px;
+ padding: 16px;
+ width: fit-content;
+ max-width: 100%;
+ box-sizing: border-box;
+}
+
+.admin-machine-container > div {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.admin-machine-container > div > img {
+ width: 128px;
+}
+
+.admin-machine-container > div > span {
+ text-align: center;
+ font-weight: 600;
+}
+
+.admin-machine-container > h2 {
+ writing-mode: vertical-lr;
+ transform: rotate(180deg);
+ margin: 0;
+ height: fit-content;
+}
+
+#passwordFeedback {
+ display: none;
+ color: red;
+}
+
+.blocks-container {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ gap: 16px;
+}
diff --git a/frontend/admin/admin.js b/frontend/admin/admin.js
new file mode 100644
index 0000000..ff1c463
--- /dev/null
+++ b/frontend/admin/admin.js
@@ -0,0 +1,110 @@
+const API_URL = "https://backend.laundryweb.altafcreator.com"
+
+async function login() {
+ const field = document.getElementById("pwfield");
+
+ const response = await fetch(`${API_URL}/admin_login`, {
+ method: "POST",
+ credentials: "include",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: `{"password": "${field.value}"}`,
+ });
+
+ if (response.status == 202) window.location.href = "./panel.html";
+ else document.getElementById("passwordFeedback").style.display = "inherit";
+}
+
+async function checkLoginStatus() {
+ const response = await fetch(`${API_URL}/admin_check`, {
+ method: "POST",
+ credentials: "include"
+ });
+
+ return response.status == 202;
+}
+
+async function autoLogin() {
+ if (await checkLoginStatus()) {
+ window.location.href = "./panel.html";
+ }
+}
+
+async function panelLoginCheck() {
+ const msg = document.getElementById("unauthorised");
+ const authDiv = document.getElementById("authorised");
+
+ if (await checkLoginStatus()) {
+ msg.style.display = "none";
+ authDiv.style.display = "inherit";
+ return true;
+ } else {
+ msg.style.display = "inherit";
+ authDiv.style.display = "none";
+ return false;
+ }
+}
+
+async function syncMachineStatus() {
+ const response = await fetch(`${API_URL}/admin_machine_status`, {
+ method: "POST",
+ credentials: "include",
+ });
+ const data = await response.json();
+
+ for (let b = 0; b < data.length; b++) {
+ for (let m = 0; m < data[b].length; m++) {
+ const img = document.getElementById("h"+(b+1).toString()+"m"+(m+1).toString()+"img");
+ const dropdown = document.getElementById("h"+(b+1).toString()+"m"+(m+1).toString());
+
+ if (data[b][m] != "OUTOFSERVICE") {
+ if (m % 2 == 0) {
+ img.src = "/assets/img/dryer_off.png";
+ } else {
+ img.src = "/assets/img/washer_off.png";
+ }
+ dropdown.selectedIndex = 0;
+ } else {
+ if (m % 2 == 0) {
+ img.src = "/assets/img/dryer_down.png";
+ } else {
+ img.src = "/assets/img/washer_down.png";
+ }
+ dropdown.selectedIndex = 1;
+ }
+ }
+ }
+}
+
+async function overrideMachineStatus(block, machine) {
+ const img = document.getElementById("h"+block.toString()+"m"+machine.toString()+"img");
+ const dropdown = document.getElementById("h"+block.toString()+"m"+machine.toString());
+
+ const response = await fetch(`${API_URL}/override_status`, {
+ method: "POST",
+ credentials: "include",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: `{"block": ${block}, "machine_id": ${machine}, "disabled": ${dropdown.selectedIndex == 1}}`,
+ });
+
+ if (response.status != 200) {
+ return;
+ }
+
+ if (dropdown.selectedIndex == 1) {
+ if (machine % 2 == 0) {
+ img.src = "/assets/img/washer_down.png";
+ } else {
+ img.src = "/assets/img/dryer_down.png";
+ }
+ } else {
+ if (machine % 2 == 0) {
+ img.src = "/assets/img/washer_off.png";
+ } else {
+ img.src = "/assets/img/dryer_off.png";
+ }
+ }
+}
diff --git a/frontend/admin/index.html b/frontend/admin/index.html
new file mode 100644
index 0000000..76df357
--- /dev/null
+++ b/frontend/admin/index.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Victoria Hall LaundryWeb Admin Panel</title>
+ <link rel="stylesheet" href="./admin-style.css">
+</head>
+<body>
+ <h1>LaundryWeb Admin Panel Log In</h1>
+ <input type="password" id="pwfield"> <button onclick="login()">Log In</button>
+ <p id="passwordFeedback">Invalid password.</p>
+ <script src="./admin.js"></script>
+ <script>
+ autoLogin();
+ </script>
+</body>
+</html>
diff --git a/frontend/admin/panel.html b/frontend/admin/panel.html
new file mode 100644
index 0000000..4813c06
--- /dev/null
+++ b/frontend/admin/panel.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Victoria Hall LaundryWeb Admin Panel</title>
+ <link rel="stylesheet" href="./admin-style.css">
+</head>
+<body>
+ <h1>LaundryWeb Admin Panel</h1>
+ <p id="unauthorised">You are unauthorised.</p>
+ <!-- even if you make this div visible, you won't be able to do anything if you are unauthorised -->
+ <div id="authorised">
+ <div class="blocks-container">
+ <div class="admin-machine-container" style="background-color: lightyellow;">
+ <h2>Block H2</h2>
+ <div>
+ <span>Dryer 1</span>
+ <img id="h2m1img" src="/assets/img/dryer_off.png" alt="">
+ <select id="h2m1" name="" onchange="overrideMachineStatus(2, 1);">
+ <option value="normal">Normal</option>
+ <option value="down">Out of Service</option>
+ </select>
+ </div>
+ <div>
+ <span>Washer 1</span>
+ <img id="h2m2img" src="/assets/img/washer_off.png" alt="">
+ <select id="h2m2" name="" onchange="overrideMachineStatus(2, 2);">
+ <option value="normal">Normal</option>
+ <option value="down">Out of Service</option>
+ </select>
+ </div>
+ <div>
+ <span>Dryer 2</span>
+ <img id="h2m3img" src="/assets/img/dryer_off.png" alt="">
+ <select id="h2m3" name="" onchange="overrideMachineStatus(2, 3);">
+ <option value="normal">Normal</option>
+ <option value="down">Out of Service</option>
+ </select>
+ </div>
+ <div>
+ <span>Washer 2</span>
+ <img id="h2m4img" src="/assets/img/washer_off.png" alt="">
+ <select id="h2m4" name="" onchange="overrideMachineStatus(2, 4);">
+ <option value="normal">Normal</option>
+ <option value="down">Out of Service</option>
+ </select>
+ </div>
+ </div>
+ <div class="admin-machine-container" style="background-color: skyblue;">
+ <h2>Block H1</h2>
+ <div>
+ <span>Dryer 1</span>
+ <img id="h1m1img" src="/assets/img/dryer_off.png" alt="">
+ <select id="h1m1" name="" onchange="overrideMachineStatus(1, 1);">
+ <option value="normal">Normal</option>
+ <option value="down">Out of Service</option>
+ </select>
+ </div>
+ <div>
+ <span>Washer 1</span>
+ <img id="h1m2img" src="/assets/img/washer_off.png" alt="">
+ <select id="h1m2" name="" onchange="overrideMachineStatus(1, 2);">
+ <option value="normal">Normal</option>
+ <option value="down">Out of Service</option>
+ </select>
+ </div>
+ <div>
+ <span>Dryer 2</span>
+ <img id="h1m3img" src="/assets/img/dryer_off.png" alt="">
+ <select id="h1m3" name="" onchange="overrideMachineStatus(1, 3);">
+ <option value="normal">Normal</option>
+ <option value="down">Out of Service</option>
+ </select>
+ </div>
+ <div>
+ <span>Washer 2</span>
+ <img id="h1m4img" src="/assets/img/washer_off.png" alt="">
+ <select id="h1m4" name="" onchange="overrideMachineStatus(1, 4);">
+ <option value="normal">Normal</option>
+ <option value="down">Out of Service</option>
+ </select>
+ </div>
+ </div>
+ </div>
+ </div>
+ <script src="admin.js"></script>
+ <script>
+ (async () => {
+ if (await panelLoginCheck()) {
+ syncMachineStatus();
+ }
+ })();
+ </script>
+</body>
+</html>