diff --git a/ui/_/code/shared.css b/ui/_/code/shared.css index 6446588..4eb9571 100644 --- a/ui/_/code/shared.css +++ b/ui/_/code/shared.css @@ -4,11 +4,12 @@ --accent: black; --accent2: black; + --bone: #fff2e7; --parchment: #FEBA7D; --gold: #FEBA7D; --divider: #bb7c36; --green: #0857265c; - --red: #CE0000; + --red: #ff0000; --quillred: #DE3F3F; --brown: #812A18; --darkbrown: #3f0808; diff --git a/ui/desktop/index.js b/ui/desktop/index.js index bb40af5..9bf2636 100644 --- a/ui/desktop/index.js +++ b/ui/desktop/index.js @@ -1,4 +1,4 @@ -import Socket from "./ws/Socket.js" +import Socket from "/_/code/ws/Socket.js" import "./Home.js" import util from "./util.js" diff --git a/ui/mobile/Home.js b/ui/mobile/Home.js new file mode 100644 index 0000000..a5f095e --- /dev/null +++ b/ui/mobile/Home.js @@ -0,0 +1,33 @@ +import "./components/AppMenu.js" +import "./apps/Dashboard/Dashboard.js" +import "./apps/People/People.js" + +class Home extends Shadow { + + render() { + ZStack(() => { + + ZStack(() => { + console.log(window.currentApp) + switch(window.currentApp) { + case "Dashboard": + Dashboard() + break; + + case "People": + People() + break; + } + }) + .onNavigate(function () { + console.log("navigate") + this.rerender() + }) + + AppMenu() + }) + .overflowX("hidden") + } +} + +register(Home) \ No newline at end of file diff --git a/ui/mobile/apps/Dashboard/Dashboard.js b/ui/mobile/apps/Dashboard/Dashboard.js new file mode 100644 index 0000000..0445bc4 --- /dev/null +++ b/ui/mobile/apps/Dashboard/Dashboard.js @@ -0,0 +1,11 @@ +class Dashboard extends Shadow { + render() { + VStack(() => { + console.log(window.currentNetwork) + }) + .width(100, pct) + .height(100, pct) + } +} + +register(Dashboard) \ No newline at end of file diff --git a/ui/mobile/apps/Forum/Forum.js b/ui/mobile/apps/Forum/Forum.js deleted file mode 100644 index aa40038..0000000 --- a/ui/mobile/apps/Forum/Forum.js +++ /dev/null @@ -1,66 +0,0 @@ -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(() => { - VStack(() => { - - ForumPanel() - - input("Message Parchment", "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) - .horizontalAlign("center") - .verticalAlign("end") - }) - .onAppear(() => document.body.style.backgroundColor = "var(--darkbrown)") - .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 deleted file mode 100644 index 9dfdde6..0000000 --- a/ui/mobile/apps/Forum/ForumPanel.js +++ /dev/null @@ -1,88 +0,0 @@ -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 () => { - 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) { - 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 deleted file mode 100644 index 25c6911..0000000 --- a/ui/mobile/apps/Jobs/Jobs.js +++ /dev/null @@ -1,101 +0,0 @@ -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: "Parchment", - 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 deleted file mode 100644 index 2af5d4f..0000000 --- a/ui/mobile/apps/Jobs/JobsGrid.js +++ /dev/null @@ -1,60 +0,0 @@ -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 deleted file mode 100644 index 1546cec..0000000 --- a/ui/mobile/apps/Jobs/JobsSidebar.js +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index 1da5332..0000000 --- a/ui/mobile/apps/Market/Market.js +++ /dev/null @@ -1,105 +0,0 @@ -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: "Parchment", - 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 deleted file mode 100644 index 320f5ec..0000000 --- a/ui/mobile/apps/Market/MarketGrid.js +++ /dev/null @@ -1,140 +0,0 @@ -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 ParchmentMade = params.get("Parchment-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 (ParchmentMade) { - filtered = filtered.filter(item => item.madeIn === "Parchment"); - } - 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 deleted file mode 100644 index 6843fc4..0000000 --- a/ui/mobile/apps/Market/MarketSidebar.js +++ /dev/null @@ -1,85 +0,0 @@ -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": "Parchment-check" - }) - .onChange(this.handleChecked) - label("Parchment-Made") - .attr({ - "for": "Parchment-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 deleted file mode 100644 index 350c880..0000000 --- a/ui/mobile/apps/Messages/Messages.js +++ /dev/null @@ -1,188 +0,0 @@ -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) - .horizontalAlign("center") - .verticalAlign("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) - .verticalAlign("center") - .horizontalAlign("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 deleted file mode 100644 index b608212..0000000 --- a/ui/mobile/apps/Messages/MessagesPanel.js +++ /dev/null @@ -1,56 +0,0 @@ -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 deleted file mode 100644 index 453a91d..0000000 --- a/ui/mobile/apps/Messages/MessagesSidebar.js +++ /dev/null @@ -1,73 +0,0 @@ -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/People/People.js b/ui/mobile/apps/People/People.js new file mode 100644 index 0000000..17f83ea --- /dev/null +++ b/ui/mobile/apps/People/People.js @@ -0,0 +1,7 @@ +class People extends Shadow { + render() { + + } +} + +register(People) \ No newline at end of file diff --git a/ui/mobile/apps/Tasks/Tasks.js b/ui/mobile/apps/Tasks/Tasks.js deleted file mode 100644 index 4b0e733..0000000 --- a/ui/mobile/apps/Tasks/Tasks.js +++ /dev/null @@ -1,153 +0,0 @@ -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 index d533876..2f61693 100644 --- a/ui/mobile/components/AppMenu.js +++ b/ui/mobile/components/AppMenu.js @@ -8,9 +8,8 @@ class AppMenu extends Shadow { } render() { - console.log("rendering") HStack(() => { - img("/_/icons/Column.svg", "1.5em", "1.5em") + img("/_/icons/House.svg", "1.5em", "1.5em") .attr({app: "forum"}) .padding(0.5, em) .borderRadius(10, px) @@ -21,13 +20,12 @@ class AppMenu extends Shadow { if(finished) { this.onNewSelection() } - e.target.style.background = "var(--accent)" - console.log(e.target, e.target.style.background) + e.target.style.background = "var(--bone)" if(finished) { window.navigateTo("/") } }) - img("/_/icons/letter.svg", "1.5em", "1.5em") + img("/_/icons/people.svg", "1.5em", "1.5em") .attr({app: "messages"}) .padding(0.5, em) .borderRadius(10, px) @@ -43,22 +41,6 @@ class AppMenu extends Shadow { window.navigateTo("/messages") } }) - img("/_/icons/jobs.svg", "1.5em", "1.5em") - .attr({app: "jobs"}) - .padding(0.5, em) - .borderRadius(10, px) - .onAppear(function () { - this.style.border = "1px solid black" - }) - .onClick((finished, e) => { - if(finished) { - this.onNewSelection() - } - e.target.style.background = "#9392bb" - if(finished) { - window.navigateTo("/jobs") - } - }) }) .borderTop("1px solid black") .height("auto") @@ -67,7 +49,7 @@ class AppMenu extends Shadow { .zIndex(1) .x(0).yBottom(0) .justifyContent("space-between") - .paddingHorizontal(4, em) + .paddingHorizontal(7, em) .paddingVertical(1, em) .width(100, vw) .boxSizing("border-box") diff --git a/ui/mobile/components/Home.js b/ui/mobile/components/Home.js deleted file mode 100644 index b0dca5e..0000000 --- a/ui/mobile/components/Home.js +++ /dev/null @@ -1,37 +0,0 @@ -import "./AppMenu.js" -import "../apps/Forum/Forum.js" -import "../apps/Messages/Messages.js" -import "../apps/Jobs/Jobs.js" - -class Home extends Shadow { - - render() { - ZStack(() => { - - ZStack(() => { - switch(window.location.pathname) { - case "/": - Forum() - break; - - case "/messages": - Messages() - break; - - case "/jobs": - Jobs() - break; - } - }) - .onNavigate(function () { - console.log("navigate") - this.rerender() - }) - - AppMenu() - }) - .overflowX("hidden") - } -} - -register(Home) \ No newline at end of file diff --git a/ui/mobile/index.html b/ui/mobile/index.html index fe8fbe8..7d7cc78 100644 --- a/ui/mobile/index.html +++ b/ui/mobile/index.html @@ -3,7 +3,7 @@ Parchment - + diff --git a/ui/mobile/index.js b/ui/mobile/index.js index 574b8e8..327f6b3 100644 --- a/ui/mobile/index.js +++ b/ui/mobile/index.js @@ -1,8 +1,120 @@ import Socket from "/_/code/ws/Socket.js" -import "./components/Home.js" +import "./Home.js" import util from "./util.js" window.util = util window.Socket = new Socket() -Home() \ No newline at end of file + +window.currentNetwork = "" +window.currentApp = "" + +async function openNetworkAndApp() { + // console.log("currentApp: ", currentApp, "currentnet: ", currentNetwork, "nfrompath: ", networkFromPath(), "afrompath", appFromPath()) + + if(window.currentNetwork !== networkFromPath()) { + window.currentNetwork = networkFromPath() + const event = new CustomEvent('networkchanged', { + detail: { name: currentNetwork } + }); + window.dispatchEvent(event) + } + + if(!window.currentNetwork.data) { + let appData = await fetch("/app/orgdata/" + window.profile.networks[0].id, {method: "GET"}) + let json = await appData.json() + window.currentNetwork.data = json + } + + console.log("current: ", window.currentApp, "afrompath: ", appFromPath()) + if(window.currentApp !== appFromPath()) { + window.currentApp = appFromPath() + const event = new CustomEvent('appchange', { + detail: { name: window.currentApp } + }); + window.dispatchEvent(event) + } + + if(window.currentNetwork) { // 2 navigates fire on load: 1 initial, and one after the org redirect + document.title = `${window.currentNetwork.abbreviation} | Parchment` + } +} + +window.addEventListener("navigate", openNetworkAndApp) + +window.openApp = function(appName) { + const appUrl = appName.charAt(0).toLowerCase() + appName.slice(1); + let parts = window.location.pathname.split('/').filter(Boolean); + let newPath = "/" + parts[0] + "/" + appUrl + window.navigateTo(newPath) + const event = new CustomEvent('appchange', { + detail: { name: appName } + }); + window.dispatchEvent(event) +} + +window.networkFromPath = function () { + const pathname = window.location.pathname; + const firstSegment = pathname.split('/').filter(Boolean)[0] || ''; + let networks = window.profile?.networks + for(let i = 0; i < networks.length; i++) { + let network = networks[i] + if(network.abbreviation === firstSegment) { + return network + } + } +} + +window.appFromPath = function() { + const pathname = window.location.pathname; + const segments = pathname.split('/').filter(Boolean); + const secondSegment = segments[1] || ""; + const capitalized = secondSegment.charAt(0).toUpperCase() + secondSegment.slice(1); + return capitalized +} + +async function getProfile() { + try { + const res = await fetch("/profile", { + method: "GET", + credentials: "include", + headers: { + "Content-Type": "application/json" + } + }); + + if (!res.ok) throw new Error("Failed to fetch profile"); + + const profile = await res.json(); + console.log("getProfile: ", profile); + window.profile = profile + } catch (err) { + console.error(err); + } +} + +function getInitialNetworkPath() { + let path = "" + let defaultNetwork = window.profile.networks[0] + + if(!networkFromPath()) { + path += (defaultNetwork.abbreviation + "/") + } + + if(!appFromPath()) { + let defaultApp = defaultNetwork.apps[0] + path += defaultApp.toLowerCase() + } + + return path +} + +getProfile().then(async () => { + + if(window.profile.networks.length > 0) { + let path = getInitialNetworkPath() + window.navigateTo(path) + } + + Home() +}) \ No newline at end of file