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
This commit is contained in:
2026-03-14 17:01:06 -04:00
parent cc8b5035fe
commit e85ffc66f8
24 changed files with 403 additions and 94 deletions

View File

@@ -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("<b>Description: </b>" + " " + 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)

124
src/apps/Events/Events.js Normal file
View File

@@ -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)

39
src/apps/Jobs/JobCard.js Normal file
View File

@@ -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("<b>Company: </b>" + " " + this.job.company)
p("<b>Salary: </b>" + " " + this.job.salary)
p("<b>Description: </b>" + " " + 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)

View File

@@ -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)
}
}

View File

@@ -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}`;
}
}