mirror of
https://github.com/wavetermdev/docusaurus-og.git
synced 2026-08-05 13:46:35 -07:00
feat: implement job list
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
SectionHeader,
|
||||
TimelineItem,
|
||||
ShowcaseCard,
|
||||
JobList,
|
||||
} from '../components/mdx'
|
||||
|
||||
<Hero size="large">
|
||||
@@ -352,3 +353,4 @@ import {
|
||||
Build on Waku
|
||||
</CallToActionButton>
|
||||
</Box>
|
||||
<JobList jobBoard="nomos" />
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import React, { useState } from 'react'
|
||||
import useFetchJobs, { JobBoard, Job } from './useFetchJobs'
|
||||
|
||||
type Props = {
|
||||
jobBoard: JobBoard
|
||||
titleFilter?: string
|
||||
}
|
||||
|
||||
export const JobList: React.FC<Props> = ({ jobBoard, titleFilter = '' }) => {
|
||||
const { data, error, fetchJobs } = useFetchJobs()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const handleFetchJobs = async () => {
|
||||
setIsLoading(true)
|
||||
await fetchJobs([jobBoard], titleFilter)
|
||||
setIsLoading(false)
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
handleFetchJobs()
|
||||
}, [jobBoard, titleFilter])
|
||||
|
||||
if (isLoading) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div>Error: {error.message}</div>
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <div>No data</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Job List</h2>
|
||||
<ul>
|
||||
{data.jobs.map((job: Job, index: number) => (
|
||||
<li key={index}>
|
||||
<a
|
||||
href={job.absolute_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{job.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './JobList'
|
||||
@@ -0,0 +1,108 @@
|
||||
import { useState } from 'react'
|
||||
|
||||
// Inspired by:
|
||||
// https://github.com/acid-info/rnd-dynamic-list/blob/master/react/useFetchJobs.js
|
||||
|
||||
const jobBoards = [
|
||||
'acidtest',
|
||||
'logos',
|
||||
'status',
|
||||
'nimbus',
|
||||
'codex',
|
||||
'nomos',
|
||||
'statusnetwork',
|
||||
'ift',
|
||||
'vac',
|
||||
'waku',
|
||||
] as const
|
||||
|
||||
export type JobBoard = (typeof jobBoards)[number]
|
||||
|
||||
const jobBoardMappings: Record<JobBoard, string> = {
|
||||
acidtest: 'testacidinfo',
|
||||
logos: 'logos',
|
||||
status: 'status72',
|
||||
nimbus: 'nimbus',
|
||||
codex: 'codex',
|
||||
nomos: 'nomos',
|
||||
statusnetwork: 'thestatusnetwork',
|
||||
ift: 'instituteoffreetechnologies',
|
||||
vac: 'vac',
|
||||
waku: 'waku',
|
||||
}
|
||||
|
||||
export type Job = {
|
||||
absolute_url: string
|
||||
data_compliance?: {
|
||||
type: string
|
||||
requires_consent: boolean
|
||||
requires_processing_consent: boolean
|
||||
requires_retention_consent: boolean
|
||||
retention_period: null | string // Assuming retention_period can be a string or null.
|
||||
}[]
|
||||
internal_job_id: number
|
||||
location?: {
|
||||
name: string
|
||||
}
|
||||
metadata?: any
|
||||
id: number
|
||||
updated_at: string
|
||||
requisition_id: string
|
||||
title: string
|
||||
}
|
||||
|
||||
type JobData = {
|
||||
jobs: Job[]
|
||||
meta: {
|
||||
total: number
|
||||
}
|
||||
} | null
|
||||
|
||||
type UseFetchJobs = {
|
||||
data: JobData
|
||||
error: any
|
||||
fetchJobs: (jobBoardsToFetch: JobBoard[], titleFilter: string) => void
|
||||
}
|
||||
|
||||
export const useFetchJobs = (): UseFetchJobs => {
|
||||
const [data, setData] = useState<JobData>(null)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
const fetchJobs = async (jobBoardsToFetch: JobBoard[], titleFilter) => {
|
||||
try {
|
||||
const resultsPerBoard: Partial<Record<JobBoard, string>> = {}
|
||||
|
||||
for (let board of jobBoardsToFetch) {
|
||||
const response = await fetch(
|
||||
`https://boards-api.greenhouse.io/v1/boards/${jobBoardMappings[board]}/jobs`,
|
||||
)
|
||||
const jobData = await response.json()
|
||||
resultsPerBoard[board] = jobData.jobs
|
||||
}
|
||||
|
||||
let jobs = Object.values(resultsPerBoard).flat() as unknown as Job[]
|
||||
|
||||
if (titleFilter) {
|
||||
jobs = jobs.filter(
|
||||
(job) => job.title && job.title.includes(titleFilter),
|
||||
)
|
||||
}
|
||||
|
||||
setData({ jobs, meta: { total: jobs.length } })
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
setError(err)
|
||||
} else if (typeof err === 'string') {
|
||||
setError(new Error(err))
|
||||
} else {
|
||||
setError(new Error('Unknown error'))
|
||||
}
|
||||
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
return { data, error, fetchJobs }
|
||||
}
|
||||
|
||||
export default useFetchJobs
|
||||
@@ -24,3 +24,4 @@ export * from './Showcase'
|
||||
export * from './ShowcaseCard'
|
||||
export * from './SocialCard'
|
||||
export * from './TimelineItem'
|
||||
export * from './JobList'
|
||||
|
||||
Reference in New Issue
Block a user