// server3.js - Premium Services API import express from 'express'; import cors from 'cors'; import helmet from 'helmet'; import dotenv from 'dotenv'; import { open } from 'sqlite'; import sqlite3 from 'sqlite3'; import jwt from 'jsonwebtoken'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); const app = express(); const PORT = process.env.PREMIUM_PORT || 5002; let db; const initDB = async () => { try { db = await open({ filename: '/home/jcoakley/aptiva-dev1-app/user_profile.db', driver: sqlite3.Database }); console.log('Connected to user_profile.db for Premium Services.'); } catch (error) { console.error('Error connecting to premium database:', error); } }; initDB(); app.use(helmet()); app.use(express.json()); const allowedOrigins = ['https://dev1.aptivaai.com']; app.use(cors({ origin: allowedOrigins, credentials: true })); const authenticatePremiumUser = (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).json({ error: 'Premium authorization required' }); try { const { userId } = jwt.verify(token, process.env.SECRET_KEY); req.userId = userId; next(); } catch (error) { return res.status(403).json({ error: 'Invalid or expired token' }); } }; // Get latest selected planned path app.get('/api/premium/planned-path/latest', authenticatePremiumUser, async (req, res) => { try { const row = await db.get( `SELECT * FROM career_path WHERE user_id = ? ORDER BY start_date DESC LIMIT 1`, [req.userId] ); res.json(row || {}); } catch (error) { console.error('Error fetching latest career path:', error); res.status(500).json({ error: 'Failed to fetch latest planned path' }); } }); // Get all planned paths for the user app.get('/api/premium/planned-path/all', authenticatePremiumUser, async (req, res) => { try { const rows = await db.all( `SELECT * FROM career_path WHERE user_id = ? ORDER BY start_date ASC`, [req.userId] ); res.json({ careerPath: rows }); } catch (error) { console.error('Error fetching career paths:', error); res.status(500).json({ error: 'Failed to fetch planned paths' }); } }); // Save a new planned path app.post('/api/premium/planned-path', authenticatePremiumUser, async (req, res) => { const { job_title, projected_end_date } = req.body; if (!job_title) { return res.status(400).json({ error: 'Job title is required' }); } try { await db.run( `INSERT INTO career_path (user_id, job_title, status, start_date, projected_end_date) VALUES (?, ?, 'Active', DATE('now'), ?)`, [req.userId, job_title, projected_end_date || null] ); res.status(201).json({ message: 'Planned path added successfully' }); } catch (error) { console.error('Error adding planned path:', error); res.status(500).json({ error: 'Failed to add planned path' }); } }); // Save a new milestone app.post('/api/premium/milestones', authenticatePremiumUser, async (req, res) => { const { milestone_type, description, date, career_path_id, progress } = req.body; if (!milestone_type || !description || !date) { return res.status(400).json({ error: 'Missing required fields' }); } try { await db.run( `INSERT INTO milestones (user_id, milestone_type, description, date, career_path_id, progress, created_at) VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`, [req.userId, milestone_type, description, date, career_path_id, progress || 0] ); res.status(201).json({ message: 'Milestone saved successfully' }); } catch (error) { console.error('Error saving milestone:', error); res.status(500).json({ error: 'Failed to save milestone' }); } }); // Get all milestones app.get('/api/premium/milestones', authenticatePremiumUser, async (req, res) => { try { const milestones = await db.all( `SELECT * FROM milestones WHERE user_id = ? ORDER BY date ASC`, [req.userId] ); const mapped = milestones.map(m => ({ id: m.id, title: m.description, date: m.date, type: m.milestone_type, progress: m.progress || 0, career_path_id: m.career_path_id })); res.json({ milestones: mapped }); } catch (error) { console.error('Error fetching milestones:', error); res.status(500).json({ error: 'Failed to fetch milestones' }); } }); /// Update an existing milestone app.put('/api/premium/milestones/:id', authenticatePremiumUser, async (req, res) => { const { id } = req.params; const { milestone_type, description, date, progress } = req.body; if (!milestone_type || !description || !date) { return res.status(400).json({ error: 'Missing required fields' }); } try { await db.run( `UPDATE milestones SET milestone_type = ?, description = ?, date = ?, progress = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? AND user_id = ?`, [milestone_type, description, date, progress || 0, id, req.userId] ); res.status(200).json({ message: 'Milestone updated successfully' }); } catch (error) { console.error('Error updating milestone:', error); res.status(500).json({ error: 'Failed to update milestone' }); } }); // Archive current career to history app.post('/api/premium/career-history', authenticatePremiumUser, async (req, res) => { const { career_path_id, company } = req.body; if (!career_path_id || !company) { return res.status(400).json({ error: 'Career path ID and company are required' }); } try { const career = await db.get(`SELECT * FROM career_path WHERE id = ? AND user_id = ?`, [career_path_id, req.userId]); if (!career) { return res.status(404).json({ error: 'Career path not found' }); } await db.run( `INSERT INTO career_history (user_id, job_title, company, start_date) VALUES (?, ?, ?, DATE('now'))`, [req.userId, career.job_title, company] ); await db.run(`DELETE FROM career_path WHERE id = ?`, [career_path_id]); res.status(201).json({ message: 'Career moved to history successfully' }); } catch (error) { console.error('Error moving career to history:', error); res.status(500).json({ error: 'Failed to update career history' }); } }); // Retrieve career history app.get('/api/premium/career-history', authenticatePremiumUser, async (req, res) => { try { const history = await db.all( `SELECT * FROM career_history WHERE user_id = ? ORDER BY start_date DESC;`, [req.userId] ); res.json({ careerHistory: history }); } catch (error) { console.error('Error fetching career history:', error); res.status(500).json({ error: 'Failed to fetch career history' }); } }); // ROI Analysis (placeholder logic) app.get('/api/premium/roi-analysis', authenticatePremiumUser, async (req, res) => { try { const userCareer = await db.get( `SELECT * FROM career_path WHERE user_id = ? ORDER BY start_date DESC LIMIT 1`, [req.userId] ); if (!userCareer) return res.status(404).json({ error: 'No planned path found for user' }); const roi = { jobTitle: userCareer.job_title, salary: userCareer.salary, tuition: 50000, netGain: userCareer.salary - 50000 }; res.json(roi); } catch (error) { console.error('Error calculating ROI:', error); res.status(500).json({ error: 'Failed to calculate ROI' }); } }); app.listen(PORT, () => { console.log(`Premium server running on http://localhost:${PORT}`); });