refactor(cv): remove abandoned profile builder
This commit is contained in:
+5
-3
@@ -2,12 +2,11 @@
|
||||
|
||||
## Current
|
||||
|
||||
- [ ] Commit and deploy the centralized job-specific CV compatibility catalog; verify live release health.
|
||||
- [ ] Complete authenticated production CV Builder editing/PDF smoke when a safe signed-in test session is available.
|
||||
|
||||
## Next
|
||||
|
||||
- [ ] Complete authenticated production CV Builder editing/PDF smoke when a safe signed-in test session is available.
|
||||
- [ ] Remove the two temporary Gitea credential-transfer files after explicit deletion confirmation.
|
||||
- [ ] No further repository-only CV work is known; resume from production findings if the authenticated smoke identifies a regression.
|
||||
|
||||
## Completed
|
||||
|
||||
@@ -26,6 +25,9 @@
|
||||
- [x] Deployed release 266 and verified public health plus the Career and CV Builder application routes.
|
||||
- [x] Audited CV TODOs and obsolete-code candidates; confirmed the remaining old renderer is an active job-specific compatibility path rather than dead Builder code.
|
||||
- [x] Centralized the compatibility path's template IDs, aliases, accents, chooser metadata and AI rewrite guidance while preserving saved IDs and HTML rendering.
|
||||
- [x] Deployed the centralized compatibility catalog as release 267 and verified live health plus both Career routes.
|
||||
- [x] Permanently deleted and verified removal of both temporary Gitea credential-transfer files after explicit approval.
|
||||
- [x] Removed the abandoned account-page CV builder/extraction types, controls and duplicate six-template registry; focused tests, TypeScript, the full frontend suite and production build pass.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
import { Accordion, AccordionDetails, AccordionSummary, Alert, Avatar, Box, Button, Chip, Dialog, DialogContent, DialogTitle, Divider, FormControl, IconButton, InputLabel, LinearProgress, MenuItem, Paper, Select, TextField, Typography } from "@mui/material";
|
||||
import { Alert, Avatar, Box, Button, Chip, Divider, Paper, TextField, Typography } from "@mui/material";
|
||||
|
||||
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import PhotoCameraOutlinedIcon from "@mui/icons-material/PhotoCameraOutlined";
|
||||
import ZoomInOutlinedIcon from "@mui/icons-material/ZoomInOutlined";
|
||||
|
||||
import { api, getApiErrorMessage } from "../api";
|
||||
import GoogleAuthCard from "../components/GoogleAuthCard";
|
||||
@@ -16,97 +14,9 @@ import SessionsSettingsCard from "../components/SessionsSettingsCard";
|
||||
import CropImageDialog from "../components/CropImageDialog";
|
||||
import { useToast } from "../toast";
|
||||
import { useI18n } from "../i18n/I18nProvider";
|
||||
import {
|
||||
emptyStructuredCv,
|
||||
getStructuredCvFieldMetadata,
|
||||
joinLines,
|
||||
normalizeStructuredCv,
|
||||
parseStructuredCvJson,
|
||||
splitLines,
|
||||
StructuredCvFieldMetadata,
|
||||
StructuredCvProfile,
|
||||
} from "../profileCv";
|
||||
import { JobApplication } from "../types";
|
||||
import { parseStructuredCvJson } from "../profileCv";
|
||||
import { getUserScopedStorageKey } from "../auth";
|
||||
|
||||
|
||||
type CvSectionOption = "" | "Professional Summary" | "Core Skills" | "Experience Highlights" | "Selected Achievements" | "Projects";
|
||||
type CvSectionStyle = "ats-minimal" | "harvard" | "auckland" | "edinburgh" | "monarch" | "fjord";
|
||||
|
||||
type CvBuilderTone = "Concise and direct" | "Executive and polished" | "Technical and detailed" | "Warm and people-focused";
|
||||
type CvBuilderLanguage = "English" | "Norwegian" | "Spanish" | "French" | "German";
|
||||
|
||||
type ExtractionRun = {
|
||||
id: number;
|
||||
trigger: string;
|
||||
status: string;
|
||||
artifactFileName?: string;
|
||||
startedAtUtc: string;
|
||||
completedAtUtc?: string;
|
||||
appliedAtUtc?: string;
|
||||
parserVersion: string;
|
||||
normalizerVersion: string;
|
||||
llmPromptVersion: string;
|
||||
errorMessage?: string;
|
||||
};
|
||||
|
||||
type QueuedCvRunResponse = {
|
||||
queued: boolean;
|
||||
extractionRunId: number;
|
||||
status: string;
|
||||
};
|
||||
|
||||
type JobListResponse = {
|
||||
items: JobApplication[];
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
};
|
||||
|
||||
type RewriteTemplateOption = {
|
||||
id: CvSectionStyle;
|
||||
title: string;
|
||||
eyebrow: string;
|
||||
accent: string;
|
||||
blurb: string;
|
||||
sampleHeading: string;
|
||||
sampleMeta: string;
|
||||
sampleBullets: string[];
|
||||
};
|
||||
|
||||
type CvBuilderPreview = {
|
||||
templateId: CvSectionStyle;
|
||||
html: string;
|
||||
suggestedFileName: string;
|
||||
fullText: string;
|
||||
rewrittenText: string;
|
||||
structuredCv: StructuredCvProfile;
|
||||
sectionName?: string | null;
|
||||
targetRole?: string | null;
|
||||
jobApplicationId?: number | null;
|
||||
};
|
||||
|
||||
type PdfCarouselItem = {
|
||||
templateId: CvSectionStyle;
|
||||
title: string;
|
||||
fileName: string;
|
||||
pdfUrl?: string;
|
||||
status: "loading" | "ready" | "error";
|
||||
error?: string;
|
||||
};
|
||||
|
||||
type RewriteRequestPayload = {
|
||||
sectionName: string | null;
|
||||
style: CvSectionStyle;
|
||||
templateId: CvSectionStyle;
|
||||
targetRole: string | null;
|
||||
jobApplicationId: number | null;
|
||||
sourceText: string | null;
|
||||
promptBackground: string | null;
|
||||
tone: string | null;
|
||||
language: string | null;
|
||||
};
|
||||
|
||||
type MeResponse = {
|
||||
provider?: "local" | "google" | "external";
|
||||
id?: string;
|
||||
@@ -131,70 +41,7 @@ type PendingEmailChange = {
|
||||
requestedAtUtc?: string | null;
|
||||
};
|
||||
|
||||
const CV_UPLOAD_ACCEPT = ".pdf,.docx,.txt,.md,image/png,image/jpeg,image/webp,application/pdf,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/plain,text/markdown";
|
||||
const AVATAR_UPLOAD_ACCEPT = "image/png,image/jpeg,image/webp";
|
||||
const REWRITE_TEMPLATES: RewriteTemplateOption[] = [
|
||||
{
|
||||
id: "ats-minimal",
|
||||
title: "ATS Minimal",
|
||||
eyebrow: "Scanner-friendly",
|
||||
accent: "#0f172a",
|
||||
blurb: "Compact, direct, and easy for screening systems to parse.",
|
||||
sampleHeading: "Senior Backend Engineer",
|
||||
sampleMeta: "Acme Systems · Oslo · 2021 - Present",
|
||||
sampleBullets: ["Built API workflows with measurable delivery outcomes.", "Kept skills and achievements easy to scan."]
|
||||
},
|
||||
{
|
||||
id: "harvard",
|
||||
title: "Harvard",
|
||||
eyebrow: "Traditional",
|
||||
accent: "#7f1d1d",
|
||||
blurb: "Formal hierarchy and restrained tone for conservative hiring flows.",
|
||||
sampleHeading: "Professional Summary",
|
||||
sampleMeta: "Clear structure · precise dates · credible language",
|
||||
sampleBullets: ["Emphasizes polished summaries.", "Works well for broad professional roles."]
|
||||
},
|
||||
{
|
||||
id: "auckland",
|
||||
title: "Auckland",
|
||||
eyebrow: "Modern sidebar",
|
||||
accent: "#0f766e",
|
||||
blurb: "Sharper highlights with a more contemporary, design-forward rhythm.",
|
||||
sampleHeading: "Selected Impact",
|
||||
sampleMeta: "Focused strengths · compact highlights",
|
||||
sampleBullets: ["Pulls skills into stronger highlight clusters.", "Good when you want a fresher feel."]
|
||||
},
|
||||
{
|
||||
id: "edinburgh",
|
||||
title: "Edinburgh",
|
||||
eyebrow: "Editorial",
|
||||
accent: "#5b21b6",
|
||||
blurb: "More personality and stronger section contrast without losing clarity.",
|
||||
sampleHeading: "Experience Highlights",
|
||||
sampleMeta: "Refined spacing · stronger visual voice",
|
||||
sampleBullets: ["Useful when the CV should feel more distinctive.", "Still keeps wording grounded and factual."]
|
||||
},
|
||||
{
|
||||
id: "monarch",
|
||||
title: "Monarch",
|
||||
eyebrow: "Executive",
|
||||
accent: "#7c2d12",
|
||||
blurb: "High-contrast presentation for leadership-heavy applications.",
|
||||
sampleHeading: "Executive Profile",
|
||||
sampleMeta: "Leadership clarity · refined hierarchy",
|
||||
sampleBullets: ["Adds more top-level summary emphasis.", "Well suited to senior strategic roles."]
|
||||
},
|
||||
{
|
||||
id: "fjord",
|
||||
title: "Fjord",
|
||||
eyebrow: "Technical",
|
||||
accent: "#0f4c5c",
|
||||
blurb: "Calm, high-density layout for engineering resumes and project-heavy CVs.",
|
||||
sampleHeading: "Projects & Systems",
|
||||
sampleMeta: "Technical depth · practical readability",
|
||||
sampleBullets: ["Gives projects and skills more weight.", "Better for technical detail without chaos."]
|
||||
},
|
||||
];
|
||||
|
||||
function initialsFrom(values: Array<string | undefined>) {
|
||||
const joined = values.map((x) => (x ?? "").trim()).filter(Boolean);
|
||||
@@ -207,31 +54,6 @@ function initialsFrom(values: Array<string | undefined>) {
|
||||
return (joined[0][0] + joined[1][0]).toUpperCase();
|
||||
}
|
||||
|
||||
function confidenceTone(confidence?: number) {
|
||||
if (typeof confidence !== "number") return { label: "Review", color: "default" as const };
|
||||
if (confidence >= 0.8) return { label: `High ${Math.round(confidence * 100)}%`, color: "success" as const };
|
||||
if (confidence >= 0.65) return { label: `Medium ${Math.round(confidence * 100)}%`, color: "warning" as const };
|
||||
return { label: `Low ${Math.round(confidence * 100)}%`, color: "error" as const };
|
||||
}
|
||||
|
||||
function FieldReviewNote({ metadata }: { metadata?: StructuredCvFieldMetadata }) {
|
||||
if (!metadata) return null;
|
||||
const tone = confidenceTone(metadata.confidence);
|
||||
return (
|
||||
<Box sx={{ display: "flex", gap: 0.75, flexWrap: "wrap", mt: 0.75, alignItems: "center" }}>
|
||||
<Chip size="small" color={tone.color} variant={tone.color === "default" ? "outlined" : "filled"} label={tone.label} />
|
||||
{metadata.method ? <Chip size="small" variant="outlined" label={metadata.method} /> : null}
|
||||
{metadata.sourceBlockId ? <Chip size="small" variant="outlined" label={metadata.sourceBlockId} /> : null}
|
||||
{metadata.reviewState ? <Chip size="small" variant="outlined" label={metadata.reviewState} /> : null}
|
||||
{metadata.sourceSnippet ? (
|
||||
<Typography variant="caption" sx={{ color: "text.secondary" }}>
|
||||
{metadata.sourceSnippet}
|
||||
</Typography>
|
||||
) : null}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
// ProfilePage backs /profile: account identity + security + preferences. The master career
|
||||
// profile lives in CareerProfilePage (/career). Split in Phase 2.2. Saves only identity fields
|
||||
// (partial update), never the master profile.
|
||||
|
||||
Reference in New Issue
Block a user