28
Adding Job Type Filtering
This is part of the ExamPro Next.js course. Additional content will be added to this lab, such as pagination and job type filtering.
In this lab, we will be adding the job type filtering feature to the existing application
localhost:3000/jobs/type/full-time
Create
pages/jobs/type/[type_name].js
Import the following
import { promises as fs } from 'fs';
import path from 'path';
import matter from 'gray-matter';
import Job from '@/components/jobs/Job';
import JobsHeader from '@/components/jobs/JobsHeader';
import Layout from '@/components/Layout';
- Create the getStaticPaths() function
export async function getStaticPaths() {
// Read from the /jobs directory
const files = await fs.readdir(path.join('jobs'));
const types = await Promise.all(
files.map(async (filename) => {
const markdown = await fs.readFile(path.join('jobs', filename), 'utf-8');
const { data } = matter(markdown);
// Return the job types in lowercase. Eg. 'full-time' instead of 'Full-Time'
return data.type.toLowerCase();
})
);
const paths = types.map((type) => ({
params: { type_name: type },
}));
return {
paths,
fallback: false,
};
}
- Create the getStaticProps() function
// This function takes the type_name from getStaticPaths()
export async function getStaticProps({ params: { type_name } }) {
// Read from /jobs directory
const files = await fs.readdir(path.join('jobs'));
// Map through jobs directory
const jobs = await Promise.all(
files.map(async (filename) => {
// Set 'slug' to name of md file
const slug = filename.replace('.md', '');
// Read all markdown from file
const markdown = await fs.readFile(path.join('jobs', filename), 'utf-8');
// Extract data from markdown
const { data } = matter(markdown);
// return slug and data in an array
return {
slug,
data,
};
})
);
// Maps through all the job types
const types = jobs.map((job) => job.data.type);
// Only take the unique job types
const uniqueTypes = [...new Set(types)];
const jobTypes = jobs.filter((job) => job.data.type.toLowerCase() === type_name);
// return jobs, typeName, types
return {
props: {
jobs: jobTypes,
typeName: type_name,
types: uniqueTypes,
},
};
}
- Create
JobTypePostings()
function
export default function JobTypePostings({ jobs, typeName }) {
const jobType = typeName.replace(/(^|[\s-])\S/g, function (match) {
return match.toUpperCase();
});
return (
<Layout title="Jobs | ExamPro">
<JobsHeader jobType={jobType} />
<div className="bg-white my-4 shadow overflow-hidden divide-y divide-gray-200 sm:rounded-md">
<ul role="list" className="divide-y divide-gray-200">
{/* Maps through each job */}
{jobs.map((job, index) => (
<Job key={index} job={job} />
))}
</ul>
</div>
</Layout>
);
}
- Import the JobsHeader component
import JobsHeader from '@/components/jobs/JobsHeader';
- Replace the following lines
<div className="px-4 py-4 sm:px-6 md:flex md:items-center md:justify-between">
<div className="flex-1 min-w-0">
<h2 className="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate">
Job Postings
</h2>
</div>
</div>
with
<JobsHeader />
28