From e85ffc66f8e4eb3debdaa31644feed2045d7acd9 Mon Sep 17 00:00:00 2001 From: matiasc18 Date: Sat, 14 Mar 2026 17:01:06 -0400 Subject: [PATCH] Jobs + Events Pages - Added Jobs/Events pages, need to set up with backend once complete - Added missing icons and fixed incorrect icons - Made AppMenu icons highlight when selected - Removed Settings from AppMenu - Fixed undefined data in People --- package.json | 6 +- src/_/code/shared.css | 22 ++++- src/_/icons/events.svg | 3 + src/_/icons/eventslight.svg | 3 + src/_/icons/eventslightselected.svg | 3 + src/_/icons/home.svg | 4 + src/_/icons/homelightselected.svg | 6 +- src/_/icons/jobslight.svg | 5 + src/_/icons/jobslightselected.svg | 5 + src/_/icons/logowhite.svg | 7 ++ src/_/icons/pin.svg | 1 + src/_/icons/pinlight.svg | 1 + src/_/icons/settings.svg | 3 + src/_/icons/settingslight.svg | 3 + src/_/icons/settingslightselected.svg | 3 + src/_/icons/time.svg | 3 + src/_/icons/timelight.svg | 3 + src/apps/Events/EventCard.js | 72 ++++++++++++++ src/apps/Events/Events.js | 124 +++++++++++++++++++++++++ src/apps/Jobs/JobCard.js | 39 ++++++++ src/apps/Jobs/Jobs.js | 129 ++++++++++++-------------- src/apps/People/People.js | 23 +++-- src/components/AppMenu.js | 20 ++-- src/components/AppWindow.js | 9 ++ 24 files changed, 403 insertions(+), 94 deletions(-) create mode 100644 src/_/icons/events.svg create mode 100644 src/_/icons/eventslight.svg create mode 100644 src/_/icons/eventslightselected.svg create mode 100644 src/_/icons/home.svg create mode 100644 src/_/icons/jobslight.svg create mode 100644 src/_/icons/jobslightselected.svg create mode 100644 src/_/icons/logowhite.svg create mode 100644 src/_/icons/pin.svg create mode 100644 src/_/icons/pinlight.svg create mode 100644 src/_/icons/settings.svg create mode 100644 src/_/icons/settingslight.svg create mode 100644 src/_/icons/settingslightselected.svg create mode 100644 src/_/icons/time.svg create mode 100644 src/_/icons/timelight.svg create mode 100644 src/apps/Events/EventCard.js create mode 100644 src/apps/Events/Events.js create mode 100644 src/apps/Jobs/JobCard.js diff --git a/package.json b/package.json index 883bcb0..60af171 100644 --- a/package.json +++ b/package.json @@ -13,13 +13,13 @@ "preview": "vite preview" }, "dependencies": { - "@capacitor/camera": "latest", - "@capacitor/core": "latest", + "@capacitor/camera": "^7.0.2", + "@capacitor/core": "^7.4.4", "@capacitor/geolocation": "^7.1.5", "@capacitor/google-maps": "^7.2.0", "@capacitor/haptics": "^7.0.3", "@capacitor/ios": "^7.4.4", - "@capacitor/splash-screen": "latest" + "@capacitor/splash-screen": "^7.0.3" }, "devDependencies": { "@capacitor/cli": "latest", diff --git a/src/_/code/shared.css b/src/_/code/shared.css index 014dde8..7e16cf5 100644 --- a/src/_/code/shared.css +++ b/src/_/code/shared.css @@ -14,14 +14,23 @@ --darkgrey: #5c4646; --home-src: /_/icons/home.svg; - --home-selected-src: /_/icons/homeselected.svg; + --home-selected-src: /_/icons/homelightselected.svg; --people-src: /_/icons/people.svg; - --people-selected-src: /_/icons/peopleselected.svg; + --people-selected-src: /_/icons/peoplelightselected.svg; + --settings-src: /_/icons/settings.svg; + --settings-selected-src: /_/icons/settingslightselected.svg; + --events-src: /_/icons/events.svg; + --events-selected-src: /_/icons/eventslightselected.svg; + --jobs-src: /_/icons/jobs.svg; + --jobs-selected-src: /_/icons/jobslightselected.svg; --column-src: /_/icons/column2.svg; --nodes-src: /_/icons/nodes.svg; --forum-src: /_/icons/forum.svg; + --pin-src: /_/icons/pin.svg; + --time-src: /_/icons/time.svg; + --top-inset: env(safe-area-inset-top, 0px); --bottom-inset: env(safe-area-inset-bottom, 0px); } @@ -37,10 +46,19 @@ --home-selected-src: /_/icons/homelightselected.svg; --people-src: /_/icons/peoplelight.svg; --people-selected-src: /_/icons/peoplelightselected.svg; + --settings-src: /_/icons/settingslight.svg; + --settings-selected-src: /_/icons/settingslightselected.svg; + --events-src: /_/icons/eventslight.svg; + --events-selected-src: /_/icons/eventslightselected.svg; + --jobs-src: /_/icons/jobslight.svg; + --jobs-selected-src: /_/icons/jobslightselected.svg; --column-src: /_/icons/column2.svg; --nodes-src: /_/icons/nodes.svg; --forum-src: /_/icons/forum.svg; + + --pin-src: /_/icons/pinlight.svg; + --time-src: /_/icons/timelight.svg; } } diff --git a/src/_/icons/events.svg b/src/_/icons/events.svg new file mode 100644 index 0000000..bf3ce43 --- /dev/null +++ b/src/_/icons/events.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/_/icons/eventslight.svg b/src/_/icons/eventslight.svg new file mode 100644 index 0000000..61be66a --- /dev/null +++ b/src/_/icons/eventslight.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/_/icons/eventslightselected.svg b/src/_/icons/eventslightselected.svg new file mode 100644 index 0000000..616ea25 --- /dev/null +++ b/src/_/icons/eventslightselected.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/_/icons/home.svg b/src/_/icons/home.svg new file mode 100644 index 0000000..c7d0035 --- /dev/null +++ b/src/_/icons/home.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/_/icons/homelightselected.svg b/src/_/icons/homelightselected.svg index a948cfa..788ae2f 100644 --- a/src/_/icons/homelightselected.svg +++ b/src/_/icons/homelightselected.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/src/_/icons/jobslight.svg b/src/_/icons/jobslight.svg new file mode 100644 index 0000000..16c87ed --- /dev/null +++ b/src/_/icons/jobslight.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/_/icons/jobslightselected.svg b/src/_/icons/jobslightselected.svg new file mode 100644 index 0000000..14887f7 --- /dev/null +++ b/src/_/icons/jobslightselected.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/_/icons/logowhite.svg b/src/_/icons/logowhite.svg new file mode 100644 index 0000000..e6278eb --- /dev/null +++ b/src/_/icons/logowhite.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/_/icons/pin.svg b/src/_/icons/pin.svg new file mode 100644 index 0000000..e662f1d --- /dev/null +++ b/src/_/icons/pin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/_/icons/pinlight.svg b/src/_/icons/pinlight.svg new file mode 100644 index 0000000..a4b91eb --- /dev/null +++ b/src/_/icons/pinlight.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/_/icons/settings.svg b/src/_/icons/settings.svg new file mode 100644 index 0000000..90ed89e --- /dev/null +++ b/src/_/icons/settings.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/_/icons/settingslight.svg b/src/_/icons/settingslight.svg new file mode 100644 index 0000000..4e082ee --- /dev/null +++ b/src/_/icons/settingslight.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/_/icons/settingslightselected.svg b/src/_/icons/settingslightselected.svg new file mode 100644 index 0000000..0a845e1 --- /dev/null +++ b/src/_/icons/settingslightselected.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/_/icons/time.svg b/src/_/icons/time.svg new file mode 100644 index 0000000..30a9b5b --- /dev/null +++ b/src/_/icons/time.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/_/icons/timelight.svg b/src/_/icons/timelight.svg new file mode 100644 index 0000000..615be77 --- /dev/null +++ b/src/_/icons/timelight.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/apps/Events/EventCard.js b/src/apps/Events/EventCard.js new file mode 100644 index 0000000..f94fc85 --- /dev/null +++ b/src/apps/Events/EventCard.js @@ -0,0 +1,72 @@ +import util from "../../util" + +class EventCard extends Shadow { + constructor(event) { + super() + this.event = event + } + + render() { + VStack(() => { + h3(this.event.title) + .color("var(--brown)") + .fontSize(1.2, em) + .fontWeight("bold") + .marginVertical(0, em) + + HStack(() => { + img(util.cssVariable("pin-src"), "1.3em") + p(this.event.location) + }) + .gap(0.3, em) + .verticalAlign("center") + + HStack(() => { + img(util.cssVariable("time-src"), "1.2em") + p(this.convertDate(this.event.time)) + }) + .gap(0.4, em) + .verticalAlign("center") + + p("Description: " + " " + this.event.description) + }) + .maxHeight(12.5, em) + .padding(0.75, em) + .gap(0, em) + .borderBottom("1px solid var(--divider)") + .verticalAlign("center") + .gap(0.5, em) + } + + convertDate(rawDate) { + const parsed = new Date(rawDate); + + if (isNaN(parsed.getTime())) return rawDate; + + const month = parsed.toLocaleString("en-US", { month: "long", timeZone: "UTC" }); + const day = parsed.getUTCDate(); + const year = parsed.getUTCFullYear(); + + const hours24 = parsed.getUTCHours(); + const minutes = parsed.getUTCMinutes(); + + const hours12 = hours24 % 12 || 12; + const ampm = hours24 >= 12 ? "PM" : "AM"; + const paddedMinutes = String(minutes).padStart(2, "0"); + + const ordinal = (n) => { + const mod100 = n % 100; + if (mod100 >= 11 && mod100 <= 13) return `${n}th`; + switch (n % 10) { + case 1: return `${n}st`; + case 2: return `${n}nd`; + case 3: return `${n}rd`; + default: return `${n}th`; + } + }; + + return `${month} ${ordinal(day)}, ${year} at ${hours12}:${paddedMinutes} ${ampm}`; + } +} + +register(EventCard) \ No newline at end of file diff --git a/src/apps/Events/Events.js b/src/apps/Events/Events.js new file mode 100644 index 0000000..ac1203d --- /dev/null +++ b/src/apps/Events/Events.js @@ -0,0 +1,124 @@ +import "../../components/LoadingCircle.js" +import "./EventCard.js" + +css(` + events- { + font-family: 'Arial'; + } + + events- h1 { + font-family: 'Bona'; + } + + events- p { + color: var(--accent); + } + + events- p b { + color: var(--darkbrown); + } +`) + +class Events extends Shadow { + events = [ + { + title: "Austin Chapter Lead", + description: "This is the descriptio lets try a longer one agaiin just to see what it would look like? mayeb even longer bc that was pretty short now that i see it. maybe 2 sentences if possible or more.", + location: "1234 location", + time: "2026-01-13 13:41:41.0722" + } + ] + + constructor() { + super() + // this.events = global.currentNetwork.data.events; + } + + render() { + VStack(() => { + h1("Events") + .color("var(--quillred)") + .textAlign("center") + .marginBottom(0) + h3(global.currentNetwork.name) + .color("var(--quillred)") + .textAlign("center") + .margin(0) + .fontFamily("Bona") + + input("Search (coming soon!)", "80%") + .attr({ + "type": "text", + "disabled": "true" + }) + .paddingVertical(0.75, em) + .boxSizing("border-box") + .paddingHorizontal(1, em) + .color("var(--accent)") + .background("#fff1dd") + .marginTop(0.25, em) + .marginBottom(0.5, em) + .border("1px solid black") + .borderRadius(100, px) + .fontFamily("Arial") + .fontSize(1, em) + .outline("none") + .cursor("not-allowed") + + if (this.events == "") { + LoadingCircle() + } else if (this.events.length > 0) { + for (let i = 0; i < this.events.length; i++) { + EventCard(this.events[i]) + .borderTop(i == 0 ? "1px solid var(--divider)" : "") + } + } else { + h2("No Events") + .color("var(--brown)") + .fontWeight("bold") + .marginTop(7.5, em) + .marginBottom(0.5, em) + .textAlign("center") + } + }) + .position("relative") + .boxSizing("border-box") + .paddingVertical(1, em) + .horizontalAlign("center") + .gap(0.5, em) + .height(100, pct) + .width(100, pct) + } + + convertDate(rawDate) { + const parsed = new Date(rawDate); + + if (isNaN(parsed.getTime())) return rawDate; + + const month = parsed.toLocaleString("en-US", { month: "long", timeZone: "UTC" }); + const day = parsed.getUTCDate(); + const year = parsed.getUTCFullYear(); + + const hours24 = parsed.getUTCHours(); + const minutes = parsed.getUTCMinutes(); + + const hours12 = hours24 % 12 || 12; + const ampm = hours24 >= 12 ? "PM" : "AM"; + const paddedMinutes = String(minutes).padStart(2, "0"); + + const ordinal = (n) => { + const mod100 = n % 100; + if (mod100 >= 11 && mod100 <= 13) return `${n}th`; + switch (n % 10) { + case 1: return `${n}st`; + case 2: return `${n}nd`; + case 3: return `${n}rd`; + default: return `${n}th`; + } + }; + + return `${month} ${ordinal(day)}, ${year} at ${hours12}:${paddedMinutes} ${ampm}`; + } +} + +register(Events) \ No newline at end of file diff --git a/src/apps/Jobs/JobCard.js b/src/apps/Jobs/JobCard.js new file mode 100644 index 0000000..c94e2f1 --- /dev/null +++ b/src/apps/Jobs/JobCard.js @@ -0,0 +1,39 @@ +import util from "../../util.js" + +class JobCard extends Shadow { + constructor(job) { + super() + this.job = job + } + + render() { + VStack(() => { + h3(this.job.title) + .color("var(--brown)") + .fontSize(1.2, em) + .fontWeight("bold") + .marginVertical(0, em) + + HStack(() => { + img(util.cssVariable("pin-src"), "1.3em") + p(this.job.location) + }) + .gap(0.3, em) + .verticalAlign("center") + + p("Company: " + " " + this.job.company) + p("Salary: " + " " + this.job.salary) + p("Description: " + " " + this.job.description) + }) + .width(100, pct) + .maxHeight(12.5, em) + .padding(0.75, em) + .gap(0, em) + .borderBottom("1px solid var(--divider)") + .textAlign("left") + .gap(0.5, em) + .boxSizing("border-box") + } +} + +register(JobCard) \ No newline at end of file diff --git a/src/apps/Jobs/Jobs.js b/src/apps/Jobs/Jobs.js index bb72598..ace77b0 100644 --- a/src/apps/Jobs/Jobs.js +++ b/src/apps/Jobs/Jobs.js @@ -1,27 +1,22 @@ import "./JobsSidebar.js" import "./JobsGrid.js" +import "./JobCard.js" css(` jobs- { + font-family: 'Arial'; + } + + jobs- h1 { font-family: 'Bona'; } - jobs- input::placeholder { - font-family: 'Bona Nova'; - font-size: 0.9em; + jobs- p { 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); + jobs- p b { + color: var(--darkbrown); } `) @@ -29,72 +24,66 @@ class Jobs extends Shadow { jobs = [ { title: "Austin Chapter Lead", + description: "This is the description", salary: "1% of Local Revenue", company: "Hyperia", - city: "Austin", - state: "TX" + location: "1234 location" } ] render() { - ZStack(() => { - HStack(() => { - JobsSidebar() - - JobsGrid(this.jobs) - }) - .width(100, "%") - .x(0).y(13, vh) + VStack(() => { + h1("Jobs") + .color("var(--quillred)") + .textAlign("center") + .marginBottom(0.25, em) + h3(global.currentNetwork.name) + .color("var(--quillred)") + .textAlign("center") + .margin(0) + .fontFamily("Bona") - 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") + input("Search (coming soon!)", "80%") + .attr({ + "type": "text", + "disabled": "true" + }) + .paddingVertical(0.75, em) + .boxSizing("border-box") + .paddingHorizontal(1, em) + .color("var(--accent)") + .background("#fff1dd") + .marginTop(0.75, em) + .marginBottom(1, em) + .border("1px solid black") + .borderRadius(100, px) + .fontFamily("Arial") + .fontSize(1, em) + .outline("none") + .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%)") + if (this.jobs == "") { + LoadingCircle() + } else if (this.jobs.length > 0) { + for (let i = 0; i < this.jobs.length; i++) { + JobCard(this.jobs[i]) + .borderTop(i == 0 ? "1px solid var(--divider)" : "") + } + } else { + h2("No Jobs") + .color("var(--brown)") + .fontWeight("bold") + .marginTop(7.5, em) + .marginBottom(0.5, em) + .textAlign("center") + } }) - .width(100, "%") - .height(100, "%") - } - - connectedCallback() { - // Optional additional logic + .position("relative") + .boxSizing("border-box") + .paddingVertical(1, em) + .horizontalAlign("center") + .height(100, pct) + .width(100, pct) } } diff --git a/src/apps/People/People.js b/src/apps/People/People.js index f42f180..d030d80 100644 --- a/src/apps/People/People.js +++ b/src/apps/People/People.js @@ -29,6 +29,13 @@ class People extends Shadow { h1("People") .color("var(--quillred)") .textAlign("center") + .marginBottom(0.25, em) + h3(global.currentNetwork.name) + .color("var(--quillred)") + .textAlign("center") + .margin(0) + .marginBottom(0.5, em) + .fontFamily("Bona") if (this.people == "") { LoadingCircle() @@ -45,7 +52,7 @@ class People extends Shadow { .background("var(--bone)") VStack(() => { - h3(this.people[i].firstName + " " + this.people[i].lastName) + h3(this.people[i].first_name + " " + this.people[i].last_name) .color("var(--brown)") .fontSize(1.2, em) .fontWeight("bold") @@ -81,13 +88,13 @@ class People extends Shadow { } convertDate(rawDate) { - const date = rawDate.split("-", 1)[0]; // "01.31.2026 - const [mm, dd, yyyy] = date.split(".").map(Number); + const parsed = new Date(rawDate); - const months = [ - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December" - ]; + if (isNaN(parsed.getTime())) return rawDate; + + const month = parsed.toLocaleString("en-US", { month: "long", timeZone: "UTC" }); + const day = parsed.getUTCDate(); + const year = parsed.getUTCFullYear(); const ordinal = (n) => { const mod100 = n % 100; @@ -100,7 +107,7 @@ class People extends Shadow { } }; - return `${months[mm - 1]} ${ordinal(dd)}, ${yyyy}`; + return `${month} ${ordinal(day)}, ${year}`; } } diff --git a/src/components/AppMenu.js b/src/components/AppMenu.js index 32e328e..025750b 100644 --- a/src/components/AppMenu.js +++ b/src/components/AppMenu.js @@ -5,14 +5,22 @@ class AppMenu extends Shadow { selected = "" images = { - "Dashboard": {src: "home-src"}, - "Messages": {src: "letter-src"}, - "People": {src: "people-src"} + "Dashboard": {src: ["home-src", "home-selected-src"]}, + "People": {src: ["people-src", "people-selected-src"]}, + "Settings": {src: ["settings-src", "settings-selected-src"]}, + "Events": {src: ["events-src", "events-selected-src"]}, + "Jobs": {src: ["jobs-src", "jobs-selected-src"]} } onNewSelection() { this.$$("img").forEach((image) => { image.style.borderBottom = "1px solid transparent" + const app = image.attributes.app.value + if (app === global.currentApp()) { + image.src = util.cssVariable(this.images[app].src[1]) + } else { + image.src = util.cssVariable(this.images[app].src[0]) + } }) } @@ -22,16 +30,16 @@ class AppMenu extends Shadow { let currentNetwork = global.currentNetwork for(let i = 0; i < currentNetwork.apps.length; i++) { let app = currentNetwork.apps[i] - console.log(app) - img(util.cssVariable(this.images[app].src), "1.3em") + if (app === "Settings") continue; + img(util.cssVariable(global.currentApp() === app ? this.images[app].src[1] : this.images[app].src[0]), "1.3em") .attr({app: app}) .padding(0.5, em) .borderBottom(global.currentApp() === app ? "1px solid var(--text)" : "1px solid transparent") .onTouch(async (done, e) => { if(done) { - this.onNewSelection() e.target.style.borderBottom = "1px solid var(--text)" global.openApp(app) + this.onNewSelection() await Haptics.impact({ style: ImpactStyle.Light }); } }) diff --git a/src/components/AppWindow.js b/src/components/AppWindow.js index cd6850c..6b1e9f8 100644 --- a/src/components/AppWindow.js +++ b/src/components/AppWindow.js @@ -2,6 +2,7 @@ import "../apps/Forum/Forum.js" import "../apps/Messages/Messages.js" import "../apps/Jobs/Jobs.js" import "../apps/People/People.js" +import "../apps/Events/Events.js" class AppWindow extends Shadow { render() { @@ -19,6 +20,14 @@ class AppWindow extends Shadow { case "People": People() break; + + case "Jobs": + Jobs() + break; + + case "Events": + Events() + break; } }) .height(100, pct)