set up downloads for tailored resume and cover letter
This commit is contained in:
parent
099ccc40e8
commit
8efa97d950
3 changed files with 193 additions and 46 deletions
|
@ -32,11 +32,12 @@
|
|||
<div id="coverLetterSection">
|
||||
<h3>Generated Cover Letter:</h3>
|
||||
<textarea id="coverLetterOutput" rows="15" cols="80"></textarea>
|
||||
<button id="downloadBtn">Download as DOCX</button>
|
||||
<button id="downloadCoverLetterBtn">Download as DOCX</button>
|
||||
</div>
|
||||
<div id="tailoredResumeSection">
|
||||
<h3>Tailored Resume:</h3>
|
||||
<textarea id="tailoredResumeOutput" rows="15" cols="80"></textarea>
|
||||
<button id="downloadResumeBtn">Download Resume as DOCX</button>
|
||||
<h3>Key Updates</h3>
|
||||
<pre id="keyResumeUpdates"></pre>
|
||||
</div>
|
||||
|
|
|
@ -115,38 +115,89 @@ document.getElementById("generateCoverLetterBtn").addEventListener("click", asyn
|
|||
}
|
||||
});
|
||||
|
||||
document.getElementById('downloadBtn').addEventListener('click', async function () {
|
||||
const coverLetterText = document.getElementById('coverLetterOutput').value;
|
||||
|
||||
async function downloadDocument(content, endpoint, filename) {
|
||||
try {
|
||||
const response = await fetch('/generate/download', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ coverLetterText })
|
||||
});
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ content })
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to download document.');
|
||||
if (!response.ok) throw new Error('Failed to download document.');
|
||||
|
||||
// Convert response to blob
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
// Convert response to blob
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
// Create a temporary download link
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'cover_letter.docx';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
// Create a temporary download link
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
// Cleanup
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
// Cleanup
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
alert('Failed to download document.');
|
||||
}
|
||||
}
|
||||
|
||||
// Event listener for cover letter download
|
||||
document.getElementById('downloadCoverLetterBtn').addEventListener('click', function () {
|
||||
const coverLetterText = document.getElementById('coverLetterOutput').value;
|
||||
if (!coverLetterText.trim()) {
|
||||
alert("Cover letter is empty!");
|
||||
return;
|
||||
}
|
||||
downloadDocument(coverLetterText, '/generate/download-cover-letter', 'cover_letter.docx');
|
||||
});
|
||||
|
||||
// Event listener for tailored resume download
|
||||
document.getElementById('downloadResumeBtn').addEventListener('click', function () {
|
||||
const tailoredResumeText = document.getElementById('tailoredResumeOutput').value;
|
||||
if (!tailoredResumeText.trim()) {
|
||||
alert("Tailored resume is empty!");
|
||||
return;
|
||||
}
|
||||
downloadDocument(tailoredResumeText, '/generate/download-resume', 'tailored_resume.docx');
|
||||
});
|
||||
|
||||
// document.getElementById('downloadBtn').addEventListener('click', async function () {
|
||||
// const coverLetterText = document.getElementById('coverLetterOutput').value;
|
||||
|
||||
// try {
|
||||
// const response = await fetch('/generate/download', {
|
||||
// method: 'POST',
|
||||
// headers: { 'Content-Type': 'application/json' },
|
||||
// body: JSON.stringify({ coverLetterText })
|
||||
// });
|
||||
|
||||
// if (!response.ok) throw new Error('Failed to download document.');
|
||||
|
||||
// // Convert response to blob
|
||||
// const blob = await response.blob();
|
||||
// const url = window.URL.createObjectURL(blob);
|
||||
|
||||
// // Create a temporary download link
|
||||
// const a = document.createElement('a');
|
||||
// a.href = url;
|
||||
// a.download = 'cover_letter.docx';
|
||||
// document.body.appendChild(a);
|
||||
// a.click();
|
||||
|
||||
// // Cleanup
|
||||
// document.body.removeChild(a);
|
||||
// window.URL.revokeObjectURL(url);
|
||||
// } catch (error) {
|
||||
// console.error('Error:', error);
|
||||
// alert('Failed to download document.');
|
||||
// }
|
||||
// });
|
||||
|
||||
|
||||
function formatCoverLetter(rawText) {
|
||||
return rawText
|
||||
|
|
|
@ -95,39 +95,102 @@ router.post('/', async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
router.post('/download', async (req, res) => {
|
||||
try {
|
||||
const { coverLetterText } = req.body;
|
||||
// router.post('/download', async (req, res) => {
|
||||
// try {
|
||||
// const { coverLetterText } = req.body;
|
||||
|
||||
// Generate .docx file dynamically
|
||||
const docBuffer = await generateCoverLetter(coverLetterText);
|
||||
// // Generate .docx file dynamically
|
||||
// const docBuffer = await generateCoverLetter(coverLetterText);
|
||||
|
||||
// Set response headers for file download
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="cover_letter.docx"');
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
|
||||
// // Set response headers for file download
|
||||
// res.setHeader('Content-Disposition', 'attachment; filename="cover_letter.docx"');
|
||||
// res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
|
||||
|
||||
res.send(docBuffer);
|
||||
// res.send(docBuffer);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).json({ error: 'Error generating document' });
|
||||
}
|
||||
});
|
||||
// } catch (error) {
|
||||
// console.error(error);
|
||||
// res.status(500).json({ error: 'Error generating document' });
|
||||
// }
|
||||
// });
|
||||
|
||||
function generateCoverLetter(rawText) {
|
||||
// function generateCoverLetter(rawText) {
|
||||
// if (!rawText || typeof rawText !== "string") {
|
||||
// throw new Error("Invalid cover letter text provided.");
|
||||
// }
|
||||
|
||||
// // Convert text into paragraphs, splitting by double newlines
|
||||
// const paragraphs = rawText.split("\n\n").map(text =>
|
||||
// new Paragraph({
|
||||
// children: [
|
||||
// new TextRun(text),
|
||||
// new TextRun("\n") // Ensures spacing between paragraphs
|
||||
// ]
|
||||
// })
|
||||
// );
|
||||
|
||||
// // Create the document
|
||||
// const doc = new Document({
|
||||
// sections: [{ properties: {}, children: paragraphs }]
|
||||
// });
|
||||
|
||||
// return Packer.toBuffer(doc);
|
||||
// }
|
||||
|
||||
// Function to generate a DOCX file
|
||||
// function generateDocx(rawText) {
|
||||
// if (!rawText || typeof rawText !== "string") {
|
||||
// throw new Error("Invalid text provided.");
|
||||
// }
|
||||
|
||||
// const paragraphs = rawText.split("\n\n").map(text =>
|
||||
// new Paragraph({
|
||||
// children: [
|
||||
// new TextRun(text),
|
||||
// new TextRun("\n") // Ensures spacing between paragraphs
|
||||
// ]
|
||||
// })
|
||||
// );
|
||||
|
||||
// const doc = new Document({
|
||||
// sections: [{ properties: {}, children: paragraphs }]
|
||||
// });
|
||||
|
||||
// return Packer.toBuffer(doc);
|
||||
// }
|
||||
|
||||
function generateDocx(rawText) {
|
||||
if (!rawText || typeof rawText !== "string") {
|
||||
throw new Error("Invalid cover letter text provided.");
|
||||
throw new Error("Invalid resume text provided.");
|
||||
}
|
||||
|
||||
// Convert text into paragraphs, splitting by double newlines
|
||||
const paragraphs = rawText.split("\n\n").map(text =>
|
||||
new Paragraph({
|
||||
children: [
|
||||
new TextRun(text),
|
||||
new TextRun("\n") // Ensures spacing between paragraphs
|
||||
]
|
||||
})
|
||||
);
|
||||
const paragraphs = [];
|
||||
|
||||
// Split text into lines
|
||||
rawText.split("\n").forEach(line => {
|
||||
if (line.trim().startsWith("•")) {
|
||||
// Format bullet points properly
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
text: line.trim(), // Keep bullet point text
|
||||
bullet: { level: 0 } // Apply bullet point formatting
|
||||
})
|
||||
);
|
||||
} else if (line.trim() === "") {
|
||||
// Add spacing for empty lines
|
||||
paragraphs.push(new Paragraph({ text: "" }));
|
||||
} else {
|
||||
// Format normal text
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [
|
||||
new TextRun(line.trim()),
|
||||
new TextRun("\n")
|
||||
]
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Create the document
|
||||
const doc = new Document({
|
||||
|
@ -138,5 +201,37 @@ function generateCoverLetter(rawText) {
|
|||
}
|
||||
|
||||
|
||||
// Route to download cover letter
|
||||
router.post('/download-cover-letter', async (req, res) => {
|
||||
try {
|
||||
const { content } = req.body;
|
||||
const docBuffer = await generateDocx(content);
|
||||
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="cover_letter.docx"');
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
|
||||
|
||||
res.send(docBuffer);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).json({ error: 'Error generating document' });
|
||||
}
|
||||
});
|
||||
|
||||
// Route to download tailored resume
|
||||
router.post('/download-resume', async (req, res) => {
|
||||
try {
|
||||
const { content } = req.body;
|
||||
const docBuffer = await generateDocx(content);
|
||||
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="tailored_resume.docx"');
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
|
||||
|
||||
res.send(docBuffer);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).json({ error: 'Error generating document' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
module.exports = router;
|
Loading…
Reference in a new issue