diff --git a/cv-engine/src/api/export.ts b/cv-engine/src/api/export.ts index 4d0bda8..b6d2119 100644 --- a/cv-engine/src/api/export.ts +++ b/cv-engine/src/api/export.ts @@ -10,7 +10,15 @@ export async function exportPdf(cv: CV, endpoint = 'http://localhost:4000/export const response = await axios.post(endpoint, { ...cv, templateId }, { responseType: 'blob' }); const contentDisposition = response.headers['content-disposition'] || ''; const match = /filename="?([^";]+)"?/i.exec(contentDisposition); - const filename = match ? match[1] : `${cv.personal.firstName || 'Candidate'}_${cv.personal.lastName || 'CV'}.pdf`; + const filename = match ? match[1] : (() => { + const today = new Date(); + const y = today.getFullYear(); + const m = String(today.getMonth() + 1).padStart(2, '0'); + const d = String(today.getDate()).padStart(2, '0'); + const dateStr = `${y}${m}${d}`; + const safeLast = (cv.personal.lastName || '').trim() || 'cv'; + return `cv-${safeLast}-${dateStr}.pdf`; + })(); const blob = new Blob([response.data], { type: 'application/pdf' }); const url = window.URL.createObjectURL(blob); @@ -48,7 +56,14 @@ export async function downloadJob(jobId: string, baseUrl = 'http://localhost:400 const response = await axios.get(`${baseUrl}/export/download/${jobId}`, { responseType: 'blob' }); const contentDisposition = response.headers['content-disposition'] || ''; const match = /filename="?([^";]+)"?/i.exec(contentDisposition); - const filename = match ? match[1] : `CV.pdf`; + const filename = match ? match[1] : (() => { + const today = new Date(); + const y = today.getFullYear(); + const m = String(today.getMonth() + 1).padStart(2, '0'); + const d = String(today.getDate()).padStart(2, '0'); + const dateStr = `${y}${m}${d}`; + return `cv-cv-${dateStr}.pdf`; + })(); const blob = new Blob([response.data], { type: 'application/pdf' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); diff --git a/cv-engine/src/editors/SkillsEditor.tsx b/cv-engine/src/editors/SkillsEditor.tsx index 86f0337..617dd1b 100644 --- a/cv-engine/src/editors/SkillsEditor.tsx +++ b/cv-engine/src/editors/SkillsEditor.tsx @@ -3,10 +3,19 @@ import { useSkillsData, useCvStore } from '../store/cvStore'; const SkillsEditor: React.FC = () => { const skills = useSkillsData(); - const { addSkill, updateSkill, removeSkill } = useCvStore(); + const { addSkill, updateSkill, removeSkill, reorderSkills } = useCvStore(); const [newSkillName, setNewSkillName] = useState(''); const [newSkillLevel, setNewSkillLevel] = useState<'Beginner' | 'Intermediate' | 'Advanced' | undefined>(undefined); + const levels = ['Beginner', 'Intermediate', 'Advanced'] as const; + type SkillLevel = typeof levels[number] | undefined; + const parseLevel = (value: string): SkillLevel => { + if (!value) return undefined; + return (levels.includes(value as SkillLevel extends undefined ? never : typeof levels[number]) + ? (value as typeof levels[number]) + : undefined); + }; + const handleAddSkill = () => { const name = newSkillName.trim(); if (!name) return; @@ -34,7 +43,7 @@ const SkillsEditor: React.FC = () => { { /> +
+ + +