People app and navigation + fixes

Index.js
- Fixed issue where incorrect pathname was set while not part of an organization.
- onNavigate(), fetchAppData(), getDefaultNetworkName(), and getDefaultAppName() all modified to account for user not being part of an organization (default path set to /my/dashboard)
- onNavigate() modified to properly set defaults for currentNetwork and currentApp, and modified to fix issue where app would crash when attempting to access nonexistent 'this.currentNetwork.data'
- onNavigate() now correctly switches currentApp

Home.js
- Changed ZStack to a VStack
- Replaced Jobs switch case with People
- Adjusted styling for AppMenu() and VStack height values
- Changed .onNavigate() from function() to () => {} for correct this binding
- !!!(TEMP FIX)!!!: Added extra rerender() call in an .onClick() after .onNavigate()

AppMenu()
- Modified app icons to be highlighted when active
- Changed Forum's app icon to redirect from "/" to "/dashboard"
- Removed fixed styling to account for Home's new responsive VStack layout

People.js
- Added People.js

Messages.js
- Fixed missing 'global." before Socket.send
- Changed 'vh' height values to 'pct' to account for AppMenu() at bottom
- Fixed misnamed modifiers

Forum.js
- Adjusted styling
- Changed 'vh' height values to 'pct' to account for AppMenu() at bottom

styles.css
- Added missing custom color vars
This commit is contained in:
2026-02-02 04:34:26 -05:00
parent a68f35faf5
commit b20ce6da06
7 changed files with 161 additions and 29 deletions

View File

@@ -3,6 +3,7 @@ import "./components/AppMenu.js"
import "./apps/Forum/Forum.js" import "./apps/Forum/Forum.js"
import "./apps/Messages/Messages.js" import "./apps/Messages/Messages.js"
import "./apps/Jobs/Jobs.js" import "./apps/Jobs/Jobs.js"
import "./apps/People/People.js"
class Home extends Shadow { class Home extends Shadow {
@@ -10,7 +11,7 @@ class Home extends Shadow {
ZStack(() => { ZStack(() => {
Sidebar() Sidebar()
ZStack(() => { VStack(() => {
switch(global.currentApp) { switch(global.currentApp) {
case "Dashboard": case "Dashboard":
Forum() Forum()
@@ -19,20 +20,25 @@ class Home extends Shadow {
case "Messages": case "Messages":
Messages() Messages()
break; break;
case "Jobs": case "People":
Jobs() People()
break; break;
} }
AppMenu()
}) })
.onNavigate(function () { .height(100, pct)
.onNavigate(() => {
console.log("navigate") console.log("navigate")
this.rerender() this.rerender()
}) })
// .onClick(() => {
AppMenu() // this.rerender()
// })
}) })
.overflowX("hidden") .overflowX("hidden")
.height(100, vh)
} }
} }

View File

@@ -3,6 +3,14 @@
--accent: #60320c; --accent: #60320c;
--text: #340000; --text: #340000;
--yellow: #f1f3c3; --yellow: #f1f3c3;
--bone: #fff2e7;
--gold: #FEBA7D;
--divider: #bb7c36;
--green: #0857265c;
--red: #ff0000;
--quillred: #DE3F3F;
--brown: #812A18;
--darkbrown: #3f0808;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {

View File

@@ -56,12 +56,14 @@ class Forum extends Shadow {
}) })
}) })
.gap(0.5, em) .gap(0.5, em)
.boxSizing("border-box")
.width(100, pct) .width(100, pct)
.height(100, vh) .height(100, pct)
.horizontalAlign("center") .horizontalAlign("center")
.verticalAlign("end") .verticalAlign("end")
}) })
.backgroundColor("var(--main)") .backgroundColor("var(--main)")
.boxSizing("border-box")
.width(100, pct) .width(100, pct)
.height(100, pct) .height(100, pct)
} }

View File

@@ -76,7 +76,7 @@ class Messages extends Shadow {
.verticalAlign("end") .verticalAlign("end")
}) })
.onAppear(async () => { .onAppear(async () => {
let res = await Socket.send({app: "MESSAGES", operation: "GET"}) let res = await global.Socket.send({app: "MESSAGES", operation: "GET"})
if(!res) console.error("failed to get messages") if(!res) console.error("failed to get messages")
if(res.msg.length > 0 && this.conversations.length === 0) { if(res.msg.length > 0 && this.conversations.length === 0) {
@@ -93,9 +93,9 @@ class Messages extends Shadow {
this.rerender() this.rerender()
}) })
}) })
.width(100, "%") .width(100, pct)
.height(87, vh) .height(87, pct)
.x(0).y(13, vh) .x(0).y(13, pct)
VStack(() => { VStack(() => {
p("Add Message") p("Add Message")
@@ -121,15 +121,15 @@ class Messages extends Shadow {
}) })
.gap(1, em) .gap(1, em)
.alignVertical("center") .verticalAlign("center")
.alignHorizontal("center") .horizontalAlign("center")
.backgroundColor("black") .backgroundColor("black")
.border("1px solid var(--accent)") .border("1px solid var(--accent)")
.position("fixed") .position("fixed")
.x(50, vw).y(50, vh) .x(50, vw).y(50, pct)
.center() .center()
.width(60, vw) .width(60, vw)
.height(60, vh) .height(60, pct)
.display("none") .display("none")
.attr({id: "addPanel"}) .attr({id: "addPanel"})
@@ -176,12 +176,13 @@ class Messages extends Shadow {
}) })
}) })
.x(55, vw).y(4, vh) .x(55, vw).y(4, pct)
.position("absolute") .position("absolute")
.transform("translateX(-50%)") .transform("translateX(-50%)")
}) })
.width(100, "%") .boxSizing("border-box")
.height(100, "%") .height(100, pct)
.width(100, pct)
} }
} }

108
src/apps/People/People.js Normal file
View File

@@ -0,0 +1,108 @@
css(`
people- {
font-family: 'Arial';
}
people- h1 {
font-family: 'Bona';
}
people- p {
color: var(--accent);
}
people- p b {
color: var(--darkbrown);
}
`)
class People extends Shadow {
people = "";
constructor() {
super()
this.people = global.currentNetwork.data.members;
}
render() {
VStack(() => {
h1("People")
.color("var(--quillred)")
.textAlign("center")
if (this.people == "") {
LoadingCircle()
} else if (this.people.length > 0) {
for (let i = 0; i < this.people.length; i++) {
HStack(() => {
HStack(() => { })
.boxSizing("border-box")
.height(3.5, em)
.width(3.5, em)
.padding(0.5, em)
.border("1px solid var(--accent)")
.borderRadius(3, px)
.background("var(--bone)")
VStack(() => {
h3(this.people[i].firstName + " " + this.people[i].lastName)
.color("var(--brown)")
.fontSize(1.2, em)
.fontWeight("bold")
.marginVertical(0, em)
p("<b>Member since: </b>" + " " + this.convertDate(this.people[i].created))
})
.verticalAlign("center")
.gap(0.5, em)
})
.height(3.5, em)
.padding(0.75, em)
.gap(1, em)
.borderBottom("1px solid var(--divider)")
.borderTop(i == 0 ? "1px solid var(--divider)" : "")
}
} else {
h2("No Members")
.color("var(--brown)")
.fontWeight("bold")
.marginTop(7.5, em)
.marginBottom(0.5, em)
.textAlign("center")
p("Invite people to this network!")
.textAlign("center")
.color("var(--darkbrown)")
}
})
.position("relative")
.boxSizing("border-box")
.background("var(--bone)")
.paddingVertical(1, em)
.height(100, pct)
.width(100, pct)
}
convertDate(rawDate) {
const date = rawDate.split("-", 1)[0]; // "01.31.2026
const [mm, dd, yyyy] = date.split(".").map(Number);
const months = [
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
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 `${months[mm - 1]} ${ordinal(dd)}, ${yyyy}`;
}
}
register(People)

View File

@@ -14,49 +14,48 @@ class AppMenu extends Shadow {
.attr({app: "forum"}) .attr({app: "forum"})
.padding(0.5, em) .padding(0.5, em)
.borderRadius(10, px) .borderRadius(10, px)
.background(global.currentApp === "Dashboard" ? "var(--accent)" : "transparent")
.onClick((finished, e) => { .onClick((finished, e) => {
if(finished) { if(finished) {
this.onNewSelection() this.onNewSelection()
} }
e.target.style.background = "var(--accent)" e.target.style.background = "var(--accent)"
console.log(e.target, e.target.style.background)
if(finished) { if(finished) {
window.navigateTo("/") window.navigateTo("/dashboard")
} }
}) })
img("/_/icons/letter.svg", "1.5em", "1.5em") img("/_/icons/letter.svg", "1.5em", "1.5em")
.attr({app: "messages"}) .attr({app: "messages"})
.padding(0.5, em) .padding(0.5, em)
.borderRadius(10, px) .borderRadius(10, px)
.background(global.currentApp === "Messages" ? "rgb(112 150 114)" : "transparent")
.onClick((finished, e) => { .onClick((finished, e) => {
if(finished) { if(finished) {
this.onNewSelection() this.onNewSelection()
} }
e.target.style.background = "rgb(112 150 114)"
if(finished) { if(finished) {
window.navigateTo("/messages") window.navigateTo("/messages")
} }
}) })
img("/_/icons/jobs.svg", "1.5em", "1.5em") img("/_/icons/jobs.svg", "1.5em", "1.5em")
.attr({app: "jobs"}) .attr({app: "people"})
.padding(0.5, em) .padding(0.5, em)
.borderRadius(10, px) .borderRadius(10, px)
.background(global.currentApp === "People" ? "#9392bb" : "transparent")
.onClick((finished, e) => { .onClick((finished, e) => {
if(finished) { if(finished) {
this.onNewSelection() this.onNewSelection()
} }
e.target.style.background = "#9392bb"
if(finished) { if(finished) {
window.navigateTo("/jobs") window.navigateTo(`/people`)
} }
}) })
}) })
.borderTop("1px solid black") .borderTop("1px solid black")
.height("auto") .height("auto")
.position('fixed')
.background("var(--main)") .background("var(--main)")
.zIndex(1) .zIndex(1)
.x(0).yBottom(0)
.justifyContent("space-between") .justifyContent("space-between")
.paddingHorizontal(4, em) .paddingHorizontal(4, em)
.paddingVertical(1, em) .paddingVertical(1, em)

View File

@@ -21,6 +21,7 @@ let Global = class {
async fetchAppData() { async fetchAppData() {
let personalSpace = this.currentNetwork === this.profile let personalSpace = this.currentNetwork === this.profile
if (personalSpace) { return {} }
let appData = await fetch(`/api/${personalSpace ? "my" : "org"}data/` + this.currentNetwork.id, {method: "GET"}) let appData = await fetch(`/api/${personalSpace ? "my" : "org"}data/` + this.currentNetwork.id, {method: "GET"})
let json = await appData.json() let json = await appData.json()
return json return json
@@ -32,9 +33,12 @@ let Global = class {
let selectedApp = this.appFromPath() let selectedApp = this.appFromPath()
if(!selectedNetwork) { if(!selectedNetwork) {
if(this.profile.networks.length > 0) { if (!this.currentNetwork || this.currentNetwork === this.profile) {
let path = `/${this.getDefaultNetworkName()}/${this.getDefaultAppName()}` let path = `/${this.getDefaultNetworkName()}/${this.getDefaultAppName()}`
history.replaceState({}, '', path) history.replaceState({}, '', path)
} else {
let path = `/${this.currentNetwork.abbreviation}${window.location.pathname}`
history.replaceState({}, '', path)
} }
} else if(!selectedApp) { } else if(!selectedApp) {
if(this.currentNetwork === window.profile) { if(this.currentNetwork === window.profile) {
@@ -50,6 +54,7 @@ let Global = class {
let networkChanged = this.currentNetwork !== selectedNetwork let networkChanged = this.currentNetwork !== selectedNetwork
let appChanged = this.currentApp !== selectedApp let appChanged = this.currentApp !== selectedApp
if(networkChanged) { if(networkChanged) {
console.log("onNavigate: network changed ->", selectedNetwork?.abbreviation)
this.currentNetwork = selectedNetwork this.currentNetwork = selectedNetwork
this.currentApp = selectedApp this.currentApp = selectedApp
const event = new CustomEvent('networkchange', { const event = new CustomEvent('networkchange', {
@@ -58,11 +63,12 @@ let Global = class {
window.dispatchEvent(event) window.dispatchEvent(event)
} }
if(!this.currentNetwork.data) { if(!this.currentNetwork?.data) {
this.currentNetwork.data = await this.fetchAppData() this.currentNetwork.data = await this.fetchAppData()
} }
if(appChanged && !networkChanged) { if(appChanged && !networkChanged) {
console.log("onNavigate: app changed ->", selectedApp, "\n")
this.currentApp = selectedApp this.currentApp = selectedApp
const event = new CustomEvent('appchange', { const event = new CustomEvent('appchange', {
detail: { name: this.currentApp } detail: { name: this.currentApp }
@@ -80,11 +86,13 @@ let Global = class {
getDefaultNetworkName() { getDefaultNetworkName() {
let defaultNetwork = this.profile.networks[0] let defaultNetwork = this.profile.networks[0]
if (!defaultNetwork) { return "my"; }
return defaultNetwork.abbreviation return defaultNetwork.abbreviation
} }
getDefaultAppName() { getDefaultAppName() {
let defaultNetwork = this.profile.networks[0] let defaultNetwork = this.profile.networks[0]
if (!defaultNetwork) { return this.profile.apps[0].toLowerCase(); }
return defaultNetwork.apps[0].toLowerCase() return defaultNetwork.apps[0].toLowerCase()
} }