From fd27ac9c692e2a09906c5384ee6d9fc2906ccd29 Mon Sep 17 00:00:00 2001 From: metacryst Date: Tue, 13 Jan 2026 18:06:32 -0600 Subject: [PATCH] sidebar --- src/{js => }/Home.js | 127 ++++++++++++++++++++++---------------- src/_/code/quill.js | 25 ++++++-- src/_/code/styles.css | 13 ++++ src/components/Sidebar.js | 46 ++++++++++++++ src/css/style.css | 12 ---- src/index.js | 2 +- 6 files changed, 154 insertions(+), 71 deletions(-) rename src/{js => }/Home.js (88%) create mode 100644 src/components/Sidebar.js delete mode 100644 src/css/style.css diff --git a/src/js/Home.js b/src/Home.js similarity index 88% rename from src/js/Home.js rename to src/Home.js index 2a6c5df..88e78a8 100644 --- a/src/js/Home.js +++ b/src/Home.js @@ -1,69 +1,36 @@ +import "./components/Sidebar.js" + class Home extends Shadow { tracking = false logs = [] timer = null - async startTracking() { - if (!navigator.geolocation) { - alert("Geolocation is not supported by your browser."); - return; - } - - this.tracking = true - - navigator.geolocation.requestPermission?.() || Promise.resolve('granted'); - - const permission = await new Promise((resolve) => { - navigator.geolocation.getCurrentPosition( - () => resolve('granted'), - () => resolve('denied') - ); - }); - - if (permission === 'denied') { - alert("Location permission required"); - this.tracking = false - return; - } - - const timer = setInterval(async () => { - navigator.geolocation.getCurrentPosition( - async (pos) => { - const { latitude, longitude } = pos.coords; - const now = new Date(); - const log = `${now.toISOString()} — (${latitude}, ${longitude})`; - const timestamp = this.formatCentralTime(now); - - this.logs = [log, ...this.logs] - - this.updateLogs() - await this.sendLocation(latitude, longitude, timestamp); - }, - (err) => console.error("Location error:", err), - { enableHighAccuracy: true } - ); - }, 1000); - - this.timer = timer - } - - stopTracking() { - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - this.tracking = false; - } - } - render() { ZStack(() => { + Sidebar() + // Title bar HStack(() => { img("./_/icons/runner.svg", "2em", "2em") + p("San Marcos, TX") - .fontSize(1.2, em) + .fontSize(1.2, em) + img("./_/icons/hamburger.svg", "2em", "2em") + .transition("scale .3s") + .zIndex(2) + .onTouch(function (start) { + if(start) { + this.style.scale = 0.8 + } else { + this.style.scale = 1 + } + + if(start === false) { + $("sidebar-").toggle() + } + }) }) .gap(15, vw) .position("fixed") @@ -144,6 +111,58 @@ class Home extends Shadow { .fontFamily("Arial") } + async startTracking() { + if (!navigator.geolocation) { + alert("Geolocation is not supported by your browser."); + return; + } + + this.tracking = true + + navigator.geolocation.requestPermission?.() || Promise.resolve('granted'); + + const permission = await new Promise((resolve) => { + navigator.geolocation.getCurrentPosition( + () => resolve('granted'), + () => resolve('denied') + ); + }); + + if (permission === 'denied') { + alert("Location permission required"); + this.tracking = false + return; + } + + const timer = setInterval(async () => { + navigator.geolocation.getCurrentPosition( + async (pos) => { + const { latitude, longitude } = pos.coords; + const now = new Date(); + const log = `${now.toISOString()} — (${latitude}, ${longitude})`; + const timestamp = this.formatCentralTime(now); + + this.logs = [log, ...this.logs] + + this.updateLogs() + await this.sendLocation(latitude, longitude, timestamp); + }, + (err) => console.error("Location error:", err), + { enableHighAccuracy: true } + ); + }, 1000); + + this.timer = timer + } + + stopTracking() { + if (this.timer) { + clearInterval(this.timer); + this.timer = null; + this.tracking = false; + } + } + showTracking() { this.$("#playButton").rerender() this.$("#playButton").style.backgroundColor = this.tracking ? "#CD593E" : "#A6EABD" @@ -176,7 +195,7 @@ class Home extends Shadow { async sendLocation(lat, lon, timestamp) { try { - const resp = await fetch('http://localhost:3008/api/location', { + const resp = await fetch('http://localhost:3009/api/location', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ diff --git a/src/_/code/quill.js b/src/_/code/quill.js index 19242eb..c8a0f7a 100644 --- a/src/_/code/quill.js +++ b/src/_/code/quill.js @@ -51,12 +51,17 @@ window.setQuery = function(key, value) { return newUrl; }; - + window.navigateTo = function(url) { window.dispatchEvent(new Event('navigate')); window.history.pushState({}, '', url); } +window.setLocation = function(url) { + window.dispatchEvent(new Event('navigate')); + window.history.replaceState({}, '', url); +} + /* $ SELECTOR */ HTMLElement.prototype.$ = function(selector) { @@ -91,8 +96,6 @@ console.green = function(message) { } /* GET CSS VARIABLES FOR DARK OR LIGHT MODE */ -window.darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; -document.documentElement.classList.add(darkMode ? 'dark' : 'light'); window.getColor = function(name) { const rootStyles = getComputedStyle(document.documentElement); @@ -815,6 +818,20 @@ window.input = function(placeholder = "", width, height) { return el } +window.select = function(cb) { + let el = document.createElement("select") + el.render = cb + quill.render(el) + return el +} + +window.option = function(placeholder = "") { + let el = document.createElement("option") + el.innerText = placeholder + quill.render(el) + return el +} + window.label = function(inside) { let el = document.createElement("label") if(typeof inside === "string") { @@ -1034,7 +1051,7 @@ HTMLElement.prototype.onInput = function(cb) { }; HTMLElement.prototype.onChange = function(cb) { - if(!this.matches('input, textarea, [contenteditable=""], [contenteditable="true"]')) + if(!this.matches('input, textarea, select, [contenteditable=""], [contenteditable="true"]')) throw new Error("Can't put input event on non-input element!") this._storeListener("change", cb); return this; diff --git a/src/_/code/styles.css b/src/_/code/styles.css index 2f0b2fe..b04acbe 100644 --- a/src/_/code/styles.css +++ b/src/_/code/styles.css @@ -9,4 +9,17 @@ :root { } +} + +html, +body { + padding: 0; + margin: 0; +} + +body { + padding-top: env(safe-area-inset-top); + padding-bottom: env(safe-area-inset-bottom); + padding-left: env(safe-area-inset-left); + padding-right: env(safe-area-inset-right); } \ No newline at end of file diff --git a/src/components/Sidebar.js b/src/components/Sidebar.js new file mode 100644 index 0000000..75f5180 --- /dev/null +++ b/src/components/Sidebar.js @@ -0,0 +1,46 @@ +class Sidebar extends Shadow { + + SidebarItem(text) { + return p(text) + .fontSize(1.5, em) + .fontWeight("bold") + .fontFamily("Sedan SC") + .marginLeft(2, em) + .fontStyle("italic") + .onClick(function () { + if(this.innerText === "Home") { + window.navigateTo("/") + return + } + window.navigateTo(this.innerText.toLowerCase().replace(/\s+/g, "")) + }) + } + + render() { + VStack(() => { + this.SidebarItem("Home") + this.SidebarItem("Map") + this.SidebarItem("Logout") + }) + .gap(2, em) + .paddingTop(30, vh) + .height(100, vh) + .width(70, vw) + .borderLeft("1px solid black") + .position("fixed") + .background("var(--main)") + .xRight(-70, vw) + .transition("right .3s") + .zIndex(1) + } + + toggle() { + if(this.style.right === "-70vw") { + this.style.right = "0vw" + } else { + this.style.right = "-70vw" + } + } +} + +register(Sidebar) \ No newline at end of file diff --git a/src/css/style.css b/src/css/style.css deleted file mode 100644 index 2b35d05..0000000 --- a/src/css/style.css +++ /dev/null @@ -1,12 +0,0 @@ -html, -body { - padding: 0; - margin: 0; -} - -body { - padding-top: env(safe-area-inset-top); - padding-bottom: env(safe-area-inset-bottom); - padding-left: env(safe-area-inset-left); - padding-right: env(safe-area-inset-right); -} \ No newline at end of file diff --git a/src/index.js b/src/index.js index c1feeba..5892631 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,3 @@ -import "./js/Home.js" +import "./Home.js" Home() document.body.style.backgroundColor = "var(--main)" \ No newline at end of file