Skip to content

Commit 314d286

Browse files
authored
Merge pull request #61 from stefanv/refactor-expiry
Refactor expiry logic into utility function
2 parents 831b3c2 + 3796bbe commit 314d286

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

src/components/Job.jsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,23 @@ import { Link } from "gatsby";
33

44
import Badge from "./Badge";
55
import jobToMarkdown from "../jobToMarkdown.mjs";
6+
import { isJobExpired } from "../utils.mjs";
67

78

89
const Job = ({ job }) => {
910
const processedJob = React.useMemo(() => jobToMarkdown(job), [job]);
1011

1112
const isExpired = React.useMemo(() => {
12-
if (!processedJob || !processedJob.expires) return false;
13-
const today = new Date();
14-
return new Date(`${processedJob.expires}T23:59:59.999-12:00`) < today;
15-
}, [processedJob]);
13+
return isJobExpired(job);
14+
}, [job]);
1615

1716
if (processedJob === undefined) {
1817
console.log("We don't expect an empty job posting; aborting");
1918
return <div>Empty job posting</div>;
2019
}
2120

2221
return (
23-
<div className="job">
22+
<div className={`job${isExpired ? " expired" : ""}`}>
2423
<div className="badges">
2524
{ processedJob.badges &&
2625
processedJob.badges.map((badge) =>

src/filter-jobs.mjs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1+
import { isJobExpired } from "./utils.mjs";
2+
13
const filterJobs = (jobs, filter) => {
2-
// Filter out expired jobs. Use Howland Island timezone to ensure
3-
// that everyone sees the job on its last day.
44
const today = new Date();
5+
6+
// Filter out expired jobs if requested.
57
if (!filter.showExpired) {
6-
jobs = jobs.filter((job) => new Date(`${job.expires}T23:59:59.999-12:00`) > today)
8+
jobs = jobs.filter((job) => !isJobExpired(job, today));
79
}
810

911
if (filter.fullTime) {
10-
jobs = jobs.filter((job) => job.percentTime === 100)
12+
jobs = jobs.filter((job) => job.percentTime === 100);
1113
}
1214

1315
if (filter.ossTimeGt) {
14-
jobs = jobs.filter((job) => job.percentOSS >= parseInt(filter.ossTimeGt))
16+
// Ensure we're comparing numbers
17+
const minOSS = parseInt(filter.ossTimeGt, 10);
18+
jobs = jobs.filter((job) => job.percentOSS >= minOSS);
1519
}
1620

1721
if (filter.remote) {
@@ -22,6 +26,6 @@ const filterJobs = (jobs, filter) => {
2226
}
2327

2428
return jobs;
25-
}
29+
};
2630

2731
export default filterJobs;

src/utils.mjs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Checks if a job has expired using the 'Anywhere on Earth' (-12:00) timezone.
3+
*/
4+
export const isJobExpired = (job, now = new Date()) => {
5+
try {
6+
const expiresStr = String(job.expires).trim();
7+
const expiryDate = new Date(`${expiresStr}T23:59:59.999-12:00`);
8+
9+
// If date is malformed, default to NOT expired to avoid hiding jobs by mistake.
10+
if (isNaN(expiryDate.getTime())) {
11+
return false;
12+
}
13+
14+
return expiryDate < now;
15+
} catch (error) {
16+
// Fail-safe: malformed data shouldn't break the entire jobs board UI.
17+
return false;
18+
}
19+
};

0 commit comments

Comments
 (0)