diff --git a/public/index.html b/public/index.html index 1192a90..2209722 100644 --- a/public/index.html +++ b/public/index.html @@ -26,7 +26,7 @@ diff --git a/public/js/script.js b/public/js/script.js index 69ac916..57917df 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -2,13 +2,14 @@ document.getElementById('uploadForm').addEventListener('submit', async function event.preventDefault(); const resumePreviewSection = document.getElementById('resumePreviewSection'); + const resumeTextPreview = document.getElementById("resumeTextOutput") const generateBtn = document.getElementById('generateCoverLetterBtn'); + generateBtn.disabled = true; - generateBtn.textContent = "Reading Resume..."; resumePreviewSection.value = ""; //This clear any previous generated output - resumePreviewSection.style.display = "flex"; + resumePreviewSection.style.display = "block"; const fileInput = document.getElementById('resume'); const file = fileInput.files[0]; @@ -31,21 +32,22 @@ document.getElementById('uploadForm').addEventListener('submit', async function if (data.error) { alert("Error: " + data.error) } else { - resumePreviewSection.value = data.extractedText; + resumeTextPreview.value = data.extractedText; generateBtn.disabled = false; - generateBtn.textContent = "Generate Cover Letter" } } catch (error) { console.error('Error:', error); alert('Something went wrong. Please try again.'); - outputSection.style.display = "none"; + resumePreviewSection.style.display = "none"; } }); +// Send Resume and Job Description to Generate Cover Letter document.getElementById("generateCoverLetterBtn").addEventListener("click", async function () { const extractedResumeText = document.getElementById("resumeTextOutput").value; const jobDescription = document.getElementById("jobDescription").value; + const generateBtn = document.getElementById("generateCoverLetterBtn") if (!extractedResumeText.trim()) { alert("Please confirm the extracted resume text."); @@ -62,6 +64,8 @@ document.getElementById("generateCoverLetterBtn").addEventListener("click", asyn jobDescription, }; + generateBtn.textContent = "Generating Cover Letter...." + try { const response = await fetch("/generate", { method: "POST", @@ -75,6 +79,7 @@ document.getElementById("generateCoverLetterBtn").addEventListener("click", asyn } else { document.getElementById("coverLetterOutput").innerText = data.coverLetter; document.getElementById("coverLetterSection").style.display = "block"; // Show cover letter section + generateBtn.textContent = "Generate New Cover Letter" } } catch (error) { console.error("Error generating cover letter:", error); diff --git a/routes/generate.js b/routes/generate.js index ef1810e..6378cff 100644 --- a/routes/generate.js +++ b/routes/generate.js @@ -17,51 +17,46 @@ const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY, }); +// Extract resume text and return it for preview +router.post('/extract-resume', upload.single('resume'), async (req, res) => { + try { + const resumeBuffer = req.file.buffer; + const extractedResumeText = await pdf(resumeBuffer); + + res.json({ extractedText: extractedResumeText.text }); + } catch (error) { + console.error(error); + res.status(500).json({ error: 'Error extracting resume text' }); + } +}); // Handle Resume upload and user input for Job Description -router.post('/', upload.single('resume'), async (req, res) =>{ - try{ +router.post('/', async (req, res) => { + try { + const { extractedResumeText, jobDescription } = req.body; - if (!req.file || !req.body.jobDescription) { - return res.status(400).json({ error: 'Resume and Job Description are required' }); - } - - let resumeText = req.file.buffer.toString('utf-8'); - const jobDescription = req.body.jobDescription; - - if (req.file.mimetype === 'application/pdf') { - const pdfData = await pdf(req.file.buffer); - resumeText = pdfData.text; - } - - // Load the LLM APi Messages - // These include placeholders to be replaced later in function const resume_parser_api = require('../data/resume_parser_api.json'); const cover_letter_api = require('../data/cover_letter_api.json'); + // Replace placeholder in API call + resume_parser_api.messages[0].content[0].text = resume_parser_api.messages[0].content[0].text.replace("{{resume}}", extractedResumeText); - // Replace placeholder in resume api with extracted text - resume_parser_api.messages[0].content[0].text = resume_parser_api.messages[0].content[0].text.replace("{{resume}}", resumeText); - - // Send resume to LLM const resumeResponse = await anthropic.messages.create(resume_parser_api); const candidateProfile = resumeResponse.content[0].text.split('```json')[1].split('```')[0].trim(); - // Replace variables in cover letter API prompt cover_letter_api.messages[0].content[0].text = cover_letter_api.messages[0].content[0].text .replace('{{resume_json}}', candidateProfile) .replace('{{job_description}}', jobDescription) .replace('{{date}}', new Date().toDateString()); - - //Send data to LLM to generate Cover Letter + const coverLetterResponse = await anthropic.messages.create(cover_letter_api); const coverLetterRawText = coverLetterResponse.content[0].text.split('')[1].split('')[0].trim(); - + res.json({ coverLetter: coverLetterRawText }); } catch (error) { console.error(error); res.status(500).json({ error: 'Error generating cover letter' }); - } + } }); router.post('/download', async (req, res) => {