diff --git a/src/apps/Events/Events.js b/src/apps/Events/Events.js index a36d117..ce3c2b2 100644 --- a/src/apps/Events/Events.js +++ b/src/apps/Events/Events.js @@ -31,19 +31,36 @@ css(` `) class Events extends Shadow { + static searchableKeys = ['title', 'description', 'location']; + constructor() { super() this.events = global.currentNetwork.data.events; + this.searchedEvents = []; + this.searchText = ""; } render() { VStack(() => { - SearchBar() + SearchBar(this.searchText) VStack(() => { if (!this.events || this.events == []) { LoadingCircle() + } else if (this.searchText) { + if (this.searchedEvents.length > 0) { + for (let i = 0; i < this.searchedEvents.length; i++) { + EventCard(this.searchedEvents[i]) + } + } else { + h2("Could not find any events with your search criteria.") + .color("var(--divider)") + .fontWeight("bold") + .marginTop(7.5, em) + .marginBottom(0.5, em) + .textAlign("center") + } } else if (this.events.length > 0) { for (let i = 0; i < this.events.length; i++) { EventCard(this.events[i]) @@ -63,6 +80,22 @@ class Events extends Shadow { .boxSizing("border-box") .height(100, pct) .width(100, pct) + .onEvent("eventsearch", this.onEventSearch) + } + + onEventSearch = (e) => { + let searchText = e.detail.searchText.toLowerCase().trim(); + if (!searchText) { + this.searchedEvents = []; + } else { + this.searchedEvents = this.events.filter(event => + Events.searchableKeys.some(key => + String(event[key]).toLowerCase().includes(searchText) + ) + ); + } + this.searchText = searchText + this.rerender() } async getEvents(networkId) { diff --git a/src/apps/Jobs/Jobs.js b/src/apps/Jobs/Jobs.js index c77d9d1..bcb8ca1 100644 --- a/src/apps/Jobs/Jobs.js +++ b/src/apps/Jobs/Jobs.js @@ -32,9 +32,13 @@ css(` `) class Jobs extends Shadow { + static searchableKeys = ['title', 'description', 'location', 'company', 'salary_period', 'salary_number']; + constructor() { super() this.jobs = global.currentNetwork.data.jobs; + this.searchedJobs = []; + this.searchText = ""; // for mainting searchText after re-render } render() { @@ -42,11 +46,24 @@ class Jobs extends Shadow { // JobForm() - SearchBar() + SearchBar(this.searchText) VStack(() => { if (!this.jobs || this.jobs == []) { LoadingCircle() + } else if (this.searchText) { + if (this.searchedJobs.length > 0) { + for (let i = 0; i < this.searchedJobs.length; i++) { + JobCard(this.searchedJobs[i]) + } + } else { + h2("Could not find any jobs with your search criteria.") + .color("var(--divider)") + .fontWeight("bold") + .marginTop(7.5, em) + .marginBottom(0.5, em) + .textAlign("center") + } } else if (this.jobs.length > 0) { for (let i = 0; i < this.jobs.length; i++) { JobCard(this.jobs[i]) @@ -66,6 +83,26 @@ class Jobs extends Shadow { .boxSizing("border-box") .height(100, pct) .width(100, pct) + .onEvent("jobsearch", this.onJobSearch) + } + + onJobSearch = (e) => { + let searchText = e.detail.searchText.toLowerCase().trim(); + if (!searchText) { + this.searchedJobs = []; + } else { + this.searchedJobs = this.jobs.filter(job => + Jobs.searchableKeys.some(key => { + if (key === "salary_number" || key === "salary_period") { + return String(job["salary_number"]).toLowerCase().includes(searchText.replace(/\/.*$/, '').replace(/[,$]/g, '')) && String(job["salary_period"]).toLowerCase().includes(searchText.replace(/^[^/]*\/?/, '')); + } else { + return String(job[key]).toLowerCase().includes(searchText); + } + }) + ); + } + this.searchText = searchText + this.rerender() } async getJobs(networkId) { diff --git a/src/components/AppWindow.js b/src/components/AppWindow.js index e43cbfe..3117196 100644 --- a/src/components/AppWindow.js +++ b/src/components/AppWindow.js @@ -31,6 +31,7 @@ class AppWindow extends Shadow { break; } }) + .overflowY("scroll") .onNavigate(() => { this.rerender() }) diff --git a/src/components/SearchBar.js b/src/components/SearchBar.js index e25595a..9804124 100644 --- a/src/components/SearchBar.js +++ b/src/components/SearchBar.js @@ -5,47 +5,79 @@ css(` `) class SearchBar extends Shadow { - render() { - HStack(() => { - input("Search", "80%") - .attr({ - "type": "text" - }) - .paddingVertical(0.75, em) - .boxSizing("border-box") - .paddingHorizontal(1, em) - .background("var(--searchbackground)") - .color("gray") - .marginBottom(1, em) - .border("1px solid color-mix(in srgb, var(--accent) 60%, transparent)") - .borderRadius(100, px) - .fontFamily("Arial") - .fontSize(1, em) - .outline("none") - .cursor("not-allowed") - .onTouch(function (start) { - if(start) { - this.style.backgroundColor = "var(--accent)" - } else { - this.style.backgroundColor = "var(--searchbackground)" - } - }) + constructor(searchText) { + super() + this.searchText = searchText + } - p("+") - .fontWeight("bolder") - .paddingVertical(0.75, em) - .boxSizing("border-box") - .paddingHorizontal(1, em) - .background("var(--searchbackground)") - .color("var(--accent)") - .marginBottom(1, em) - .border("1px solid var(--accent)") - .borderRadius(15, px) - }) + + render() { + form(() => { + HStack(() => { + input("Search", "80%") + .attr({ name: "searchText", type: "text" }) + .attr({ value: this.searchText ? this.searchText : "" }) + .paddingVertical(0.75, em) + .boxSizing("border-box") + .paddingHorizontal(1, em) + .background("var(--searchbackground)") + .color("gray") + .marginBottom(1, em) + .border("1px solid color-mix(in srgb, var(--accent) 60%, transparent)") + .borderRadius(100, px) + .fontFamily("Arial") + .fontSize(1, em) + .outline("none") + .cursor("not-allowed") + .onTouch(function (start) { + if (start) { + this.style.backgroundColor = "var(--accent)" + } else { + this.style.backgroundColor = "var(--searchbackground)" + } + }) + // .onInput(async (e) => { + // e.preventDefault(); + // console.log("helloooo submitted") + // }) // can be used for live updating + + p("+") + .fontWeight("bolder") + .paddingVertical(0.75, em) + .boxSizing("border-box") + .paddingHorizontal(1, em) + .background("var(--searchbackground)") + .color("var(--accent)") + .marginBottom(1, em) + .border("1px solid var(--accent)") + .borderRadius(15, px) + }) .width(100, pct) .horizontalAlign("center") .verticalAlign("center") .gap(0.5, em) + }) + .onSubmit(async (e) => { + e.preventDefault(); + const data = new FormData(e.target); + this.dispatchSearchEvent(data.get("searchText")) + }) + } + + dispatchSearchEvent(searchText) { + const app = global.currentApp(); + switch (app) { + case "Jobs": + window.dispatchEvent(new CustomEvent('jobsearch', { + detail: { searchText: searchText } + })); + break; + case "Events": + window.dispatchEvent(new CustomEvent('eventsearch', { + detail: { searchText: searchText } + })); + break; + } } }