From 48b48f81654dcb1449f2a99e2a3037145fe064dc Mon Sep 17 00:00:00 2001 From: geulah Date: Sun, 5 Oct 2025 23:45:56 +0100 Subject: [PATCH] feat(summary): implement summary editor with validation and preview Add summary editor component with rich text formatting capabilities Add validation for summary section in cv store Implement printable preview mode in preview panel Replace placeholder with actual summary editor in App component Update HTML sanitization to use DOMPurify with allowed tags --- cv-engine/src/App.tsx | 3 +- cv-engine/src/components/PreviewPanel.tsx | 46 ++++++- cv-engine/src/editors/SummaryEditor.tsx | 112 ++++++++++++++++ cv-engine/src/schema/cvSchema.ts | 12 +- cv-engine/src/store/cvStore.ts | 14 ++ cv-engine/src/utils/printable.ts | 156 ++++++++++++++++++++++ 6 files changed, 330 insertions(+), 13 deletions(-) create mode 100644 cv-engine/src/editors/SummaryEditor.tsx create mode 100644 cv-engine/src/utils/printable.ts diff --git a/cv-engine/src/App.tsx b/cv-engine/src/App.tsx index 0986189..f485b54 100644 --- a/cv-engine/src/App.tsx +++ b/cv-engine/src/App.tsx @@ -4,6 +4,7 @@ import PersonalEditor from './editors/PersonalEditor'; import WorkEditor from './editors/WorkEditor'; import EducationEditor from './editors/EducationEditor'; import SkillsEditor from './editors/SkillsEditor'; +import SummaryEditor from './editors/SummaryEditor'; import PreviewPanel from './components/PreviewPanel'; import { useActiveStep } from './store/cvStore'; @@ -22,7 +23,7 @@ const App: React.FC = () => { case 'skills': return ; case 'summary': - return
Summary editor will be implemented in M3
; + return ; case 'finalize': return
Finalize step will be implemented in M5
; default: diff --git a/cv-engine/src/components/PreviewPanel.tsx b/cv-engine/src/components/PreviewPanel.tsx index 5d29758..c751e88 100644 --- a/cv-engine/src/components/PreviewPanel.tsx +++ b/cv-engine/src/components/PreviewPanel.tsx @@ -1,6 +1,7 @@ -import React from 'react'; +import React, { useMemo, useState } from 'react'; import { useCvStore } from '../store/cvStore'; import ATSTemplate from '../templates/ATSTemplate'; +import { buildPrintableHtml } from '../utils/printable'; interface PreviewPanelProps { className?: string; @@ -9,20 +10,53 @@ interface PreviewPanelProps { const PreviewPanel: React.FC = ({ className = '' }) => { const cv = useCvStore(state => state.cv); const templateId = useCvStore(state => state.cv.templateId); + const [mode, setMode] = useState<'inline' | 'printable'>('inline'); + const printableHtml = useMemo(() => buildPrintableHtml(cv), [cv]); return (

Preview

-
- Template: {templateId === 'ats' ? 'ATS-Friendly' : templateId} +
+
+ Template: {templateId === 'ats' ? 'ATS-Friendly' : templateId} +
+
+ + +
- {/* Render the appropriate template based on templateId */} - {templateId === 'ats' && } - {/* Add more template options here as they are implemented */} + {mode === 'inline' && ( + <> + {/* Render the appropriate template based on templateId */} + {templateId === 'ats' && } + {/* Add more template options here as they are implemented */} + + )} + + {mode === 'printable' && ( +