diff --git a/package.json b/package.json
index ca950a4..1761750 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"cors": "^2.8.5",
"dotenv": "^17.2.3",
"express": "^4.18.2",
+ "express-useragent": "^2.0.2",
"jsonwebtoken": "^9.0.2",
"moment": "^2.30.1",
"ws": "^8.18.3",
diff --git a/server/index.js b/server/index.js
index e14544b..f703edc 100644
--- a/server/index.js
+++ b/server/index.js
@@ -6,6 +6,7 @@ const fs = require('fs');
const chalk = require('chalk');
const moment = require('moment');
const path = require('path');
+const useragent = require("express-useragent");
import "./util.js"
import Socket from './ws/ws.js'
@@ -112,12 +113,13 @@ class Server {
let privateSite = () => {
let filePath;
+ let platformFolder = req.useragent.isMobile ? "mobile" : "desktop"
if(url.startsWith("/_")) {
filePath = path.join(this.UIPath, url);
} else if(url.includes("75820185")) {
- filePath = path.join(this.UIPath, "site", url.split("75820185")[1]);
+ filePath = path.join(this.UIPath, platformFolder, url.split("75820185")[1]);
} else {
- filePath = path.join(this.UIPath, "site", "index.html");
+ filePath = path.join(this.UIPath, platformFolder, "index.html");
}
res.sendFile(filePath);
@@ -134,10 +136,10 @@ class Server {
const formattedDate = moment().format('M.D');
const formattedTime = moment().format('h:mma');
if(req.url.includes("/api/")) {
- console.logclean(chalk.blue(` ${req.method} ${req.url} | ${formattedDate} ${formattedTime}`));
+ console.log(chalk.blue(` ${req.method} ${req.url} | ${formattedDate} ${formattedTime}`));
} else {
if(req.url === "/")
- console.logclean(chalk.gray(` ${req.method} ${req.url} | ${formattedDate} ${formattedTime}`));
+ console.log(chalk.gray(` ${req.method} ${req.url} | ${formattedDate} ${formattedTime}`));
}
next();
}
@@ -146,9 +148,9 @@ class Server {
const originalSend = res.send;
res.send = function (body) {
if(res.statusCode >= 400) {
- console.logclean(chalk.blue( `<-${chalk.red(res.statusCode)}- ${req.method} ${req.url} | ${chalk.red(body)}`));
+ console.log(chalk.blue( `<-${chalk.red(res.statusCode)}- ${req.method} ${req.url} | ${chalk.red(body)}`));
} else {
- console.logclean(chalk.blue(`<-${res.statusCode}- ${req.method} ${req.url}`));
+ console.log(chalk.blue(`<-${res.statusCode}- ${req.method} ${req.url}`));
}
originalSend.call(this, body);
};
@@ -164,6 +166,7 @@ class Server {
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
+ app.use(useragent.express());
app.use(this.logRequest);
app.use(this.logResponse);
@@ -176,16 +179,16 @@ class Server {
global.Socket = new Socket(server);
const PORT = 3003;
server.listen(PORT, () => {
- console.logclean("\n")
- console.logclean(chalk.yellow("*************** Hyperia ***************"))
- console.logclean(chalk.yellowBright(`Server is running on port ${PORT}: http://localhost`));
- console.logclean(chalk.yellow("***************************************"))
- console.logclean("\n")
+ console.log("\n")
+ console.log(chalk.yellow("*************** Hyperia ***************"))
+ console.log(chalk.yellowBright(`Server is running on port ${PORT}: http://localhost`));
+ console.log(chalk.yellow("***************************************"))
+ console.log("\n")
});
process.on('SIGINT', async () => {
- console.logclean(chalk.red('Closing server...'));
- console.logclean(chalk.green('Database connection closed.'));
+ console.log(chalk.red('Closing server...'));
+ console.log(chalk.green('Database connection closed.'));
process.exit(0);
});
@@ -193,31 +196,4 @@ class Server {
}
}
-const _log = console.log;
-
-console.logclean = function (...args) {
- _log.call(console, ...args);
-}
-
-// console.log = function (...args) {
-// // Get the caller location
-// const stack = new Error().stack.split("\n")[2];
-// const match = stack.match(/(\/.*:\d+:\d+)/);
-// let location = match ? match[1] : "unknown";
-
-// // Remove CWD prefix
-// while (location.startsWith("/")) {
-// location = location.slice(1);
-// }
-// location = "/" + location
-
-// let cwd = process.cwd();
-// if (location.startsWith(cwd)) {
-// location = location.slice(cwd.length);
-// if (location.startsWith("/")) location = location.slice(1);
-// }
-
-// _log.call(console, `[${location}]`, ...args);
-// };
-
const server = new Server()
\ No newline at end of file
diff --git a/ui/_/icons/Column.svg b/ui/_/icons/Column.svg
new file mode 100644
index 0000000..ab79e11
--- /dev/null
+++ b/ui/_/icons/Column.svg
@@ -0,0 +1,4 @@
+
diff --git a/ui/site/apps/Forum/Forum.js b/ui/desktop/apps/Forum/Forum.js
similarity index 100%
rename from ui/site/apps/Forum/Forum.js
rename to ui/desktop/apps/Forum/Forum.js
diff --git a/ui/site/apps/Forum/ForumPanel.js b/ui/desktop/apps/Forum/ForumPanel.js
similarity index 100%
rename from ui/site/apps/Forum/ForumPanel.js
rename to ui/desktop/apps/Forum/ForumPanel.js
diff --git a/ui/site/apps/Jobs/Jobs.js b/ui/desktop/apps/Jobs/Jobs.js
similarity index 100%
rename from ui/site/apps/Jobs/Jobs.js
rename to ui/desktop/apps/Jobs/Jobs.js
diff --git a/ui/site/apps/Jobs/JobsGrid.js b/ui/desktop/apps/Jobs/JobsGrid.js
similarity index 100%
rename from ui/site/apps/Jobs/JobsGrid.js
rename to ui/desktop/apps/Jobs/JobsGrid.js
diff --git a/ui/site/apps/Jobs/JobsSidebar.js b/ui/desktop/apps/Jobs/JobsSidebar.js
similarity index 100%
rename from ui/site/apps/Jobs/JobsSidebar.js
rename to ui/desktop/apps/Jobs/JobsSidebar.js
diff --git a/ui/site/apps/Market/Market.js b/ui/desktop/apps/Market/Market.js
similarity index 100%
rename from ui/site/apps/Market/Market.js
rename to ui/desktop/apps/Market/Market.js
diff --git a/ui/site/apps/Market/MarketGrid.js b/ui/desktop/apps/Market/MarketGrid.js
similarity index 100%
rename from ui/site/apps/Market/MarketGrid.js
rename to ui/desktop/apps/Market/MarketGrid.js
diff --git a/ui/site/apps/Market/MarketSidebar.js b/ui/desktop/apps/Market/MarketSidebar.js
similarity index 100%
rename from ui/site/apps/Market/MarketSidebar.js
rename to ui/desktop/apps/Market/MarketSidebar.js
diff --git a/ui/site/apps/Messages/Messages.js b/ui/desktop/apps/Messages/Messages.js
similarity index 100%
rename from ui/site/apps/Messages/Messages.js
rename to ui/desktop/apps/Messages/Messages.js
diff --git a/ui/site/apps/Messages/MessagesPanel.js b/ui/desktop/apps/Messages/MessagesPanel.js
similarity index 100%
rename from ui/site/apps/Messages/MessagesPanel.js
rename to ui/desktop/apps/Messages/MessagesPanel.js
diff --git a/ui/site/apps/Messages/MessagesSidebar.js b/ui/desktop/apps/Messages/MessagesSidebar.js
similarity index 100%
rename from ui/site/apps/Messages/MessagesSidebar.js
rename to ui/desktop/apps/Messages/MessagesSidebar.js
diff --git a/ui/site/apps/Tasks/Tasks.js b/ui/desktop/apps/Tasks/Tasks.js
similarity index 100%
rename from ui/site/apps/Tasks/Tasks.js
rename to ui/desktop/apps/Tasks/Tasks.js
diff --git a/ui/site/components/AppMenu.js b/ui/desktop/components/AppMenu.js
similarity index 100%
rename from ui/site/components/AppMenu.js
rename to ui/desktop/components/AppMenu.js
diff --git a/ui/site/components/AppWindow.js b/ui/desktop/components/AppWindow.js
similarity index 100%
rename from ui/site/components/AppWindow.js
rename to ui/desktop/components/AppWindow.js
diff --git a/ui/site/components/Home.js b/ui/desktop/components/Home.js
similarity index 100%
rename from ui/site/components/Home.js
rename to ui/desktop/components/Home.js
diff --git a/ui/site/components/InputBox.js b/ui/desktop/components/InputBox.js
similarity index 100%
rename from ui/site/components/InputBox.js
rename to ui/desktop/components/InputBox.js
diff --git a/ui/site/components/LoadingCircle.js b/ui/desktop/components/LoadingCircle.js
similarity index 100%
rename from ui/site/components/LoadingCircle.js
rename to ui/desktop/components/LoadingCircle.js
diff --git a/ui/site/components/ProfileButton.js b/ui/desktop/components/ProfileButton.js
similarity index 100%
rename from ui/site/components/ProfileButton.js
rename to ui/desktop/components/ProfileButton.js
diff --git a/ui/site/components/ProfileMenu.js b/ui/desktop/components/ProfileMenu.js
similarity index 100%
rename from ui/site/components/ProfileMenu.js
rename to ui/desktop/components/ProfileMenu.js
diff --git a/ui/site/components/Sidebar.js b/ui/desktop/components/Sidebar.js
similarity index 100%
rename from ui/site/components/Sidebar.js
rename to ui/desktop/components/Sidebar.js
diff --git a/ui/site/index.html b/ui/desktop/index.html
similarity index 100%
rename from ui/site/index.html
rename to ui/desktop/index.html
diff --git a/ui/site/index.js b/ui/desktop/index.js
similarity index 100%
rename from ui/site/index.js
rename to ui/desktop/index.js
diff --git a/ui/site/util.js b/ui/desktop/util.js
similarity index 100%
rename from ui/site/util.js
rename to ui/desktop/util.js
diff --git a/ui/site/ws/Connection.js b/ui/desktop/ws/Connection.js
similarity index 100%
rename from ui/site/ws/Connection.js
rename to ui/desktop/ws/Connection.js
diff --git a/ui/site/ws/Socket.js b/ui/desktop/ws/Socket.js
similarity index 100%
rename from ui/site/ws/Socket.js
rename to ui/desktop/ws/Socket.js
diff --git a/ui/mobile/apps/Forum/Forum.js b/ui/mobile/apps/Forum/Forum.js
new file mode 100644
index 0000000..0a26881
--- /dev/null
+++ b/ui/mobile/apps/Forum/Forum.js
@@ -0,0 +1,104 @@
+import './ForumPanel.js'
+
+css(`
+ forum- {
+ font-family: 'Bona';
+ }
+
+ forum- input::placeholder {
+ font-family: 'Bona Nova';
+ font-size: 0.9em;
+ color: var(--accent);
+ }
+
+ input[type="checkbox"] {
+ appearance: none; /* remove default style */
+ -webkit-appearance: none;
+ width: 1em;
+ height: 1em;
+ border: 1px solid var(--accent);
+ }
+
+ input[type="checkbox"]:checked {
+ background-color: var(--red);
+ }
+`)
+
+class Forum extends Shadow {
+
+ selectedForum = "HY"
+
+ render() {
+ ZStack(() => {
+ HStack(() => {
+ VStack(() => {
+ img("/_/icons/logo.svg", "2em")
+ .padding(0.8, em)
+ .borderRadius(12, px)
+ .marginHorizontal(1, em)
+ .onHover(function (hovering) {
+ if(hovering) {
+ this.style.background = "var(--darkbrown)"
+ } else {
+ this.style.background = ""
+ }
+ })
+ .opacity(0)
+
+ img("/_/icons/place/austin.svg", "2em")
+ .padding(0.8, em)
+ .borderRadius(12, px)
+ .marginHorizontal(1, em)
+ .onHover(function (hovering) {
+ if(hovering) {
+ this.style.background = "var(--darkbrown)"
+ } else {
+ this.style.background = ""
+ }
+ })
+ .opacity(0)
+
+ })
+ .height(100, vh)
+ .paddingLeft(2, em)
+ .paddingRight(2, em)
+ .gap(1, em)
+ .marginTop(20, vh)
+
+ VStack(() => {
+
+ ForumPanel()
+
+ input("Message Hyperia", "98%")
+ .paddingVertical(1, em)
+ .paddingLeft(2, pct)
+ .color("var(--accent)")
+ .background("var(--darkbrown)")
+ .marginBottom(6, em)
+ .border("none")
+ .fontSize(1, em)
+ .onKeyDown(function (e) {
+ if (e.key === "Enter") {
+ window.Socket.send({app: "FORUM", operation: "SEND", msg: {forum: "HY", text: this.value }})
+ this.value = ""
+ }
+ })
+ })
+ .gap(0.5, em)
+ .width(100, pct)
+ .height(100, vh)
+ .alignHorizontal("center")
+ .alignVertical("end")
+ })
+ .width(100, "%")
+ .height(87, vh)
+ .x(0).y(0, vh)
+ })
+ .width(100, pct)
+ .height(100, pct)
+ }
+
+
+}
+
+register(Forum)
\ No newline at end of file
diff --git a/ui/mobile/apps/Forum/ForumPanel.js b/ui/mobile/apps/Forum/ForumPanel.js
new file mode 100644
index 0000000..d2a6fa4
--- /dev/null
+++ b/ui/mobile/apps/Forum/ForumPanel.js
@@ -0,0 +1,90 @@
+import "../../components/LoadingCircle.js"
+
+class ForumPanel extends Shadow {
+ forums = [
+ "HY"
+ ]
+ messages = []
+
+ render() {
+ VStack(() => {
+ if(this.messages.length > 0) {
+
+ let previousDate = null
+
+ for(let i=0; i {
+ HStack(() => {
+ p(message.sentBy)
+ .fontWeight("bold")
+ .marginBottom(0.3, em)
+
+ p(util.formatTime(message.time))
+ .opacity(0.2)
+ .marginLeft(1, em)
+ })
+ p(message.text)
+ })
+ }
+ } else {
+ LoadingCircle()
+ }
+ })
+ .gap(1, em)
+ .position("relative")
+ .overflow("scroll")
+ .height(100, pct)
+ .width(96, pct)
+ .paddingTop(5, em)
+ .paddingBottom(2, em)
+ .paddingLeft(4, pct)
+ .backgroundColor("var(--darkbrown)")
+ .onAppear(async () => {
+ console.log("appear")
+ requestAnimationFrame(() => {
+ this.scrollTop = this.scrollHeight
+ });
+ let res = await Socket.send({app: "FORUM", operation: "GET", msg: {forum: "HY", number: 100}})
+ if(!res) console.error("failed to get messages")
+ if(res.msg.length > 0 && this.messages.length === 0) {
+ console.log("rerendering", res.msg)
+ this.messages = res.msg
+ this.rerender()
+ }
+ window.addEventListener("new-post", (e) => {
+ this.messages = e.detail
+ if(e.detail.length !== this.messages || e.detail.last.time !== this.messages.last.time || e.detail.first.time !== this.messages.first.time) {
+ this.rerender()
+ }
+ })
+ })
+ }
+
+ parseDate(str) {
+ // Format: MM.DD.YYYY-HH:MM:SSxxxxxx(am|pm)
+ const match = str.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})-(\d{1,2}):(\d{2}).*(am|pm)$/i);
+ if (!match) return null;
+
+ const [, mm, dd, yyyy, hh, min, ampm] = match;
+ const date = `${mm}/${dd}/${yyyy}`;
+ const time = `${hh}:${min}${ampm.toLowerCase()}`;
+
+ return { date, time };
+ }
+}
+
+register(ForumPanel)
\ No newline at end of file
diff --git a/ui/mobile/apps/Jobs/Jobs.js b/ui/mobile/apps/Jobs/Jobs.js
new file mode 100644
index 0000000..bb72598
--- /dev/null
+++ b/ui/mobile/apps/Jobs/Jobs.js
@@ -0,0 +1,101 @@
+import "./JobsSidebar.js"
+import "./JobsGrid.js"
+
+css(`
+ jobs- {
+ font-family: 'Bona';
+ }
+
+ jobs- input::placeholder {
+ font-family: 'Bona Nova';
+ font-size: 0.9em;
+ color: var(--accent);
+ }
+
+ input[type="checkbox"] {
+ appearance: none; /* remove default style */
+ -webkit-appearance: none;
+ width: 1em;
+ height: 1em;
+ border: 1px solid var(--accent);
+ }
+
+ input[type="checkbox"]:checked {
+ background-color: var(--red);
+ }
+`)
+
+class Jobs extends Shadow {
+ jobs = [
+ {
+ title: "Austin Chapter Lead",
+ salary: "1% of Local Revenue",
+ company: "Hyperia",
+ city: "Austin",
+ state: "TX"
+ }
+ ]
+
+ render() {
+ ZStack(() => {
+ HStack(() => {
+ JobsSidebar()
+
+ JobsGrid(this.jobs)
+ })
+ .width(100, "%")
+ .x(0).y(13, vh)
+
+ HStack(() => {
+ input("Search jobs... (Coming Soon!)", "45vw")
+ .attr({
+ "type": "text",
+ "disabled": "true"
+ })
+ .fontSize(1.1, em)
+ .paddingLeft(1.3, em)
+ .background("transparent")
+ .border("0.5px solid var(--divider)")
+ .outline("none")
+ .color("var(--accent)")
+ .opacity(0.5)
+ .borderRadius(10, px)
+ .background("grey")
+ .cursor("not-allowed")
+
+ button("+ Add Job")
+ .width(7, em)
+ .marginLeft(1, em)
+ .borderRadius(10, px)
+ .background("transparent")
+ .border("0.3px solid var(--accent2)")
+ .color("var(--accent)")
+ .fontFamily("Bona Nova")
+ .onHover(function (hovering) {
+ if(hovering) {
+ this.style.background = "var(--green)"
+
+ } else {
+ this.style.background = "transparent"
+
+ }
+ })
+ .onClick((clicking) => {
+ console.log(this, "clicked")
+ })
+
+ })
+ .x(55, vw).y(4, vh)
+ .position("absolute")
+ .transform("translateX(-50%)")
+ })
+ .width(100, "%")
+ .height(100, "%")
+ }
+
+ connectedCallback() {
+ // Optional additional logic
+ }
+}
+
+register(Jobs)
\ No newline at end of file
diff --git a/ui/mobile/apps/Jobs/JobsGrid.js b/ui/mobile/apps/Jobs/JobsGrid.js
new file mode 100644
index 0000000..2af5d4f
--- /dev/null
+++ b/ui/mobile/apps/Jobs/JobsGrid.js
@@ -0,0 +1,60 @@
+class JobsGrid extends Shadow {
+ jobs;
+
+ constructor(jobs) {
+ super()
+ this.jobs = jobs
+ }
+
+ boldUntilFirstSpace(text) {
+ const index = text.indexOf(' ');
+ if (index === -1) {
+ // No spaces — bold the whole thing
+ return `${text}`;
+ }
+ return `${text.slice(0, index)}${text.slice(index)}`;
+ }
+
+ render() {
+ VStack(() => {
+ h3("Results")
+ .marginTop(0.1, em)
+ .marginBottom(1, em)
+ .marginLeft(0.4, em)
+ .color("var(--accent2)")
+
+ if (this.jobs.length > 0) {
+ ZStack(() => {
+ for (let i = 0; i < this.jobs.length; i++) {
+ VStack(() => {
+ p(this.jobs[i].title)
+ .fontSize(1.2, em)
+ .fontWeight("bold")
+ .marginBottom(0.5, em)
+ p(this.jobs[i].company)
+ p(this.jobs[i].city + ", " + this.jobs[i].state)
+ .marginBottom(0.5, em)
+ p(this.boldUntilFirstSpace(this.jobs[i].salary))
+ })
+ .padding(1, em)
+ .borderRadius(5, "px")
+ .background("var(--darkbrown)")
+ }
+ })
+ .display("grid")
+ .gridTemplateColumns("repeat(auto-fill, minmax(250px, 1fr))")
+ .gap(1, em)
+ } else {
+ p("No Jobs!")
+ }
+ })
+ .height(100, vh)
+ .paddingLeft(2, em)
+ .paddingRight(2, em)
+ .paddingTop(2, em)
+ .gap(0, em)
+ .width(100, "%")
+ }
+}
+
+register(JobsGrid)
diff --git a/ui/mobile/apps/Jobs/JobsSidebar.js b/ui/mobile/apps/Jobs/JobsSidebar.js
new file mode 100644
index 0000000..1546cec
--- /dev/null
+++ b/ui/mobile/apps/Jobs/JobsSidebar.js
@@ -0,0 +1,26 @@
+class JobsSidebar extends Shadow {
+ render() {
+ VStack(() => {
+ h3("Location")
+ .color("var(--accent2)")
+ .marginBottom(0, em)
+
+ HStack(() => {
+ input("Location", "100%")
+ .paddingLeft(3, em)
+ .paddingVertical(0.75, em)
+ .backgroundImage("/_/icons/locationPin.svg")
+ .backgroundRepeat("no-repeat")
+ .backgroundSize("18px 18px")
+ .backgroundPosition("10px center")
+ })
+ })
+ .paddingTop(1, em)
+ .paddingLeft(3, em)
+ .paddingRight(3, em)
+ .gap(1, em)
+ .minWidth(10, vw)
+ }
+}
+
+register(JobsSidebar)
\ No newline at end of file
diff --git a/ui/mobile/apps/Market/Market.js b/ui/mobile/apps/Market/Market.js
new file mode 100644
index 0000000..e3bceeb
--- /dev/null
+++ b/ui/mobile/apps/Market/Market.js
@@ -0,0 +1,105 @@
+import "./MarketSidebar.js"
+import "./MarketGrid.js"
+
+css(`
+ market- {
+ font-family: 'Bona';
+ }
+
+ market- input::placeholder {
+ font-family: 'Bona Nova';
+ font-size: 0.9em;
+ color: var(--accent);
+ }
+
+ input[type="checkbox"] {
+ appearance: none; /* remove default style */
+ -webkit-appearance: none;
+ width: 1em;
+ height: 1em;
+ border: 1px solid var(--accent);
+ }
+
+ input[type="checkbox"]:checked {
+ background-color: var(--red);
+ }
+`)
+
+class Market extends Shadow {
+
+ listings = [
+ {
+ title: "Shield Lapel Pin",
+ stars: "5",
+ reviews: 1,
+ price: "$12",
+ company: "Hyperia",
+ type: "new",
+ image: "/db/images/1",
+ madeIn: "America"
+ }
+ ]
+
+ render() {
+ ZStack(() => {
+ HStack(() => {
+ MarketSidebar()
+
+ MarketGrid(this.listings)
+ })
+ .width(100, "%")
+ .x(0).y(13, vh)
+
+ HStack(() => {
+ input("Search for products... (Coming Soon!)", "45vw")
+ .attr({
+ "type": "text",
+ "disabled": "true"
+ })
+ .fontSize(1.1, em)
+ .paddingLeft(1.3, em)
+ .background("transparent")
+ .border("0.5px solid var(--divider)")
+ .outline("none")
+ .color("var(--accent)")
+ .opacity(0.5)
+ .borderRadius(10, px)
+ .background("grey")
+ .cursor("not-allowed")
+
+ button("+ Add Item")
+ .width(7, em)
+ .marginLeft(1, em)
+ .borderRadius(10, px)
+ .background("transparent")
+ .border("0.5px solid var(--accent2)")
+ .color("var(--accent)")
+ .fontFamily("Bona Nova")
+ .onHover(function (hovering) {
+ if(hovering) {
+ this.style.background = "var(--green)"
+
+ } else {
+ this.style.background = "transparent"
+
+ }
+ })
+ .onClick((clicking) => {
+ console.log(this, "clicked")
+ })
+
+ })
+ .x(55, vw).y(4, vh)
+ .position("absolute")
+ .transform("translateX(-50%)")
+ })
+ .width(100, "%")
+ .height(100, "%")
+ }
+
+ connectedCallback() {
+ // Optional additional logic
+ }
+}
+
+register(Market)
diff --git a/ui/mobile/apps/Market/MarketGrid.js b/ui/mobile/apps/Market/MarketGrid.js
new file mode 100644
index 0000000..8740f9e
--- /dev/null
+++ b/ui/mobile/apps/Market/MarketGrid.js
@@ -0,0 +1,140 @@
+class MarketGrid extends Shadow {
+ listings;
+
+ constructor(listings) {
+ super()
+ this.listings = listings
+ }
+
+ boldUntilFirstSpace(text) {
+ if(!text) return
+ const index = text.indexOf(' ');
+ if (index === -1) {
+ // No spaces — bold the whole thing
+ return `${text}`;
+ }
+ return `${text.slice(0, index)}${text.slice(index)}`;
+ }
+
+ render() {
+ VStack(() => {
+ h3("Results")
+ .marginTop(0.1, em)
+ .marginBottom(1, em)
+ .marginLeft(0.4, em)
+ .color("var(--accent)")
+ .opacity(0.7)
+
+ if (this.listings.length > 0) {
+ ZStack(() => {
+ // BuyModal()
+
+ let params = new URLSearchParams(window.location.search);
+
+ const hyperiaMade = params.get("hyperia-made") === "true";
+ const americaMade = params.get("america-made") === "true";
+ const newItem = params.get("new") === "true";
+ const usedItem = params.get("used") === "true";
+
+
+ let filtered = this.listings;
+ if (hyperiaMade) {
+ filtered = filtered.filter(item => item.madeIn === "Hyperia");
+ }
+ if (americaMade) {
+ filtered = filtered.filter(item => item.madeIn === "America");
+ }
+ if (newItem) {
+ filtered = filtered.filter(item => item.type === "new");
+ }
+ if (usedItem) {
+ filtered = filtered.filter(item => item.type === "used");
+ }
+
+ for (let i = 0; i < filtered.length; i++) {
+ const rating = filtered[i].stars
+ const percent = (rating / 5)
+
+ VStack(() => {
+ img(filtered[i].image)
+ .marginBottom(0.5, em)
+
+ p(filtered[i].company)
+ .marginBottom(0.5, em)
+
+ p(filtered[i].title)
+ .fontSize(1.2, em)
+ .fontWeight("bold")
+ .marginBottom(0.5, em)
+
+ HStack(() => {
+ p(filtered[i].stars)
+ .marginRight(0.2, em)
+
+ ZStack(() => {
+ div("★★★★★") // Empty stars (background)
+ .color("#ccc")
+
+ div("★★★★★") // Filled stars (foreground, clipped by width)
+ .color("#ffa500")
+ .position("absolute")
+ .top(0)
+ .left(0)
+ .whiteSpace("nowrap")
+ .overflow("hidden")
+ .width(percent * 5, em)
+ })
+ .display("inline-block")
+ .position("relative")
+ .fontSize(1.2, em)
+ .lineHeight(1)
+
+ p(filtered[i].reviews)
+ .marginLeft(0.2, em)
+ })
+ .marginBottom(0.5, em)
+
+ p(filtered[i].price)
+ .fontSize(1.75, em)
+ .marginBottom(0.5, em)
+
+ button("Coming Soon!")
+ .onClick((finished) => {
+ if(finished) {
+
+ }
+ })
+ .onHover(function (hovering) {
+ if(hovering) {
+ this.style.backgroundColor = "var(--green)"
+ } else {
+ this.style.backgroundColor = ""
+ }
+ })
+
+ })
+ .padding(1, em)
+ .border("1px solid var(--accent2)")
+ .borderRadius(5, "px")
+ }
+ })
+ .display("grid")
+ .gridTemplateColumns("repeat(auto-fill, minmax(250px, 1fr))")
+ .gap(1, em)
+ } else {
+ p("No Listings!")
+ }
+ })
+ .onQueryChanged(() => {
+ console.log("query did change yup")
+ this.rerender()
+ })
+ .height(100, vh)
+ .paddingLeft(2, em)
+ .paddingRight(2, em)
+ .gap(0, em)
+ .width(100, "%")
+ }
+}
+
+register(MarketGrid)
\ No newline at end of file
diff --git a/ui/mobile/apps/Market/MarketSidebar.js b/ui/mobile/apps/Market/MarketSidebar.js
new file mode 100644
index 0000000..9324618
--- /dev/null
+++ b/ui/mobile/apps/Market/MarketSidebar.js
@@ -0,0 +1,85 @@
+class MarketSidebar extends Shadow {
+
+ handleChecked(e) {
+ let checked = e.target.checked
+ let label = $(`label[for="${e.target.id}"]`).innerText
+ if(checked) {
+ window.setQuery(label.toLowerCase(), true)
+ } else {
+ window.setQuery(label.toLowerCase(), null)
+ }
+ }
+
+ render() {
+ VStack(() => {
+
+ p("Make")
+
+ HStack(() => {
+ input()
+ .attr({
+ "type": "checkbox",
+ "id": "hyperia-check"
+ })
+ .onChange(this.handleChecked)
+ label("Hyperia-Made")
+ .attr({
+ "for": "hyperia-check"
+ })
+ .marginLeft(0.5, em)
+ })
+
+ HStack(() => {
+ input()
+ .attr({
+ "type": "checkbox",
+ "id": "america-check"
+ })
+ .onChange(this.handleChecked)
+ label("America-Made")
+ .attr({
+ "for": "america-check"
+ })
+ .marginLeft(0.5, em)
+ })
+
+ p("Condition")
+
+ HStack(() => {
+ input()
+ .attr({
+ "type": "checkbox",
+ "id": "new-check"
+ })
+ .onChange(this.handleChecked)
+ label("New")
+ .attr({
+ "for": "new-check"
+ })
+ .marginLeft(0.5, em)
+ })
+
+ HStack(() => {
+ input()
+ .attr({
+ "type": "checkbox",
+ "id": "used-check"
+ })
+ .onChange(this.handleChecked)
+ label("Used")
+ .attr({
+ "for": "used-check"
+ })
+ .marginLeft(0.5, em)
+ })
+ })
+ .paddingTop(12, vh)
+ .paddingLeft(3, em)
+ .paddingRight(3, em)
+ .gap(1, em)
+ .minWidth(10, vw)
+ .userSelect('none')
+ }
+}
+
+register(MarketSidebar)
\ No newline at end of file
diff --git a/ui/mobile/apps/Messages/Messages.js b/ui/mobile/apps/Messages/Messages.js
new file mode 100644
index 0000000..dd288a6
--- /dev/null
+++ b/ui/mobile/apps/Messages/Messages.js
@@ -0,0 +1,188 @@
+import "./MessagesSidebar.js"
+import "./MessagesPanel.js"
+
+css(`
+ messages- {
+ font-family: 'Bona';
+ }
+
+ messages- input::placeholder {
+ font-family: 'Bona Nova';
+ font-size: 0.9em;
+ color: var(--accent);
+ }
+
+ input[type="checkbox"] {
+ appearance: none; /* remove default style */
+ -webkit-appearance: none;
+ width: 1em;
+ height: 1em;
+ border: 1px solid var(--accent);
+ }
+
+ input[type="checkbox"]:checked {
+ background-color: var(--red);
+ }
+`)
+
+class Messages extends Shadow {
+ conversations = []
+ selectedConvoID = null
+ onConversationSelect(i) {
+ console.log("convo selected: ", i)
+ this.selectedConvoID = i
+ this.$("messagessidebar-").rerender()
+ this.$("messagespanel-").rerender()
+ }
+
+ getConvoFromID(id) {
+ for(let i=0; i {
+ HStack(() => {
+ MessagesSidebar(this.conversations, this.selectedConvoID, this.onConversationSelect)
+
+ VStack(() => {
+ if(this.getConvoFromID(this.selectedConvoID)) {
+ MessagesPanel(this.getConvoFromID(this.selectedConvoID).messages)
+ } else {
+ MessagesPanel()
+ }
+
+ input("Send Message", "93%")
+ .paddingVertical(1, em)
+ .paddingHorizontal(2, em)
+ .color("var(--accent)")
+ .background("var(--darkbrown)")
+ .marginBottom(6, em)
+ .border("none")
+ .fontSize(1, em)
+ .onKeyDown((e) => {
+ if (e.key === "Enter") {
+ window.Socket.send({app: "MESSAGES", operation: "SEND", msg: { conversation: `CONVERSATION-${this.selectedConvoID}`, text: e.target.value }})
+ e.target.value = ""
+ }
+ })
+ })
+ .gap(1, em)
+ .width(100, pct)
+ .alignHorizontal("center")
+ .alignVertical("end")
+ })
+ .onAppear(async () => {
+ let res = await Socket.send({app: "MESSAGES", operation: "GET"})
+ if(!res) console.error("failed to get messages")
+
+ if(res.msg.length > 0 && this.conversations.length === 0) {
+ this.conversations = res.msg
+ this.selectedConvoID = this.conversations[0].id
+ this.rerender()
+ }
+
+ window.addEventListener("new-message", (e) => {
+ let convoID = e.detail.conversationID
+ let messages = e.detail.messages
+ let convo = this.getConvoFromID(convoID)
+ convo.messages = messages
+ this.rerender()
+ })
+ })
+ .width(100, "%")
+ .height(87, vh)
+ .x(0).y(13, vh)
+
+ VStack(() => {
+ p("Add Message")
+
+ input("enter email...")
+ .color("var(--accent)")
+ .onKeyDown(function (e) {
+ if (e.key === "Enter") {
+ window.Socket.send({app: "MESSAGES", operation: "ADDCONVERSATION", msg: {email: this.value }})
+ this.value = ""
+ }
+ })
+
+ p("x")
+ .onClick(function (done) {
+ if(done) {
+ this.parentElement.style.display = "none"
+ }
+ })
+ .xRight(2, em).y(2, em)
+ .fontSize(1.4, em)
+ .cursor("pointer")
+
+ })
+ .gap(1, em)
+ .alignVertical("center")
+ .alignHorizontal("center")
+ .backgroundColor("black")
+ .border("1px solid var(--accent)")
+ .position("fixed")
+ .x(50, vw).y(50, vh)
+ .center()
+ .width(60, vw)
+ .height(60, vh)
+ .display("none")
+ .attr({id: "addPanel"})
+
+ HStack(() => {
+ input("Search messages... (Coming Soon!)", "45vw")
+ .attr({
+ "type": "text",
+ "disabled": "true"
+ })
+ .fontSize(1.1, em)
+ .paddingLeft(1.3, em)
+ .background("transparent")
+ .border("0.5px solid var(--divider)")
+ .outline("none")
+ .color("var(--accent)")
+ .opacity(0.5)
+ .borderRadius(10, px)
+ .background("grey")
+ .cursor("not-allowed")
+
+ button("+ New Message")
+ .width(13, em)
+ .marginLeft(1, em)
+ .borderRadius(10, px)
+ .background("transparent")
+ .border("0.5px solid var(--divider)")
+ .color("var(--accent)")
+ .fontFamily("Bona Nova")
+ .onHover(function (hovering) {
+ if(hovering) {
+ this.style.background = "var(--green)"
+
+ } else {
+ this.style.background = "transparent"
+
+ }
+ })
+ .onClick((done) => {
+ console.log("click")
+ if(done) {
+ this.$("#addPanel").style.display = "flex"
+ }
+ console.log(this, "clicked")
+ })
+
+ })
+ .x(55, vw).y(4, vh)
+ .position("absolute")
+ .transform("translateX(-50%)")
+ })
+ .width(100, "%")
+ .height(100, "%")
+ }
+}
+
+register(Messages)
\ No newline at end of file
diff --git a/ui/mobile/apps/Messages/MessagesPanel.js b/ui/mobile/apps/Messages/MessagesPanel.js
new file mode 100644
index 0000000..b608212
--- /dev/null
+++ b/ui/mobile/apps/Messages/MessagesPanel.js
@@ -0,0 +1,56 @@
+import "../../components/LoadingCircle.js"
+
+class MessagesPanel extends Shadow {
+ messages
+
+ constructor(messages) {
+ super()
+ this.messages = messages
+ }
+
+ render() {
+ VStack(() => {
+ if(this.messages) {
+ for(let i=0; i {
+ HStack(() => {
+ p(message.from.firstName + " " + message.from.lastName)
+ .fontWeight("bold")
+ .marginBottom(0.3, em)
+
+ p(util.formatTime(message.time))
+ .opacity(0.2)
+ .marginLeft(1, em)
+ })
+ p(message.text)
+ })
+ .paddingVertical(0.5, em)
+ .marginLeft(fromMe ? 70 : 0, pct)
+ .paddingRight(fromMe ? 10 : 0, pct)
+ .marginRight(fromMe ? 0 : 70, pct)
+ .paddingLeft(fromMe ? 5 : 10, pct)
+ .background(fromMe ? "var(--brown)" : "var(--green)")
+ }
+ } else {
+ LoadingCircle()
+ }
+ })
+ .onAppear(async () => {
+ requestAnimationFrame(() => {
+ this.scrollTop = this.scrollHeight
+ });
+ })
+ .gap(1, em)
+ .position("relative")
+ .overflow("scroll")
+ .height(95, pct)
+ .width(100, pct)
+ .paddingTop(2, em)
+ .paddingBottom(2, em)
+ .backgroundColor("var(--darkbrown)")
+ }
+}
+
+register(MessagesPanel)
\ No newline at end of file
diff --git a/ui/mobile/apps/Messages/MessagesSidebar.js b/ui/mobile/apps/Messages/MessagesSidebar.js
new file mode 100644
index 0000000..453a91d
--- /dev/null
+++ b/ui/mobile/apps/Messages/MessagesSidebar.js
@@ -0,0 +1,73 @@
+class MessagesSidebar extends Shadow {
+ conversations = []
+ selectedConvoID
+ onSelect
+
+ constructor(conversations, selectedConvoID, onSelect) {
+ super()
+ this.conversations = conversations
+ this.selectedConvoID = selectedConvoID
+ this.onSelect = onSelect
+ }
+
+ render() {
+ VStack(() => {
+ this.conversations.forEach((convo, i) => {
+
+ VStack(() => {
+ HStack(() => {
+
+ p(this.makeConvoTitle(convo.between))
+ .textAlign("left")
+ .marginLeft(0.5, inches)
+ .paddingTop(0.2, inches)
+ .width(100, pct)
+ .marginTop(0)
+ .fontSize(1, em)
+ .fontWeight("bold")
+
+ p(util.formatTime(convo.messages.last.time))
+ .paddingTop(0.2, inches)
+ .fontSize(0.8, em)
+ .marginRight(0.1, inches)
+ .color("var(--divider")
+ })
+ .justifyContent("space-between")
+ .marginBottom(0)
+
+ p(convo.messages.last.text)
+ .fontSize(0.8, em)
+ .textAlign("left")
+ .marginLeft(0.5, inches)
+ .marginBottom(2, em)
+ .color("var(--divider)")
+ })
+ .background(convo.id === this.selectedConvoID ? "var(--darkbrown)" : "")
+ .onClick(() => {
+ this.onSelect(i)
+ })
+ })
+ })
+ .minWidth(15, vw)
+ .height(100, vh)
+ .gap(0, em)
+ }
+
+ makeConvoTitle(members) {
+ let membersString = ""
+ for(let i=0; i 2) {
+ membersString += member.firstName
+ } else {
+ membersString += member.firstName + " " + member.lastName
+ }
+ }
+ return membersString
+ }
+}
+
+register(MessagesSidebar)
\ No newline at end of file
diff --git a/ui/mobile/apps/Tasks/Tasks.js b/ui/mobile/apps/Tasks/Tasks.js
new file mode 100644
index 0000000..4b0e733
--- /dev/null
+++ b/ui/mobile/apps/Tasks/Tasks.js
@@ -0,0 +1,153 @@
+css(`
+ tasks- {
+ font-family: 'Bona';
+ }
+
+ tasks- input::placeholder {
+ font-family: 'Bona Nova';
+ font-size: 0.9em;
+ color: var(--accent);
+ }
+
+ input[type="checkbox"] {
+ appearance: none; /* remove default style */
+ -webkit-appearance: none;
+ width: 1em;
+ height: 1em;
+ border: 1px solid var(--accent);
+ }
+
+ input[type="checkbox"]:checked {
+ background-color: var(--red);
+ }
+`)
+
+class Tasks extends Shadow {
+ projects = [
+ {
+ "title": "Blockcatcher",
+ "tasks": {}
+ }
+ ]
+ columns = [
+ {
+ "title": "backlog",
+ "tasks": {}
+ }
+ ]
+
+ render() {
+ ZStack(() => {
+ HStack(() => {
+ VStack(() => {
+ h3("Projects")
+ .marginTop(0)
+ .marginBottom(1, em)
+ .marginLeft(0.4, em)
+
+ if (this.projects.length >= 1) {
+ for(let i = 0; i < this.projects.length; i++) {
+ p(this.projects[i].title)
+ }
+ } else {
+ p("No Projects!")
+ }
+ })
+ .height(100, vh)
+ .paddingLeft(2, em)
+ .paddingRight(2, em)
+ .paddingTop(2, em)
+ .gap(0, em)
+ .borderRight("0.5px solid var(--accent2)")
+
+ HStack(() => {
+ if (this.columns.length >= 1) {
+ for(let i = 0; i < this.columns.length; i++) {
+ p(this.columns[i].name)
+ }
+ } else {
+ p("No Conversations!")
+ }
+ })
+ .height(100, vh)
+ .paddingLeft(2, em)
+ .paddingRight(2, em)
+ .paddingTop(2, em)
+ .gap(0, em)
+ .borderRight("0.5px solid var(--accent2)")
+ })
+ .width(100, "%")
+ .x(0).y(13, vh)
+ .borderTop("0.5px solid var(--accent2)")
+
+ p("0 Items")
+ .position("absolute")
+ .x(50, vw).y(50, vh)
+ .transform("translate(-50%, -50%)")
+
+ HStack(() => {
+ input("Search tasks...", "45vw")
+ .attr({
+ "type": "text"
+ })
+ .fontSize(1.1, em)
+ .paddingLeft(1.3, em)
+ .background("transparent")
+ .border("0.5px solid var(--accent2)")
+ .outline("none")
+ .color("var(--accent)")
+ .borderRadius(10, px)
+
+ button("Search")
+ .marginLeft(2, em)
+ .borderRadius(10, px)
+ .background("transparent")
+ .border("0.5px solid var(--accent2)")
+ .color("var(--accent)")
+ .fontFamily("Bona Nova")
+ .onHover(function (hovering) {
+ if(hovering) {
+ this.style.background = "var(--green)"
+
+ } else {
+ this.style.background = "transparent"
+
+ }
+ })
+
+ button("+ New Task")
+ .width(9, em)
+ .marginLeft(1, em)
+ .borderRadius(10, px)
+ .background("transparent")
+ .border("0.5px solid var(--accent2)")
+ .color("var(--accent)")
+ .fontFamily("Bona Nova")
+ .onHover(function (hovering) {
+ if(hovering) {
+ this.style.background = "var(--green)"
+
+ } else {
+ this.style.background = "transparent"
+
+ }
+ })
+ .onClick((clicking) => {
+ console.log(this, "clicked")
+ })
+
+ })
+ .x(55, vw).y(4, vh)
+ .position("absolute")
+ .transform("translateX(-50%)")
+ })
+ .width(100, "%")
+ .height(100, "%")
+ }
+
+ connectedCallback() {
+ // Optional additional logic
+ }
+}
+
+register(Tasks)
\ No newline at end of file
diff --git a/ui/mobile/components/AppMenu.js b/ui/mobile/components/AppMenu.js
new file mode 100644
index 0000000..7b28205
--- /dev/null
+++ b/ui/mobile/components/AppMenu.js
@@ -0,0 +1,22 @@
+class AppMenu extends Shadow {
+ render() {
+ HStack(() => {
+ img("/_/icons/mail.png", "2em", "2em")
+ img("/_/icons/Column.svg", "2em", "2em")
+ p("S")
+ p("S")
+ p("S")
+ })
+ .borderTop("1px solid black")
+ .height(3, em)
+ .x(0).yBottom(0)
+ .justifyContent("space-between")
+ .paddingHorizontal(2, em)
+ .paddingVertical(1, em)
+ .transform("translateY(-50%)")
+ .width(100, vw)
+ .boxSizing("border-box")
+ }
+}
+
+register(AppMenu)
\ No newline at end of file
diff --git a/ui/mobile/components/Home.js b/ui/mobile/components/Home.js
new file mode 100644
index 0000000..0e97d8e
--- /dev/null
+++ b/ui/mobile/components/Home.js
@@ -0,0 +1,12 @@
+import "./AppMenu.js"
+
+class Home extends Shadow {
+
+ render() {
+ ZStack(() => {
+ AppMenu()
+ })
+ }
+}
+
+register(Home)
\ No newline at end of file
diff --git a/ui/mobile/index.html b/ui/mobile/index.html
new file mode 100644
index 0000000..ca92388
--- /dev/null
+++ b/ui/mobile/index.html
@@ -0,0 +1,14 @@
+
+
+
+ Hyperia
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/mobile/index.js b/ui/mobile/index.js
new file mode 100644
index 0000000..d0acae8
--- /dev/null
+++ b/ui/mobile/index.js
@@ -0,0 +1,8 @@
+import Socket from "./ws/Socket.js"
+import "./components/Home.js"
+
+import util from "./util.js"
+window.util = util
+
+window.Socket = new Socket()
+Home()
\ No newline at end of file
diff --git a/ui/mobile/util.js b/ui/mobile/util.js
new file mode 100644
index 0000000..43c3bd1
--- /dev/null
+++ b/ui/mobile/util.js
@@ -0,0 +1,9 @@
+export default class util {
+ static formatTime(str) {
+ const match = str.match(/-(\d+:\d+):\d+.*(am|pm)/i);
+ if (!match) return null;
+
+ const [_, hourMin, ampm] = match;
+ return hourMin + ampm.toLowerCase();
+ }
+}
\ No newline at end of file
diff --git a/ui/mobile/ws/Connection.js b/ui/mobile/ws/Connection.js
new file mode 100644
index 0000000..69232ff
--- /dev/null
+++ b/ui/mobile/ws/Connection.js
@@ -0,0 +1,62 @@
+class Connection {
+ connectionTries = 0
+ ws;
+ linkCreated;
+ wsStatus;
+
+ constructor(receiveCB) {
+ this.init()
+ this.receiveCB = receiveCB
+ }
+
+ init() {
+ if(window.location.hostname === "localhost") {
+ this.ws = new WebSocket("ws://" + "localhost:3003")
+ } else {
+ this.ws = new WebSocket("wss://" + window.location.hostname + window.location.pathname)
+ }
+ this.ws.addEventListener('open', () => {
+ this.connectionTries = 0
+ console.log("Websocket connection established.");
+ this.ws.addEventListener('message', this.receiveCB)
+ });
+ this.ws.addEventListener("close", () => {
+ this.checkOpen();
+ console.log('Websocket Closed')
+ })
+ }
+
+ async checkOpen() {
+ if (this.ws.readyState === WebSocket.OPEN) {
+ return true
+ } else {
+ await this.sleep(this.connectionTries < 20 ? 5000 : 60000)
+ this.connectionTries++
+ console.log('Reestablishing connection')
+ this.init()
+ }
+ }
+
+ sleep = (time) => {
+ return new Promise(resolve => {
+ setTimeout(resolve, time);
+ });
+ }
+
+ send = (msg) => {
+ console.log("sending")
+ if (this.ws.readyState === WebSocket.OPEN) {
+ this.ws.send(msg);
+ }
+ else if(this.connectionTries === 0) {
+ setTimeout(() => {
+ this.send(msg)
+ }, 100)
+ }
+ else {
+ console.error('No websocket connection: Cannot send message');
+ }
+ }
+}
+
+export default Connection
\ No newline at end of file
diff --git a/ui/mobile/ws/Socket.js b/ui/mobile/ws/Socket.js
new file mode 100644
index 0000000..49357ef
--- /dev/null
+++ b/ui/mobile/ws/Socket.js
@@ -0,0 +1,45 @@
+import Connection from "./Connection.js";
+
+export default class Socket {
+ connection;
+ disabled = true;
+ requestID = 1;
+ pending = new Map();
+
+ constructor() {
+ this.connection = new Connection(this.receive);
+ }
+
+ isOpen() {
+ if(this.connection.checkOpen()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ send(msg) {
+ return new Promise(resolve => {
+ const id = (++this.requestID).toString();
+ this.pending.set(id, resolve);
+ this.connection.send(JSON.stringify({ id, ...msg }));
+ });
+ }
+
+ receive = (event) => {
+ const msg = JSON.parse(event.data);
+ if (msg.id && this.pending.has(msg.id)) {
+ this.pending.get(msg.id)(msg);
+ this.pending.delete(msg.id);
+ return;
+ } else {
+ this.onBroadcast(msg)
+ }
+ }
+
+ onBroadcast(msg) {
+ window.dispatchEvent(new CustomEvent(msg.event, {
+ detail: msg.msg
+ }));
+ }
+}
\ No newline at end of file
diff --git a/ui/public/pages/Events.js b/ui/public/pages/Events.js
index 56891d9..e6e8014 100644
--- a/ui/public/pages/Events.js
+++ b/ui/public/pages/Events.js
@@ -2,7 +2,7 @@ class Events extends Shadow {
events = [
{
- date: `January 2, 2025`,
+ date: `January 23, 2025`,
title: `Hyperia Winter Ball`,
description: `Join us in Austin, Texas for a dance. Live music and drinks will be included.
Admission for men is $50, women are free. Open to the public.`,
location: `Austin, TX`
@@ -20,7 +20,7 @@ class Events extends Shadow {
Stack(() => {
VStack(() => {
- p(`January 2, 2025`)
+ p(`January 23, 2025`)
p(`Hyperia Winter Ball`)
.fontSize(1.2, em)
@@ -29,7 +29,7 @@ class Events extends Shadow {
})
- p(`Join us in Austin, Texas for a great dance, with free drinks and live music.
Admission: $50 for men, women are free.`)
+ p(`Join us in Austin, Texas for a great dance, with free drinks and live music.
Admission: $30 for men, women are free.`)
.marginRight(4, em)
button("Tickets Available Soon")
diff --git a/ui/public/pages/SIgnIn.js b/ui/public/pages/SIgnIn.js
index ec93dad..c766caf 100644
--- a/ui/public/pages/SIgnIn.js
+++ b/ui/public/pages/SIgnIn.js
@@ -1,9 +1,9 @@
class SignIn extends Shadow {
inputStyles(el) {
- console.log(el)
return el
- .border("1px solid var(--accent)")
+ .color("var(--accent)")
+ .border("1px solid var(--accent)")
}
render() {
diff --git a/ui/site/index.css b/ui/site/index.css
deleted file mode 100644
index e69de29..0000000