From ebeb0079318cfb3753929d2fe2670f3ce32d481c Mon Sep 17 00:00:00 2001 From: jongomez Date: Wed, 25 Oct 2023 15:24:02 +0100 Subject: [PATCH] fix: use the department API endpoint instead - working version --- .../docusaurus-playground/src/pages/index.mdx | 4 +- .../components/mdx/JobLists/JobLists.tsx | 77 --- .../mdx/JobLists/SingleJobBoardList.tsx | 47 -- .../client/components/mdx/JobLists/index.ts | 1 - .../mdx/JobLists/jobListsDummyData.ts | 145 ----- .../components/mdx/JobLists/useFetchJobs.ts | 152 ----- .../JobsPerDepartment.scss} | 22 +- .../JobsPerDepartment/JobsPerDepartment.tsx | 66 +++ .../SingleDepartmentJobs.tsx | 49 ++ .../components/mdx/JobsPerDepartment/index.ts | 1 + .../jobsPerDepartmentDummyData.ts | 555 ++++++++++++++++++ .../mdx/JobsPerDepartment/useFetchJobs.ts | 162 +++++ .../src/client/components/mdx/index.ts | 2 +- 13 files changed, 847 insertions(+), 436 deletions(-) delete mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/JobLists.tsx delete mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/SingleJobBoardList.tsx delete mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/index.ts delete mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/jobListsDummyData.ts delete mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/useFetchJobs.ts rename packages/logos-docusaurus-theme/src/client/components/mdx/{JobLists/JobLists.scss => JobsPerDepartment/JobsPerDepartment.scss} (62%) create mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/JobsPerDepartment.tsx create mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/SingleDepartmentJobs.tsx create mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/index.ts create mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/jobsPerDepartmentDummyData.ts create mode 100644 packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/useFetchJobs.ts diff --git a/packages/docusaurus-playground/src/pages/index.mdx b/packages/docusaurus-playground/src/pages/index.mdx index 20c25d3..7d4abbb 100644 --- a/packages/docusaurus-playground/src/pages/index.mdx +++ b/packages/docusaurus-playground/src/pages/index.mdx @@ -18,7 +18,7 @@ import { SectionHeader, TimelineItem, ShowcaseCard, - JobLists, + JobsPerDepartment, } from '../components/mdx' @@ -353,4 +353,4 @@ import { Build on Waku - + diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/JobLists.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/JobLists.tsx deleted file mode 100644 index ac34029..0000000 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/JobLists.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { Typography } from '@acid-info/lsd-react' -import { SingleJobBoardList } from './SingleJobBoardList' -import useFetchJobs, { JobBoard, JobsPerBoard } from './useFetchJobs' -import React from 'react' -import { jobListsDummyData } from './jobListsDummyData' - -const hasJobs = (jobsPerBoard: JobsPerBoard): boolean => { - if (!jobsPerBoard) return false - let jobFound = false - - Object.keys(jobsPerBoard).forEach((board) => { - if (jobsPerBoard[board]!.jobs.length > 0) { - jobFound = true - return - } - }) - - return jobFound -} - -type JobListsProps = React.HTMLAttributes & { - jobBoard: JobBoard - titleFilter?: string - fetchAll?: boolean - useDummyData?: boolean -} - -export const JobLists: React.FC = ({ - jobBoard, - titleFilter = '', - fetchAll = false, - useDummyData = false, - ...props -}) => { - const { data, error, isLoading } = useFetchJobs( - [jobBoard], - fetchAll, - titleFilter, - useDummyData ? jobListsDummyData : null, - ) - - console.log('data', data) - console.log('error', error) - console.log('isLoading', isLoading) - - if (isLoading) { - return
Loading...
- } - - if (error) { - return
Error fetching data
- } - - if (!data || !hasJobs(data)) { - return
No job openings to show
- } - - const returnedJobBoards = Object.keys(data) - - return ( -
- - Current job openings - - {returnedJobBoards.map((board) => { - const jobDataForBoard = data[board] - return ( - - ) - })} -
- ) -} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/SingleJobBoardList.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/SingleJobBoardList.tsx deleted file mode 100644 index 416291e..0000000 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/SingleJobBoardList.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { Typography } from '@acid-info/lsd-react' -import { Job, JobBoard } from './useFetchJobs' -import React from 'react' -import { IconExternalLink } from '@logos-theme/components/Icon' -import './JobLists.scss' - -type SingleJobBoardListProps = { - jobBoard: JobBoard - jobs: Job[] -} - -export const SingleJobBoardList: React.FC = ({ - jobBoard, - jobs, -}) => { - return ( -
- - {jobBoard} - - -
- ) -} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/index.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/index.ts deleted file mode 100644 index 8dd0638..0000000 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './JobLists' diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/jobListsDummyData.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/jobListsDummyData.ts deleted file mode 100644 index a3be806..0000000 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/jobListsDummyData.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { JobsPerBoard } from './useFetchJobs' - -// Only for dev purposes - prevents making multiple requests to the API while developing. -export const jobListsDummyData: JobsPerBoard = { - nomos: { - jobs: [ - { - absolute_url: 'https://boards.greenhouse.io/nomos/jobs/5453089', - data_compliance: [ - { - type: 'gdpr', - requires_consent: false, - requires_processing_consent: false, - requires_retention_consent: false, - retention_period: null, - }, - ], - internal_job_id: 2315608, - location: { - name: 'Remote (Worldwide)', - }, - metadata: null, - id: 5453089, - updated_at: '2023-10-20T07:06:31-04:00', - requisition_id: 'PROV-Nom-5', - title: 'Applied Network Researcher', - }, - ], - meta: { - total: 1, - }, - }, - waku: { - jobs: [ - { - absolute_url: 'https://boards.greenhouse.io/waku/jobs/5453096', - data_compliance: [ - { - type: 'gdpr', - requires_consent: false, - requires_processing_consent: false, - requires_retention_consent: false, - retention_period: null, - }, - ], - internal_job_id: 2055187, - location: { - name: 'Remote (Worldwide)', - }, - metadata: null, - id: 5453096, - updated_at: '2023-10-20T07:00:46-04:00', - requisition_id: 'PROV-Sec-2', - title: 'Protocol Engineer', - }, - { - absolute_url: 'https://boards.greenhouse.io/waku/jobs/5453098', - data_compliance: [ - { - type: 'gdpr', - requires_consent: false, - requires_processing_consent: false, - requires_retention_consent: false, - retention_period: null, - }, - ], - internal_job_id: 1830496, - location: { - name: 'Remote, Worldwide', - }, - metadata: null, - id: 5453098, - updated_at: '2023-10-20T07:01:13-04:00', - requisition_id: 'PROV-Sec-3', - title: 'Protocol Researcher (Distributed Systems)', - }, - { - absolute_url: 'https://boards.greenhouse.io/waku/jobs/5453099', - data_compliance: [ - { - type: 'gdpr', - requires_consent: false, - requires_processing_consent: false, - requires_retention_consent: false, - retention_period: null, - }, - ], - internal_job_id: 2584916, - location: { - name: 'Remote (Worldwide)', - }, - metadata: null, - id: 5453099, - updated_at: '2023-10-20T07:01:37-04:00', - requisition_id: 'SDK-2', - title: 'Software Engineer (Chat SDK)', - }, - { - absolute_url: 'https://boards.greenhouse.io/waku/jobs/5453102', - data_compliance: [ - { - type: 'gdpr', - requires_consent: false, - requires_processing_consent: false, - requires_retention_consent: false, - retention_period: null, - }, - ], - internal_job_id: 2656108, - location: { - name: 'Remote (Worldwide)', - }, - metadata: null, - id: 5453102, - updated_at: '2023-10-20T07:02:20-04:00', - requisition_id: 'PROV-Wak-13', - title: 'Software Engineer Distributed Systems Testing', - }, - { - absolute_url: 'https://boards.greenhouse.io/waku/jobs/5453103', - data_compliance: [ - { - type: 'gdpr', - requires_consent: false, - requires_processing_consent: false, - requires_retention_consent: false, - retention_period: null, - }, - ], - internal_job_id: 2694724, - location: { - name: 'Remote (Worldwide)', - }, - metadata: null, - id: 5453103, - updated_at: '2023-10-20T13:12:19-04:00', - requisition_id: 'WAK-BD-1', - title: 'Technical Business Development Lead ', - }, - ], - meta: { - total: 5, - }, - }, -} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/useFetchJobs.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/useFetchJobs.ts deleted file mode 100644 index 7993f0e..0000000 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/useFetchJobs.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { useEffect, useRef, useState } from 'react' - -/* -const allJobBoards = [ - 'testacidinfo', // Acid Test job board - 'logos', - 'nimbus', - 'codex', - 'nomos', - 'thestatusnetwork', - 'instituteoffreetechnologies', // aka IFT - 'vac', - 'waku', -] as const - -*/ - -const allJobBoards = ['codex', 'nomos', 'vac', 'waku'] as const - -export type JobBoard = string - -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 - }[] - 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 - -export type JobsPerBoard = Record | null - -type UseFetchJobsReturn = { - data: JobsPerBoard - error: Error | null - isLoading: boolean -} - -const parseJobs = (rawJobs: Job[], titleFilter?: string): JobData => { - const jobs = titleFilter - ? rawJobs.filter((job) => job.title?.includes(titleFilter)) - : rawJobs - - return { jobs, meta: { total: jobs.length } } -} - -export const useFetchJobs = ( - jobBoardsToFetch: JobBoard[] = [], - fetchAllJobBoards: boolean = false, - titleFilter: string = '', - dummyResponse: JobsPerBoard = null, -): UseFetchJobsReturn => { - const [data, setData] = useState(null) - const [error, setError] = useState(null) - const [isLoading, setIsLoading] = useState(false) - const isMounted = useRef(true) - - const fetchJobs = async (): Promise<{ - jobsPerBoard: JobsPerBoard - errorData: Error | null - }> => { - try { - if (dummyResponse) { - return { jobsPerBoard: dummyResponse, errorData: null } - } - - const jobsPerBoard: JobsPerBoard = {} - - if (fetchAllJobBoards) { - const promises = allJobBoards.map((boardName) => - fetch( - `https://boards-api.greenhouse.io/v1/boards/${boardName}/jobs`, - ).then((response) => response.json()), - ) - - const allResults = await Promise.all(promises) - allResults.forEach((result, index) => { - const currentBoard = allJobBoards[index] - - if (!currentBoard) { - throw new Error('No current board found for ' + result) - } - - jobsPerBoard[currentBoard] = parseJobs(result.jobs, titleFilter) - }) - } else { - for (let board of jobBoardsToFetch) { - const response = await fetch( - `https://boards-api.greenhouse.io/v1/boards/${board}/jobs`, - ) - const jobData = await response.json() - jobsPerBoard[board] = parseJobs(jobData.jobs, titleFilter) - } - } - - return { - jobsPerBoard, - errorData: null, - } - } catch (err) { - const errorData = - err instanceof Error - ? err - : typeof err === 'string' - ? new Error(err) - : new Error('Unknown error') - - console.error(err) - return { jobsPerBoard: null, errorData } - } - } - - useEffect(() => { - if (isLoading) return - - setIsLoading(true) - fetchJobs().then(({ jobsPerBoard, errorData }) => { - // We should not update state if the component is unmounted. - if (!isMounted.current) return - - if (jobsPerBoard) setData(jobsPerBoard) - if (errorData) setError(errorData) - setIsLoading(false) - }) - - return () => { - isMounted.current = false - } - }, []) - - return { data, error, isLoading } -} - -export default useFetchJobs diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/JobLists.scss b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/JobsPerDepartment.scss similarity index 62% rename from packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/JobLists.scss rename to packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/JobsPerDepartment.scss index 215677d..c2e7d88 100644 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/JobLists/JobLists.scss +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/JobsPerDepartment.scss @@ -1,43 +1,43 @@ @use '../../../css/utils'; @use '../../../css/lsd'; -.mdx-jl__header { +.mdx-jpd__header { margin-bottom: 40px; margin-top: 16px; } -.mdx-jl__single-job-board-container { +.mdx-jpd__single-job-department-container { border-top: 1px solid rgb(var(--lsd-border-primary)); padding-top: 8px; } -.mdx-jl__board-title { - font-size: 12px; - line-height: 16px; +.mdx-jpd__department-title { + font-size: 12px !important; + line-height: 16px !important; } -.mdx-jl__job-title-container { +.mdx-jpd__job-title-container { display: flex; align-items: center; padding-bottom: 8px; } -.mdx-jl__external-link-icon { +.mdx-jpd__external-link-icon { margin-left: 8px; } -.mdx-jl__job-list { +.mdx-jpd__job-list { list-style-type: none; padding: 8px 0 24px 0; margin: 0; } -.mdx-jl__job-list-item { +.mdx-jpd__job-list-item { padding: 14px 0; } -.mdx-jl__job-link { +.mdx-jpd__job-link { display: block; width: fit-content; text-decoration: none; @@ -45,7 +45,7 @@ &:hover { text-decoration: none; - .mdx-jl__job-title { + .mdx-jpd__job-title { text-decoration: underline; } } diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/JobsPerDepartment.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/JobsPerDepartment.tsx new file mode 100644 index 0000000..43395f2 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/JobsPerDepartment.tsx @@ -0,0 +1,66 @@ +import { Typography } from '@acid-info/lsd-react' +import { SingleDepartmentJobs } from './SingleDepartmentJobs' +import useFetchJobs, { JobDepartmentArray } from './useFetchJobs' +import React from 'react' +import { jobsPerDepartmentDummyData } from './jobsPerDepartmentDummyData' + +const hasJobs = (jobsPerDepartment: JobDepartmentArray): boolean => { + if (!jobsPerDepartment) return false + + // Check if there's any department that has at least one job + let jobFound = jobsPerDepartment.some((department) => { + return department.jobs && department.jobs.length > 0 + }) + + return jobFound +} + +type JobsPerDepartmentProps = React.HTMLAttributes & { + jobBoard: string + titleFilter?: string + fetchAll?: boolean + useDummyData?: boolean +} + +export const JobsPerDepartment: React.FC = ({ + jobBoard, + titleFilter = '', + fetchAll = false, + useDummyData = false, + ...props +}) => { + const { data, error, isLoading } = useFetchJobs( + jobBoard, + titleFilter, + useDummyData ? jobsPerDepartmentDummyData : null, + ) + + console.log('data', data) + console.log('error', error) + console.log('isLoading', isLoading) + + if (isLoading) { + return
Loading...
+ } + + if (error) { + return
Error fetching data
+ } + + if (!data || !hasJobs(data)) { + return
No job openings to show
+ } + + return ( +
+ + Current job openings + + {data.map((department) => { + return ( + + ) + })} +
+ ) +} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/SingleDepartmentJobs.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/SingleDepartmentJobs.tsx new file mode 100644 index 0000000..e4c504b --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/SingleDepartmentJobs.tsx @@ -0,0 +1,49 @@ +import { Typography } from '@acid-info/lsd-react' +import { Job, JobDepartmentData } from './useFetchJobs' +import React from 'react' +import { IconExternalLink } from '@logos-theme/components/Icon' +import './JobsPerDepartment.scss' + +type SingleDepartmentJobsProps = { + department: JobDepartmentData +} + +export const SingleDepartmentJobs: React.FC = ({ + department, +}) => { + if (!department.jobs || department.jobs.length === 0) { + return null + } + + return ( +
+ + {department.name} + + +
+ ) +} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/index.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/index.ts new file mode 100644 index 0000000..68907d2 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/index.ts @@ -0,0 +1 @@ +export * from './JobsPerDepartment' diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/jobsPerDepartmentDummyData.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/jobsPerDepartmentDummyData.ts new file mode 100644 index 0000000..ee967da --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/jobsPerDepartmentDummyData.ts @@ -0,0 +1,555 @@ +import { JobDepartmentArray } from './useFetchJobs' + +// Only for dev purposes - prevents making multiple requests to the API while developing. +export const jobsPerDepartmentDummyData: JobDepartmentArray = [ + { + id: 87842, + name: 'App', + parent_id: 43806, + child_ids: [87847, 87852, 87850, 87848, 45530, 87849], + jobs: [], + }, + { + id: 54504, + name: 'Brand Design Studio', + parent_id: null, + child_ids: [], + jobs: [], + }, + { + id: 45532, + name: 'Business Development', + parent_id: null, + child_ids: [], + jobs: [], + }, + { + id: 87841, + name: 'Codex', + parent_id: 43806, + child_ids: [], + jobs: [ + { + absolute_url: 'https://jobs.status.im/?gh_jid=5329400', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2662332, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5329400, + updated_at: '2023-10-13T09:40:03-04:00', + requisition_id: 'Cod-6', + title: 'Technical Business Development Lead [Codex]', + }, + ], + }, + { + id: 84549, + name: 'Communications', + parent_id: null, + child_ids: [], + jobs: [ + { + absolute_url: 'https://jobs.status.im/?gh_jid=5276254', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2645076, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5276254, + updated_at: '2023-10-19T03:08:59-04:00', + requisition_id: 'PROV-Com-16', + title: 'Motion Designer', + }, + ], + }, + { + id: 45531, + name: 'Design', + parent_id: null, + child_ids: [], + jobs: [], + }, + { + id: 87847, + name: 'Desktop', + parent_id: 87842, + child_ids: [], + jobs: [], + }, + { + id: 87852, + name: 'Documentation', + parent_id: 87842, + child_ids: [], + jobs: [], + }, + { + id: 45547, + name: 'Engineering ', + parent_id: null, + child_ids: [], + jobs: [ + { + absolute_url: 'https://jobs.status.im/?gh_jid=5419957', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2693761, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5419957, + updated_at: '2023-10-24T07:30:00-04:00', + requisition_id: 'APP-QA-2', + title: 'Desktop QA Engineer ', + }, + { + absolute_url: 'https://jobs.status.im/?gh_jid=3694379', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2055210, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 3694379, + updated_at: '2023-10-24T16:23:12-04:00', + requisition_id: 'BACK-1050', + title: 'Senior C++ Qt/QML developer for blockchain app', + }, + { + absolute_url: 'https://jobs.status.im/?gh_jid=3702173', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2058858, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 3702173, + updated_at: '2023-10-24T16:21:54-04:00', + requisition_id: '93', + title: 'Senior Mobile ClojureScript UI Developer ', + }, + ], + }, + { + id: 49925, + name: 'Finance', + parent_id: 87845, + child_ids: [], + jobs: [], + }, + { + id: 87854, + name: 'Infrastructure', + parent_id: 43806, + child_ids: [], + jobs: [], + }, + { + id: 87853, + name: 'Insights', + parent_id: 87845, + child_ids: [], + jobs: [], + }, + { + id: 87850, + name: 'Keycard', + parent_id: 87842, + child_ids: [], + jobs: [], + }, + { + id: 145838, + name: 'Leadership', + parent_id: null, + child_ids: [], + jobs: [ + { + absolute_url: 'https://jobs.status.im/?gh_jid=5447463', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2704948, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5447463, + updated_at: '2023-10-24T09:07:22-04:00', + requisition_id: 'LEAD-1', + title: 'Chief of Staff [whole ecosystem]', + }, + ], + }, + { + id: 74156, + name: 'Legal', + parent_id: 87845, + child_ids: [], + jobs: [], + }, + { + id: 91698, + name: 'Logos', + parent_id: null, + child_ids: [], + jobs: [], + }, + { + id: 43807, + name: 'Marketing', + parent_id: null, + child_ids: [], + jobs: [], + }, + { + id: 87848, + name: 'Mobile', + parent_id: 87842, + child_ids: [], + jobs: [], + }, + { + id: 87843, + name: 'Nimbus', + parent_id: 43806, + child_ids: [], + jobs: [ + { + absolute_url: 'https://jobs.status.im/?gh_jid=5370820', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2679527, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5370820, + updated_at: '2023-10-19T03:05:07-04:00', + requisition_id: 'LIDO-1', + title: 'Senior DevOps Engineer (Blockchain)', + }, + ], + }, + { + id: 144866, + name: 'Nomos', + parent_id: 43806, + child_ids: [], + jobs: [ + { + absolute_url: 'https://jobs.status.im/?gh_jid=5433423', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2315608, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5433423, + updated_at: '2023-10-12T11:20:52-04:00', + requisition_id: 'PROV-Nom-5', + title: 'Applied Network Researcher', + }, + ], + }, + { + id: 45548, + name: 'People Operations', + parent_id: 87845, + child_ids: [], + jobs: [], + }, + { + id: 45530, + name: 'Product Design', + parent_id: 87842, + child_ids: [], + jobs: [], + }, + { + id: 90941, + name: 'Program Management', + parent_id: null, + child_ids: [], + jobs: [], + }, + { + id: 43806, + name: 'Research & Development', + parent_id: null, + child_ids: [ + 87842, 87841, 87854, 87843, 144866, 87846, 87981, 87847, 87852, 87850, + 87848, 45530, 87849, + ], + jobs: [], + }, + { + id: 87851, + name: 'Security', + parent_id: 87845, + child_ids: [], + jobs: [], + }, + { + id: 87845, + name: 'Services', + parent_id: null, + child_ids: [49925, 87853, 74156, 45548, 87851], + jobs: [], + }, + { + id: 91697, + name: 'Status App ', + parent_id: null, + child_ids: [], + jobs: [], + }, + { + id: 54783, + name: 'Technical Writing ', + parent_id: null, + child_ids: [], + jobs: [], + }, + { + id: 87846, + name: 'Vac', + parent_id: 43806, + child_ids: [], + jobs: [ + { + absolute_url: 'https://jobs.status.im/?gh_jid=4460860', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2331302, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 4460860, + updated_at: '2023-10-04T05:13:53-04:00', + requisition_id: 'PROV-zkV-1', + title: 'Zero Knowledge Research Engineer ', + }, + ], + }, + { + id: 87981, + name: 'Waku', + parent_id: 43806, + child_ids: [], + jobs: [ + { + absolute_url: 'https://jobs.status.im/?gh_jid=5456032', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2707470, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5456032, + updated_at: '2023-10-23T11:40:19-04:00', + requisition_id: 'WAK-GL-1', + title: 'Growth Lead', + }, + { + absolute_url: 'https://jobs.status.im/?gh_jid=3693623', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2055187, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 3693623, + updated_at: '2023-10-04T05:13:53-04:00', + requisition_id: 'PROV-Sec-2', + title: 'Protocol Engineer', + }, + { + absolute_url: 'https://jobs.status.im/?gh_jid=3157908', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 1830496, + location: { + name: 'Remote, Worldwide', + }, + metadata: null, + id: 3157908, + updated_at: '2023-10-04T05:13:53-04:00', + requisition_id: 'PROV-Sec-3', + title: 'Protocol Researcher (Distributed Systems)', + }, + { + absolute_url: 'https://jobs.status.im/?gh_jid=5175038', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2584916, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5175038, + updated_at: '2023-10-09T05:53:53-04:00', + requisition_id: 'SDK-2', + title: 'Software Engineer (Chat SDK)', + }, + { + absolute_url: 'https://jobs.status.im/?gh_jid=5310503', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2656108, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5310503, + updated_at: '2023-10-19T03:12:53-04:00', + requisition_id: 'PROV-Wak-13', + title: 'Software Engineer Distributed Systems Testing', + }, + { + absolute_url: 'https://jobs.status.im/?gh_jid=5423094', + data_compliance: [ + { + type: 'gdpr', + requires_consent: false, + requires_processing_consent: false, + requires_retention_consent: false, + retention_period: null, + }, + ], + internal_job_id: 2694724, + location: { + name: 'Remote (Worldwide)', + }, + metadata: null, + id: 5423094, + updated_at: '2023-10-24T12:39:05-04:00', + requisition_id: 'WAK-BD-1', + title: 'Technical Business Development Lead ', + }, + ], + }, + { + id: 87849, + name: 'Web', + parent_id: 87842, + child_ids: [], + jobs: [], + }, + { + id: 0, + name: 'No Department', + parent_id: null, + child_ids: [], + jobs: [], + }, +] diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/useFetchJobs.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/useFetchJobs.ts new file mode 100644 index 0000000..d65cc82 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/JobsPerDepartment/useFetchJobs.ts @@ -0,0 +1,162 @@ +import { useEffect, useRef, useState } from 'react' + +/* +// Array of possible job boards: +const allJobBoards = [ + 'testacidinfo', // Acid Test job board + 'logos', + 'nimbus', + 'codex', + 'status72', // Note: this job board has all the jobs from the other job boards + 'nomos', + 'thestatusnetwork', + 'instituteoffreetechnologies', // aka IFT + 'vac', + 'waku', +] as const +*/ + +export type JobDepartmentName = string + +export type JobDepartmentData = { + id: number + name: string + parent_id: number | null + child_ids: number[] + jobs: Job[] +} + +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 + }[] + internal_job_id: number + location: { + name: string + } + metadata?: any + id: number + updated_at: string + requisition_id: string + title: string +} + +export type JobDepartmentArray = JobDepartmentData[] | null + +type UseFetchJobsReturn = { + data: JobDepartmentArray + error: Error | null + isLoading: boolean +} + +const parseJobDepartments = ( + rawJobDepartmentData: any, + titleFilter?: string, +): JobDepartmentArray => { + const jobDepartmentArray = rawJobDepartmentData?.departments + + if (!jobDepartmentArray) { + throw Error('No departments found in rawJobDepartmentData') + } + + if (!Array.isArray(jobDepartmentArray)) { + throw Error('The received jobDepartmentArray is not an array') + } + + // Map through each department and filter its jobs based on titleFilter + const processedJobDepartmentArray: JobDepartmentData[] = + jobDepartmentArray.map((department: JobDepartmentData) => { + let filteredJobs = department.jobs + + if (titleFilter) { + filteredJobs = department.jobs.filter((job) => + job.title.includes(titleFilter), + ) + } + + return { + ...department, + jobs: filteredJobs, + } + }) + + return processedJobDepartmentArray +} + +// Fetches jobs from greenhouse via their department endpoint: +// https://developers.greenhouse.io/job-board.html#list-departments + +export const useFetchJobs = ( + jobBoardToFetch: string, + titleFilter: string = '', + dummyResponse: JobDepartmentArray = null, +): UseFetchJobsReturn => { + const [data, setData] = useState(null) + const [error, setError] = useState(null) + const [isLoading, setIsLoading] = useState(false) + const isMounted = useRef(true) + + const fetchJobs = async (): Promise<{ + jobsPerDepartment: JobDepartmentArray + errorData: Error | null + }> => { + try { + if (dummyResponse) { + console.log('dummy data bruh:', dummyResponse) + return { jobsPerDepartment: dummyResponse, errorData: null } + } + + const response = await fetch( + `https://boards-api.greenhouse.io/v1/boards/${jobBoardToFetch}/departments`, + ) + const jobDepartmentData = await response.json() + + const jobsPerDepartment: JobDepartmentArray = parseJobDepartments( + jobDepartmentData, + titleFilter, + ) + + return { + jobsPerDepartment, + errorData: null, + } + } catch (err) { + const errorData = + err instanceof Error + ? err + : typeof err === 'string' + ? new Error(err) + : new Error('Unknown error') + + console.error(err) + return { jobsPerDepartment: null, errorData } + } + } + + useEffect(() => { + if (isLoading) return + + setIsLoading(true) + fetchJobs().then(({ jobsPerDepartment, errorData }) => { + // We should not update state if the component is unmounted. + if (!isMounted.current) return + + if (jobsPerDepartment) setData(jobsPerDepartment) + if (errorData) setError(errorData) + setIsLoading(false) + }) + + return () => { + isMounted.current = false + } + }, []) + + return { data, error, isLoading } +} + +export default useFetchJobs diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/index.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/index.ts index ae3212b..04e421d 100644 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/index.ts +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/index.ts @@ -24,4 +24,4 @@ export * from './Showcase' export * from './ShowcaseCard' export * from './SocialCard' export * from './TimelineItem' -export * from './JobLists' +export * from './JobsPerDepartment'