File size: 8,415 Bytes
92a138e
 
 
 
 
 
2b7b868
92a138e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
const { v4: uuidv4 } = require('uuid');
const { getDb } = require('../config/database');
const { scoreResume } = require('../services/atsService');
const logger = require('../config/logger');

const DEFAULT_CONTENT = JSON.stringify({
  contact: { name: '', title: '', email: '', phone: '', location: '', linkedin: '', github: '', website: '' },
  summary: '', experience: [], education: [], skills: [], certifications: [], projects: [], languages: [], awards: [], customSections: [],
});
const DEFAULT_DESIGN = JSON.stringify({ primaryColor: '#2563EB', fontFamily: 'Inter, sans-serif', fontSize: 11 });
const DEFAULT_ORDER = JSON.stringify(['contact', 'summary', 'experience', 'education', 'skills']);

async function saveVersion(db, resumeId, snapshot, label) {
  const lastVer = await db.get('SELECT version_num FROM resume_versions WHERE resume_id = ? ORDER BY version_num DESC LIMIT 1', resumeId);
  const nextNum = lastVer ? lastVer.version_num + 1 : 1;
  await db.run('INSERT INTO resume_versions (id, resume_id, version_num, snapshot, label) VALUES (?, ?, ?, ?, ?)', uuidv4(), resumeId, nextNum, JSON.stringify(snapshot), label || null);
}

async function createResume(req, res) {
  const { title, templateId, content, design, sectionOrder } = req.body;
  const db = await getDb();
  const id = uuidv4();

  // Default to the first modern template if none provided
  const finalTemplateId = templateId || 'tmpl_modern_1';

  if (finalTemplateId) {
    const tmpl = await db.get('SELECT id FROM templates WHERE id = ?', finalTemplateId);
    if (!tmpl) {
      if (templateId) return res.status(404).json({ success: false, message: 'Template not found' });
      // If default template isn't found, just proceed with null (user will have to select one)
    }
  }

  await db.run(
    `INSERT INTO resumes (id, user_id, template_id, title, content, design, section_order) VALUES (?, ?, ?, ?, ?, ?, ?)`,
    id, (req.user ? req.user.id : 'guest_user'), finalTemplateId || null, title || 'Untitled Resume', content ? JSON.stringify(content) : DEFAULT_CONTENT, design ? JSON.stringify(design) : DEFAULT_DESIGN, sectionOrder ? JSON.stringify(sectionOrder) : DEFAULT_ORDER
  );

  const resume = await db.get('SELECT * FROM resumes WHERE id = ?', id);
  return res.status(201).json({ success: true, resume: parseResume(resume) });
}

async function listResumes(req, res) {
  const db = await getDb();
  const resumes = await db.all('SELECT r.*, t.name AS template_name FROM resumes r LEFT JOIN templates t ON r.template_id = t.id WHERE r.user_id = ? ORDER BY r.updated_at DESC', (req.user ? req.user.id : 'guest_user'));
  return res.json({ success: true, resumes: resumes.map(parseResume) });
}

async function getResume(req, res) {
  const db = await getDb();
  const resume = await db.get('SELECT r.*, t.html_content, t.css_content FROM resumes r LEFT JOIN templates t ON r.template_id = t.id WHERE r.id = ? AND (r.user_id = ? OR r.is_public = 1)', req.params.id, (req.user ? req.user.id : 'guest_user'));
  if (!resume) return res.status(404).json({ success: false, message: 'Resume not found' });
  return res.json({ success: true, resume: parseResume(resume) });
}

async function updateResume(req, res) {
  const db = await getDb();
  const existing = await db.get('SELECT * FROM resumes WHERE id = ? AND user_id = ?', req.params.id, (req.user ? req.user.id : 'guest_user'));
  if (!existing) return res.status(404).json({ success: false, message: 'Resume not found' });

  const { title, templateId, content, design, sectionOrder, isPublic } = req.body;

  let atsScore = existing.ats_score;
  let atsFeedback = existing.ats_feedback;


  await db.run(
    `UPDATE resumes SET title = COALESCE(?, title), template_id = COALESCE(?, template_id), content = COALESCE(?, content), design = COALESCE(?, design), section_order = COALESCE(?, section_order), is_public = COALESCE(?, is_public), ats_score = ?, ats_feedback = ?, updated_at = datetime('now') WHERE id = ?`,
    title || null, templateId || null, content ? JSON.stringify(content) : null, design ? JSON.stringify(design) : null, sectionOrder ? JSON.stringify(sectionOrder) : null, isPublic !== undefined ? (isPublic ? 1 : 0) : null, atsScore, atsFeedback, req.params.id
  );

  const updated = await db.get('SELECT * FROM resumes WHERE id = ?', req.params.id);
  return res.json({ success: true, resume: parseResume(updated) });
}

async function deleteResume(req, res) {
  const db = await getDb();
  const result = await db.run('DELETE FROM resumes WHERE id = ? AND user_id = ?', req.params.id, (req.user ? req.user.id : 'guest_user'));
  if (result.changes === 0) return res.status(404).json({ success: false, message: 'Resume not found' });
  return res.json({ success: true, message: 'Resume deleted' });
}

async function getAtsScore(req, res) {
  const db = await getDb();
  const resume = await db.get('SELECT * FROM resumes WHERE id = ? AND user_id = ?', req.params.id, (req.user ? req.user.id : 'guest_user'));
  if (!resume) return res.status(404).json({ success: false, message: 'Resume not found' });
  const result = await scoreResume(JSON.parse(resume.content), resume.template_id);
  await db.run('UPDATE resumes SET ats_score = ?, ats_feedback = ?, updated_at = datetime("now") WHERE id = ?', result.score, JSON.stringify(result.feedback), resume.id);
  return res.json({ success: true, ats: result });
}

async function duplicateResume(req, res) {
  const db = await getDb();
  const original = await db.get('SELECT * FROM resumes WHERE id = ? AND user_id = ?', req.params.id, (req.user ? req.user.id : 'guest_user'));
  if (!original) return res.status(404).json({ success: false, message: 'Resume not found' });

  const id = uuidv4();
  await db.run(
    `INSERT INTO resumes (id, user_id, template_id, title, content, design, section_order) VALUES (?, ?, ?, ?, ?, ?, ?)`,
    id, (req.user ? req.user.id : 'guest_user'), original.template_id, `${original.title} (Copy)`, original.content, original.design, original.section_order
  );

  const duplicated = await db.get('SELECT * FROM resumes WHERE id = ?', id);
  return res.status(201).json({ success: true, resume: parseResume(duplicated) });
}

async function getVersions(req, res) {
  const db = await getDb();
  const versions = await db.all('SELECT id, version_num, label, created_at FROM resume_versions WHERE resume_id = ? ORDER BY version_num DESC', req.params.id);
  return res.json({ success: true, versions });
}

async function restoreVersion(req, res) {
  const db = await getDb();
  const version = await db.get('SELECT * FROM resume_versions WHERE id = ? AND resume_id = ?', req.params.versionId, req.params.id);
  if (!version) return res.status(404).json({ success: false, message: 'Version not found' });

  await db.run('UPDATE resumes SET content = ?, updated_at = datetime("now") WHERE id = ?', version.snapshot, req.params.id);
  const updated = await db.get('SELECT * FROM resumes WHERE id = ?', req.params.id);
  return res.json({ success: true, resume: parseResume(updated) });
}

async function updateDesign(req, res) {
  const db = await getDb();
  const { design } = req.body;
  await db.run('UPDATE resumes SET design = ?, updated_at = datetime("now") WHERE id = ? AND user_id = ?', JSON.stringify(design), req.params.id, (req.user ? req.user.id : 'guest_user'));
  const updated = await db.get('SELECT * FROM resumes WHERE id = ?', req.params.id);
  return res.json({ success: true, resume: parseResume(updated) });
}

async function updateSectionOrder(req, res) {
  const db = await getDb();
  const { sectionOrder } = req.body;
  await db.run('UPDATE resumes SET section_order = ?, updated_at = datetime("now") WHERE id = ? AND user_id = ?', JSON.stringify(sectionOrder), req.params.id, (req.user ? req.user.id : 'guest_user'));
  const updated = await db.get('SELECT * FROM resumes WHERE id = ?', req.params.id);
  return res.json({ success: true, resume: parseResume(updated) });
}

function parseResume(r) {
  if (!r) return null;
  return { ...r, content: JSON.parse(r.content || '{}'), design: JSON.parse(r.design || '{}'), sectionOrder: JSON.parse(r.section_order || '[]'), atsFeedback: JSON.parse(r.ats_feedback || '[]'), isPublic: Boolean(r.is_public) };
}

module.exports = { createResume, listResumes, getResume, updateResume, deleteResume, getAtsScore, duplicateResume, getVersions, restoreVersion, updateDesign, updateSectionOrder };