import {
Award,
Certification,
CustomSection,
CustomSectionGroup,
Education,
Experience,
Interest,
Language,
Profile,
Project,
Publication,
Reference,
SectionKey,
SectionWithItem,
Skill,
URL,
Volunteer,
} from "@reactive-resume/schema";
import { cn, isEmptyString, isUrl } from "@reactive-resume/utils";
import get from "lodash.get";
import { Fragment } from "react";
import { Picture } from "../components/picture";
import { useArtboardStore } from "../store/artboard";
import { TemplateProps } from "../types/template";
const Header = () => {
const basics = useArtboardStore((state) => state.resume.basics);
return (
{basics.name}
{basics.headline}
{basics.location && (
)}
{basics.phone && (
)}
{basics.email && (
)}
{basics.customFields.map((item) => (
{[item.name, item.value].filter(Boolean).join(": ")}
))}
);
};
const Summary = () => {
const section = useArtboardStore((state) => state.resume.sections.summary);
if (!section.visible || isEmptyString(section.content)) return null;
return (
);
};
type RatingProps = { level: number };
const Rating = ({ level }: RatingProps) => (
{Array.from({ length: 5 }).map((_, index) => (
index && "bg-primary group-[.sidebar]:bg-background",
)}
/>
))}
);
type LinkProps = {
url: URL;
icon?: React.ReactNode;
label?: string;
className?: string;
};
const Link = ({ url, icon, label, className }: LinkProps) => {
if (!isUrl(url.href)) return null;
return (
);
};
type SectionProps
= {
section: SectionWithItem | CustomSectionGroup;
children?: (item: T) => React.ReactNode;
className?: string;
urlKey?: keyof T;
levelKey?: keyof T;
summaryKey?: keyof T;
keywordsKey?: keyof T;
};
const Section = ({
section,
children,
className,
urlKey,
levelKey,
summaryKey,
keywordsKey,
}: SectionProps) => {
if (!section.visible || !section.items.length) return null;
return (
{section.name}
{section.items
.filter((item) => item.visible)
.map((item) => {
const url = (urlKey && get(item, urlKey)) as URL | undefined;
const level = (levelKey && get(item, levelKey, 0)) as number | undefined;
const summary = (summaryKey && get(item, summaryKey, "")) as string | undefined;
const keywords = (keywordsKey && get(item, keywordsKey, [])) as string[] | undefined;
return (
{children?.(item as T)}
{url !== undefined && }
{summary !== undefined && !isEmptyString(summary) && (
)}
{level !== undefined && level > 0 &&
}
{keywords !== undefined && keywords.length > 0 && (
{keywords.join(", ")}
)}
);
})}
);
};
const Experience = () => {
const section = useArtboardStore((state) => state.resume.sections.experience);
return (
section={section} urlKey="url" summaryKey="summary">
{(item) => (
{item.company}
{item.position}
{item.date}
{item.location}
)}
);
};
const Education = () => {
const section = useArtboardStore((state) => state.resume.sections.education);
return (
section={section} urlKey="url" summaryKey="summary">
{(item) => (
{item.institution}
{item.area}
{item.score}
{item.date}
{item.studyType}
)}
);
};
const Profiles = () => {
const section = useArtboardStore((state) => state.resume.sections.profiles);
const fontSize = useArtboardStore((state) => state.resume.metadata.typography.font.size);
return (
section={section}>
{(item) => (
{isUrl(item.url.href) ? (
}
/>
) : (
{item.username}
)}
{item.network}
)}
);
};
const Awards = () => {
const section = useArtboardStore((state) => state.resume.sections.awards);
return (
section={section} urlKey="url" summaryKey="summary">
{(item) => (
{item.title}
{item.awarder}
)}
);
};
const Certifications = () => {
const section = useArtboardStore((state) => state.resume.sections.certifications);
return (
section={section} urlKey="url" summaryKey="summary">
{(item) => (
{item.name}
{item.issuer}
)}
);
};
const Skills = () => {
const section = useArtboardStore((state) => state.resume.sections.skills);
return (
section={section} levelKey="level" keywordsKey="keywords">
{(item) => (
{item.name}
{item.description}
)}
);
};
const Interests = () => {
const section = useArtboardStore((state) => state.resume.sections.interests);
return (
section={section} keywordsKey="keywords" className="space-y-0.5">
{(item) => {item.name}
}
);
};
const Publications = () => {
const section = useArtboardStore((state) => state.resume.sections.publications);
return (
section={section} urlKey="url" summaryKey="summary">
{(item) => (
{item.name}
{item.publisher}
)}
);
};
const Volunteer = () => {
const section = useArtboardStore((state) => state.resume.sections.volunteer);
return (
section={section} urlKey="url" summaryKey="summary">
{(item) => (
{item.organization}
{item.position}
{item.date}
{item.location}
)}
);
};
const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
section={section} levelKey="level">
{(item) => (
{item.name}
{item.description}
)}
);
};
const Projects = () => {
const section = useArtboardStore((state) => state.resume.sections.projects);
return (
section={section} urlKey="url" summaryKey="summary" keywordsKey="keywords">
{(item) => (
{item.name}
{item.description}
)}
);
};
const References = () => {
const section = useArtboardStore((state) => state.resume.sections.references);
return (
section={section} urlKey="url" summaryKey="summary">
{(item) => (
{item.name}
{item.description}
)}
);
};
const Custom = ({ id }: { id: string }) => {
const section = useArtboardStore((state) => state.resume.sections.custom[id]);
return (
section={section}
urlKey="url"
summaryKey="summary"
keywordsKey="keywords"
>
{(item) => (
{item.name}
{item.description}
{item.date}
{item.location}
)}
);
};
const mapSectionToComponent = (section: SectionKey) => {
switch (section) {
case "profiles":
return ;
case "summary":
return ;
case "experience":
return ;
case "education":
return ;
case "awards":
return ;
case "certifications":
return ;
case "skills":
return ;
case "interests":
return ;
case "publications":
return ;
case "volunteer":
return ;
case "languages":
return ;
case "projects":
return ;
case "references":
return ;
default:
if (section.startsWith("custom.")) return ;
return null;
}
};
export const Chikorita = ({ columns, isFirstPage = false }: TemplateProps) => {
const [main, sidebar] = columns;
return (
{isFirstPage && }
{main.map((section) => (
{mapSectionToComponent(section)}
))}
{sidebar.map((section) => (
{mapSectionToComponent(section)}
))}
);
};