Ctrl K
ComunidadGuías…

src/lib/resume-templates.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/**
 * The six templates, in one place.
 *
 * They were written out by hand in four places that had no reason to agree:
 * `get_resume_format`'s handler, the Design popover's select, the new-resume
 * dialog's cards, and `PHOTO_TEMPLATES` in resume-paper.tsx. Four lists, one
 * subject — the same shape LINES_PER_PAGE and LETTER_LABEL each cost this
 * codebase once.
 *
 * PURE and client-safe, beside resume-text.ts and for the same reason: the
 * editor and the paper are client components, and the tool handler is not.
 *
 * `template` is a plain String column on Resume with a default of "harvard",
 * NOT part of the resume document contract in resume-schema.ts. Adding a value
 * here touches no zod schema and no saved `Resume.data`.
 */

export type ResumeTemplate = {
  key: string;
  /** What the picker calls it. */
  name: string;
  /** One clause, for the card in the new-resume dialog. */
  hint: string;
  /** The paragraph get_resume_format hands an assistant choosing one. */
  description: string;
  /** False where the format's own convention forbids one: harvard, ats. */
  takesPhoto: boolean;
  /** False where the template ignores `accent` and prints black: ats. */
  takesAccent: boolean;
};

export const DEFAULT_TEMPLATE = "harvard";

export const RESUME_TEMPLATES: readonly ResumeTemplate[] = [
  {
    key: "harvard",
    name: "Harvard",
    hint: "Dense, black and white, the academic standard",
    description:
      "DEFAULT. The Harvard OCS format: Times-metric serif, everything one size, name and section headings centred over full-width rules, each entry two justified lines (organisation/location, then role/dates). Dense, black-and-white, maximally ATS-safe. Use this unless asked otherwise.",
    // The format's own convention has no photograph on it.
    takesPhoto: false,
    takesAccent: true,
  },
  {
    key: "classic",
    name: "Classic",
    hint: "Serif headings, centred",
    description:
      "Serif headings, centred header. Timeless, ATS-safe. Takes a photo, centred above the name.",
    takesPhoto: true,
    takesAccent: true,
  },
  {
    key: "modern",
    name: "Modern",
    hint: "Sans-serif, accent rules",
    description:
      "Sans-serif, accent rules, left-aligned header. Takes a photo, beside the name.",
    takesPhoto: true,
    takesAccent: true,
  },
  {
    key: "compact",
    name: "Compact",
    hint: "Tight leading, fits the most",
    description:
      "Tight leading, two-column skills. Fits the most content. Takes a photo, beside the name.",
    takesPhoto: true,
    takesAccent: true,
  },
  {
    key: "editorial",
    name: "Editorial",
    hint: "Large display name, generous space",
    description:
      "Large display name, generous whitespace, magazine feel. Takes a photo, squared off beside the name.",
    takesPhoto: true,
    takesAccent: true,
  },
  {
    key: "ats",
    name: "Plain (ATS)",
    hint: "One column, black, every link printed as its URL",
    description:
      "Plain, single column, black on white, no accent colour and no photo. Conventional headings, dates as ordinary text, real list markers, and every link printed as its URL rather than as a label with the address hidden in the markup. Reach for it when a portal is going to parse the file rather than a person read it, or when somebody asks for something 'ATS-friendly' — and say plainly that this is a smaller difference than the internet claims. What it does change: harvard and the others print a labelled link as its label, so a text extractor sees the label and never the address; here every address is on the page.",
    takesPhoto: false,
    takesAccent: false,
  },
];

const byKey = new Map(RESUME_TEMPLATES.map((template) => [template.key, template]));

export const TEMPLATE_KEYS: string[] = RESUME_TEMPLATES.map((template) => template.key);

/** Unknown keys fall through to the default's answer, which is the safe one. */
export function templateTakesPhoto(key: string): boolean {
  return byKey.get(key)?.takesPhoto ?? byKey.get(DEFAULT_TEMPLATE)!.takesPhoto;
}

export function templateTakesAccent(key: string): boolean {
  return byKey.get(key)?.takesAccent ?? true;
}