113 lines
3.1 KiB
TypeScript
Raw Normal View History

/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import {
faCalendar,
faQuestionCircle,
faTasks,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { type JSX, useCallback, useState } from "react";
import { Volunteer } from "../icons/Volunteer";
interface JobProperties {
readonly title: string;
readonly company: string;
readonly start: Date;
readonly end: Date | null;
readonly link: string;
readonly type: "volunteer" | "fixed" | "project" | "hypothetical";
readonly description: string;
readonly logo: string;
}
const IconMap = {
fixed: faCalendar,
hypothetical: faQuestionCircle,
project: faTasks,
volunteer: Volunteer,
};
const getColor
= (type: JobProperties["type"], end: JobProperties["end"]): string => {
if (type === "hypothetical") {
return "text-[--primary]";
}
if (end) {
return "text-[--former]";
}
return "text-[--current]";
};
const getBorder
= (type: JobProperties["type"], end: JobProperties["end"]): string => {
if (type === "hypothetical") {
return "border-[--primary]";
}
if (end) {
return "border-[--former]";
}
return "border-[--current]";
};
/**
* Renders the view for a job.
* @param properties - The job to render.
* @returns A JSX element.
*/
export const Job = (properties: JobProperties): JSX.Element => {
const { title, company, start, end, type, description } = properties;
const [ showDescription, setShowDescription ] = useState(false);
const toggleDescription = useCallback((): void => {
setShowDescription(!showDescription);
}, [ showDescription ]);
const color = getColor(type, end);
const border = getBorder(type, end);
const borderStyle = end
? "border-dashed border-2"
: "border-double border-4";
return (
<li className={`mb-10 ms-6 ${color}`}>
<span
className={`absolute flex items-center justify-center w-6 h-6 bg-[--background] rounded-full -start-3 ${color}`}
>
<FontAwesomeIcon className="text-3xl" icon={IconMap[type]} />
</span>
<h3 className={`flex items-center mb-1 text-lg font-semibold`}>
{`${title} for ${company}`}
</h3>
<time className="block mb-2 text-sm font-normal leading-none">
{start.toLocaleDateString("en-US", {
month: "long",
year: "numeric",
})}{" - "}
{end
? end.toLocaleDateString("en-US", {
month: "long",
year: "numeric",
})
: "Present"}
</time>
{showDescription
? <div
className="mb-4 text-base font-normal"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: description }}
></div>
: null}
<button
2024-09-25 16:04:46 -07:00
className={`inline-flex items-center px-4 py-2 text-sm font-medium ${borderStyle} ${border}`}
onClick={toggleDescription}
type="button"
>
{showDescription
? "Hide Details"
: "Show Details"}
</button>
</li>
);
};