Feature: Implement Cover Letters as a custom section type (#2659)

This commit is contained in:
Amruth Pillai
2026-01-31 03:17:20 +01:00
committed by GitHub
parent a8d8d0e340
commit 71dac2021d
65 changed files with 1516 additions and 5 deletions
@@ -1,5 +1,6 @@
import { match } from "ts-pattern";
import type {
CoverLetterItem as CoverLetterItemType,
CustomSectionItem,
CustomSectionType,
SectionItem,
@@ -10,6 +11,7 @@ import { cn } from "@/utils/style";
import { useResumeStore } from "../store/resume";
import { AwardsItem } from "./items/awards-item";
import { CertificationsItem } from "./items/certifications-item";
import { CoverLetterItem } from "./items/cover-letter-item";
import { EducationItem } from "./items/education-item";
import { ExperienceItem } from "./items/experience-item";
import { InterestsItem } from "./items/interests-item";
@@ -49,6 +51,7 @@ function renderItemByType(type: CustomSectionType, item: CustomSectionItem, item
))
.with("volunteer", () => <VolunteerItem {...(item as SectionItem<"volunteer">)} className={itemClassName} />)
.with("references", () => <ReferencesItem {...(item as SectionItem<"references">)} className={itemClassName} />)
.with("cover-letter", () => <CoverLetterItem {...(item as CoverLetterItemType)} className={itemClassName} />)
.exhaustive();
}
@@ -171,7 +174,7 @@ export function getSectionComponent(
return (
<section className={cn(`page-section page-section-custom page-section-${id}`, sectionClassName)}>
{customSection.type !== "summary" && (
{customSection.type !== "summary" && customSection.type !== "cover-letter" && (
<h6 className="mb-1.5 text-(--page-primary-color)">{customSection.title}</h6>
)}
@@ -0,0 +1,28 @@
import { TiptapContent } from "@/components/input/rich-input";
import type { CoverLetterItem as CoverLetterItemType } from "@/schema/resume/data";
import { stripHtml } from "@/utils/string";
import { cn } from "@/utils/style";
type CoverLetterItemProps = CoverLetterItemType & {
className?: string;
};
export function CoverLetterItem({ className, ...item }: CoverLetterItemProps) {
if (!stripHtml(item.recipient) && !stripHtml(item.content)) return null;
return (
<div className={cn("cover-letter-item", className)}>
{stripHtml(item.recipient) && (
<div className="cover-letter-item-recipient mb-4">
<TiptapContent content={item.recipient} />
</div>
)}
{stripHtml(item.content) && (
<div className="cover-letter-item-content">
<TiptapContent content={item.content} />
</div>
)}
</div>
);
}