153 lines
4.7 KiB
JavaScript
153 lines
4.7 KiB
JavaScript
import "./JobsSidebar.js"
|
|
import "./JobsGrid.js"
|
|
import "./JobCard.js"
|
|
import "./JobForm.js"
|
|
import "../../components/SearchBar.js"
|
|
import "../../components/AddButton.js"
|
|
import server from "../../_/code/bridge/server.js"
|
|
|
|
css(`
|
|
jobs- {
|
|
font-family: 'Arial';
|
|
scrollbar-width: none;
|
|
-ms-overflow-style: none;
|
|
}
|
|
|
|
jobs- h1 {
|
|
font-family: 'Bona';
|
|
}
|
|
|
|
jobs- .VStack::-webkit-scrollbar {
|
|
display: none;
|
|
width: 0px;
|
|
height: 0px;
|
|
}
|
|
|
|
jobs- .VStack::-webkit-scrollbar-thumb {
|
|
background: transparent;
|
|
}
|
|
|
|
jobs- .VStack::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
`)
|
|
|
|
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() {
|
|
ZStack(() => {
|
|
|
|
JobForm()
|
|
|
|
VStack(() => {
|
|
HStack(() => {
|
|
SearchBar(this.searchText, "75vw")
|
|
AddButton()
|
|
})
|
|
|
|
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])
|
|
}
|
|
} else {
|
|
h2("No Jobs")
|
|
.color("var(--divider)")
|
|
.fontWeight("bold")
|
|
.marginTop(7.5, em)
|
|
.marginBottom(0.5, em)
|
|
.textAlign("center")
|
|
}
|
|
})
|
|
.overflowY("scroll")
|
|
.gap(0.75, em)
|
|
})
|
|
.boxSizing("border-box")
|
|
.height(100, pct)
|
|
.width(100, pct)
|
|
.onEvent("jobsearch", this.onJobSearch)
|
|
.onEvent("new-job", this.onNewJob)
|
|
})
|
|
}
|
|
|
|
onNewJob = (e) => {
|
|
let newJob = e.detail.job;
|
|
this.jobs.push(newJob)
|
|
this.rerender()
|
|
}
|
|
|
|
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) {
|
|
const fetchedJobs = await server.getJobs(networkId)
|
|
if (this.checkForUpdates(this.jobs, fetchedJobs.data)) {
|
|
this.jobs = fetchedJobs
|
|
this.rerender()
|
|
}
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.getJobs(global.currentNetwork.id)
|
|
}
|
|
|
|
checkForUpdates(currentJobs, fetchedJobs) {
|
|
if (currentJobs.length !== fetchedJobs.length) return true;
|
|
|
|
const currentMap = new Map(currentJobs.map(job => [job.id, job]));
|
|
|
|
for (const fetchedJob of fetchedJobs) {
|
|
const currentJob = currentMap.get(fetchedJob.id);
|
|
|
|
// new job added
|
|
if (!currentJob) return true;
|
|
|
|
// existing job changed
|
|
if (currentJob.updated_at !== fetchedJob.updated_at) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
register(Jobs) |