diff options
Diffstat (limited to 'frontend/main.js')
| -rw-r--r-- | frontend/main.js | 393 |
1 files changed, 373 insertions, 20 deletions
diff --git a/frontend/main.js b/frontend/main.js index 46341d6..cfacc86 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -1,23 +1,376 @@ -const btn = document.getElementById("notbtn") -btn.addEventListener("click", () => requestPermission()) -function requestPermission() { - console.log("Requesting permission..."); - OneSignal.Notifications.requestPermission(); +// --- begin, important constants +const data = { + duration: 1, // will be multiplied by 30 + machine_id: "", } -document.cookie = "session_key=0" +const API_URL = "https://backend.laundryweb.altafcreator.com" -const data = { - duration: 2, - block: 1, - machine: 2, -} - -fetch("http://localhost:8000/start", { - credentials: "include", - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(data) -}); +const PUBLIC_VAPID_KEY = "BCvVfKfWBtHKtzdakJfhYy604yTn0_FgZxy2sNtxcQm6YyC3qdzBBuCJLbVcG6pmbz_CZLa0I44Z-b5UVBbegGw" + +// --- REGISTER SERVICE WORKERS +if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/sw.js', { + scope: '/', + }); +} + +// --- subscribe +async function subscribe() { + if (!('serviceWorker' in navigator)) { + alert("err: no service worker"); + return; + } + + console.log(await Notification.requestPermission()); + + const registration = await navigator.serviceWorker.ready; + + try { + const subscription = await registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: urlBase64ToUint8Array(PUBLIC_VAPID_KEY), + }); + + console.log(subscription); + + console.log("sw regis pass, write to db"); + + const db_reply = await fetch(`${API_URL}/notifsubscribe`, { + method: 'POST', + credentials: "include", + body: JSON.stringify(subscription), + headers: { + "Content-Type": "application/json", + }, + }); + + console.log(db_reply) + + return db_reply.ok; + } catch (e) { + console.log("ERR in regis, ", e); + return false; + } + +} + +/// copied from somewhere +const urlBase64ToUint8Array = (base64String) => { + const padding = '='.repeat((4 - base64String.length % 4) % 4); + const base64 = (base64String + padding) + .replace(/\-/g, '+') + .replace(/_/g, '/'); + + const rawData = window.atob(base64); + const outputArray = new Uint8Array(rawData.length); + + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; +}; + +// --- check machine status +// returns a 2d array representing machines +// []: root array +// []: block +// enum: machine status +async function checkMachineStatus() { + const response = await fetch(`${API_URL}/status`, { + method: "POST", + credentials: "include", + }); + return await response.json(); +} + +// --- timer duration +const minField = document.getElementById("min-field"); +const decBtn = document.getElementById("decTime"); +function increaseTime() { + data.duration += 1; + minField.innerText = (30 * data.duration).toString() + " minutes"; + decBtn.disabled = false; +} + +function decreaseTime() { + data.duration -= 1; + data.duration = Math.max(data.duration, 1); + if (data.duration == 1) { + decBtn.disabled = true; + } + minField.innerText = (30 * data.duration).toString() + " minutes"; +} + +// --- starting a timer +async function start() { + fetch(`${API_URL}/start`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(data) + }).then(response => response.text()) + .then(data => { + console.log(data); + if (data == "all good bro timer started") { + window.location.href = "/timer/"; + } + cookieStore.delete("last_used_url"); + }); +} + +// --- information loading + cookie setting (from server) +async function information(urlParam = null) { + const urlCookie = await cookieStore.get("last_used_url"); + + const response = await fetch(`${API_URL}/info`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ "machine_id": urlParam ? urlParam : "" }), + }); + + const json = await response.json(); + + if (json["block"]) { + document.getElementById("logo-id").innerText = "H" + json["block"]; + } else { + document.getElementById("logo-id").innerText = "H?"; + } + + return Promise.resolve(json); +} + + +// ------ page specific ----- +// wait WHY THE FUCK ARE THESE HERE THEN? + +// ---- machine status page + +const STATUS_INTERVAL = 30 + +// --- machines visual +async function startUpdateMachines() { + const urlParams = new URLSearchParams(window.location.search); + + await information(urlParams.get("machine")); + console.log("info done") + + updateMachines(); + + while (true) { + await delay(STATUS_INTERVAL * 1000); + + await updateMachines(); + } +} + +async function updateMachines() { + // less disgusting. + const types = ["dryer", "washer"]; + const ns = [1, 2]; + + const machineImgs = []; + const machineTxts = []; + const machineDetailImgs = []; + const machineDetailTitles = []; + const machineDetailDescs = []; + + for (const n of ns) { + for (const t of types) { + machineImgs.push(document.getElementById(`${t}${n}-img`)); + machineTxts.push(document.getElementById(`${t}${n}-span`)); + machineDetailImgs.push(document.getElementById(`detail-${t[0]}${n}-img`)); + machineDetailTitles.push(document.getElementById(`detail-${t[0]}${n}-title`)); + machineDetailDescs.push(document.getElementById(`detail-${t[0]}${n}-desc`)); + } + } + + console.log(machineDetailImgs); + console.log(machineDetailTitles); + console.log(machineDetailDescs); + + const status = await checkMachineStatus(); + console.log(status); + + for (let i = 0; i < status[0].length; i++) { + if (status[0][i] == "RUNNING") { + if ((i + 1) % 2 == 0) { + machineImgs[i].src = "/assets/img/washer_on.png"; + if (machineDetailImgs[0]) machineDetailImgs[i].src = "/assets/img/washer_on.png"; + if (machineDetailImgs[0]) machineDetailDescs[i].innerHTML = "Timing might differ due to heavy load or excess suds." + } else { + machineImgs[i].src = "/assets/img/dryer_on.png"; + if (machineDetailImgs[0]) machineDetailImgs[i].src = "/assets/img/dryer_on.png"; + if (machineDetailImgs[0]) machineDetailTitles[i].innerHTML = "Idle" + } + const now = Date.now(); + const end = Date.parse(status[2][i]); + const minsLeft = Math.ceil((end - now) / 60000).toString(); + machineTxts[i].innerHTML = minsLeft + " min(s) left"; + if (machineDetailImgs[0]) machineDetailTitles[i].innerHTML = minsLeft + " minute(s) left" + } else if (status[0][i] == "OUTOFSERVICE") { + if ((i + 1) % 2 == 0) { + machineImgs[i].src = "/assets/img/washer_down.png"; + if (machineDetailImgs[0]) machineDetailImgs[i].src = "/assets/img/washer_down.png"; + } else { + machineImgs[i].src = "/assets/img/dryer_down.png"; + if (machineDetailImgs[0]) machineDetailImgs[i].src = "/assets/img/dryer_down.png"; + } + machineTxts[i].innerHTML = "Down" + if (machineDetailImgs[0]) machineDetailTitles[i].innerHTML = "Out of Service" + if (machineDetailImgs[0]) machineDetailDescs[i].innerHTML = "This machine is currently out of service, and is unavailable to use." + } else if (status[0][i] == "FINISHED") { + if ((i + 1) % 2 == 0) { + machineImgs[i].src = "/assets/img/washer_clothes.png"; + if (machineDetailImgs[0]) machineDetailImgs[i].src = "/assets/img/washer_clothes.png"; + } else { + machineImgs[i].src = "/assets/img/dryer_clothes.png"; + if (machineDetailImgs[0]) machineDetailImgs[i].src = "/assets/img/dryer_clothes.png"; + } + machineTxts[i].innerHTML = "Idle" + if (machineDetailImgs[0]) machineDetailTitles[i].innerHTML = "Idle" + if (machineDetailImgs[0]) machineDetailDescs[i].innerHTML = "Clothes may not be collected yet." + } else { + if ((i + 1) % 2 == 0) { + machineImgs[i].src = "/assets/img/washer_off.png"; + if (machineDetailImgs[0]) machineDetailImgs[i].src = "/assets/img/washer_off.png"; + } else { + machineImgs[i].src = "/assets/img/dryer_off.png"; + if (machineDetailImgs[0]) machineDetailImgs[i].src = "/assets/img/dryer_off.png"; + } + if (machineDetailImgs[0]) machineDetailTitles[i].innerHTML = "Idle" + if (machineDetailImgs[0]) machineDetailDescs[i].innerHTML = "" + machineTxts[i].innerHTML = "Idle" + } + } + + console.log("done"); +} + +// --- current timers +async function startLoadTimers() { + information(); + + const timersData = await fetchTimers(); + + if (timersData[0] != 200) { + console.error(timersData[0].toString() + " from backend: " + timersData[1]); + return; + } + + const timers = timersData[1]; + + const container = document.getElementById("timer-container") + if (timers.length > 0) container.innerHTML = ''; + + const textList = [] + const progList = [] + const startTimestamps = [] + const endTimestamps = [] + + for (let i = 0; i < timers.length; i++) { + container.innerHTML += ` + <div class="section-container no-pad" id="timer-${timers[i]["id"]}"> + <h1>Timer #${(i + 1).toString()}</h1> + <div class="machine-container"> + <div class="txtcol-dryer ${timers[i]["machine"] == 1 ? "machine-selected" : ""}"> + <span>Dryer 1</span> + <img src="/assets/img/dryer_${timers[i]["machine"] == 1 ? "on" : "off"}.png" alt=""> + </div> + <div class="txtcol-washer ${timers[i]["machine"] == 2 ? "machine-selected" : ""}"> + <span>Washer 1</span> + <img src="/assets/img/washer_${timers[i]["machine"] == 2 ? "on" : "off"}.png" alt=""> + </div> + <div class="txtcol-dryer ${timers[i]["machine"] == 3 ? "machine-selected" : ""}"> + <span>Dryer 2</span> + <img src="/assets/img/dryer_${timers[i]["machine"] == 3 ? "on" : "off"}.png" alt=""> + </div> + <div class="txtcol-washer ${timers[i]["machine"] == 4 ? "machine-selected" : ""}"> + <span>Washer 2</span> + <img src="/assets/img/washer_${timers[i]["machine"] == 4 ? "on" : "off"}.png" alt=""> + </div> + </div> + <div class="timer-container"> + <span id="timer-txt-${i}">15:00</span> + <div class="prog-container"> + <div class="prog" id="timer-prog-${i}"></div> + </div> + </div> + <button class="button bg-1" disabled id="timer-btn-${i}">I have collected my laundry!</button> + </div> + ` + + textList.push(`timer-txt-${i}`); + progList.push(`timer-prog-${i}`); + endTimestamps.push(Date.parse(timers[i]["end_time"])); + startTimestamps.push(Date.parse(timers[i]["start_time"])); + } + + for (let i = 0; i < timers.length; i++) { // html rebuilds everytime innerHTML is modified + document.getElementById(`timer-btn-${i}`).addEventListener("click", function () { + finishLaundryTimer(timers[i]["id"]); + }); + console.log("added!"); + } + + console.log(textList); + console.log(progList); + console.log(endTimestamps); + console.log(startTimestamps); + + while (true) { + for (let i = 0; i < textList.length; i++) { + const text = document.getElementById(textList[i]); + text.innerText = ""; + const timeRemaining = Math.max(Math.round((endTimestamps[i] - Date.now()) / 1000), 0); + const hours = Math.floor(timeRemaining / 3600); + const minutes = Math.floor(timeRemaining / 60) % 60; + const seconds = timeRemaining % 60; + if (hours > 0) text.innerText += hours.toString().padStart(2, '0') + ':'; + text.innerText += minutes.toString().padStart(2, '0') + ':'; + text.innerText += seconds.toString().padStart(2, '0'); + + const prog = document.getElementById(progList[i]); + const totalTime = endTimestamps[0] - startTimestamps[0]; + prog.style.width = ((timeRemaining / (totalTime / 1000)) * 100).toString() + "%"; + + if (timeRemaining <= 0) { + document.getElementById(`timer-btn-${i}`).disabled = false; + } + } + await delay(1000); + } +} + +async function fetchTimers() { + const response = await fetch(`${API_URL}/laundry`, { + method: "POST", + credentials: "include", + }); + return [response.status, await response.json()]; +} + +// --- finish / collect timer / laundry +async function finishLaundryTimer(timerId) { + console.log("finishing timer! w/ id "+timerId.toString()); + const response = await fetch(`${API_URL}/finish`, { + method: "POST", + credentials: "include", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({id: timerId}), + }); + if (await response.text() == "laundry finished") { + window.location.reload(); + } +} + +const delay = (durationMs) => { + return new Promise(resolve => setTimeout(resolve, durationMs)); +} |
