diff --git a/backend/server3.js b/backend/server3.js index 7a3d478..f0de7d4 100644 --- a/backend/server3.js +++ b/backend/server3.js @@ -11,10 +11,6 @@ import path from 'path'; import { fileURLToPath } from 'url'; import { simulateFinancialProjection } from '../src/utils/FinancialProjectionService.js'; - - - - const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -132,6 +128,8 @@ app.post('/api/premium/planned-path', authenticatePremiumUser, async (req, res) } }); + +// Milestones premium services // Save a new milestone app.post('/api/premium/milestone', authenticatePremiumUser, async (req, res) => { const rawMilestones = Array.isArray(req.body.milestones) ? req.body.milestones : [req.body]; @@ -220,8 +218,6 @@ app.post('/api/premium/milestone', authenticatePremiumUser, async (req, res) => } }); - - // Get all milestones app.get('/api/premium/milestones', authenticatePremiumUser, async (req, res) => { try { @@ -243,8 +239,7 @@ app.get('/api/premium/milestones', authenticatePremiumUser, async (req, res) => } }); - -/// Update an existing milestone +// Update an existing milestone app.put('/api/premium/milestones/:id', authenticatePremiumUser, async (req, res) => { try { const { id } = req.params; @@ -335,36 +330,8 @@ app.delete('/api/premium/milestones/:id', authenticatePremiumUser, async (req, r } }); -// 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' }); - } -}); - +//Financial Profile premium services +//Get financial profile app.get('/api/premium/financial-profile', authenticatePremiumUser, async (req, res) => { try { const row = await db.get(`SELECT * FROM financial_profile WHERE user_id = ?`, [req.userId]); @@ -377,6 +344,7 @@ app.get('/api/premium/financial-profile', authenticatePremiumUser, async (req, r // Backend code (server3.js) +// Save or update financial profile app.post('/api/premium/financial-profile', authenticatePremiumUser, async (req, res) => { const { currentSalary, additionalIncome, monthlyExpenses, monthlyDebtPayments, @@ -480,21 +448,122 @@ app.post('/api/premium/financial-profile', authenticatePremiumUser, async (req, } }); +//PreimumOnboarding +//Career onboarding +app.post('/api/premium/onboarding/career', authenticatePremiumUser, async (req, res) => { + const { career_name, status, start_date, projected_end_date } = req.body; - - -// 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] + const careerPathId = uuidv4(); + + await db.run(` + INSERT INTO career_path (id, user_id, career_name, status, start_date, projected_end_date) + VALUES (?, ?, ?, ?, ?, ?)`, + [careerPathId, req.userId, career_name, status || 'planned', start_date || new Date().toISOString(), projected_end_date || null] ); - res.json({ careerHistory: history }); + res.status(201).json({ message: 'Career onboarding data saved.', careerPathId }); } catch (error) { - console.error('Error fetching career history:', error); - res.status(500).json({ error: 'Failed to fetch career history' }); + console.error('Error saving career onboarding data:', error); + res.status(500).json({ error: 'Failed to save career onboarding data.' }); + } +}); + +//Financial onboarding +app.post('/api/premium/onboarding/financial', authenticatePremiumUser, async (req, res) => { + const { + current_salary, additional_income, monthly_expenses, monthly_debt_payments, + retirement_savings, retirement_contribution, emergency_fund + } = req.body; + + try { + await db.run(` + INSERT INTO financial_profile ( + id, user_id, current_salary, additional_income, monthly_expenses, + monthly_debt_payments, retirement_savings, retirement_contribution, emergency_fund, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`, + [ + uuidv4(), req.userId, current_salary, additional_income, monthly_expenses, + monthly_debt_payments, retirement_savings, retirement_contribution, emergency_fund + ] + ); + + res.status(201).json({ message: 'Financial onboarding data saved.' }); + } catch (error) { + console.error('Error saving financial onboarding data:', error); + res.status(500).json({ error: 'Failed to save financial onboarding data.' }); + } +}); + +//College onboarding +app.post('/api/premium/onboarding/college', authenticatePremiumUser, async (req, res) => { + const { + in_college, expected_graduation, selected_school, selected_program, + program_type, is_online, credit_hours_per_year, hours_completed + } = req.body; + + try { + await db.run(` + INSERT INTO financial_profile ( + id, user_id, in_college, expected_graduation, selected_school, + selected_program, program_type, is_online, credit_hours_per_year, + hours_completed, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`, + [ + uuidv4(), req.userId, in_college ? 1 : 0, expected_graduation, selected_school, + selected_program, program_type, is_online, credit_hours_per_year, + hours_completed + ] + ); + + res.status(201).json({ message: 'College onboarding data saved.' }); + } catch (error) { + console.error('Error saving college onboarding data:', error); + res.status(500).json({ error: 'Failed to save college onboarding data.' }); + } +}); + +//Financial Projection Premium Services +// Save financial projection for a specific careerPathId +app.post('/api/premium/financial-projection/:careerPathId', authenticatePremiumUser, async (req, res) => { + const { careerPathId } = req.params; + const { projectionData } = req.body; // JSON containing detailed financial projections + + try { + const projectionId = uuidv4(); + + await db.run(` + INSERT INTO financial_projections (id, user_id, career_path_id, projection_json) + VALUES (?, ?, ?, ?)`, + [projectionId, req.userId, careerPathId, JSON.stringify(projectionData)] + ); + + res.status(201).json({ message: 'Financial projection saved.', projectionId }); + } catch (error) { + console.error('Error saving financial projection:', error); + res.status(500).json({ error: 'Failed to save financial projection.' }); + } +}); + +// Get financial projection for a specific careerPathId +app.get('/api/premium/financial-projection/:careerPathId', authenticatePremiumUser, async (req, res) => { + const { careerPathId } = req.params; + + try { + const projection = await db.get(` + SELECT projection_json FROM financial_projections + WHERE user_id = ? AND career_path_id = ?`, + [req.userId, careerPathId] + ); + + if (!projection) { + return res.status(404).json({ error: 'Projection not found.' }); + } + + res.status(200).json(JSON.parse(projection.projection_json)); + } catch (error) { + console.error('Error fetching financial projection:', error); + res.status(500).json({ error: 'Failed to fetch financial projection.' }); } }); diff --git a/src/App.js b/src/App.js index b417149..3391a8e 100644 --- a/src/App.js +++ b/src/App.js @@ -11,6 +11,8 @@ import UserProfile from './components/UserProfile.js'; import FinancialProfileForm from './components/FinancialProfileForm.js'; import MilestoneTracker from "./components/MilestoneTracker.js"; import Paywall from "./components/Paywall.js"; +import OnboardingContainer from './components/PremiumOnboarding/OnboardingContainer.js'; + import './App.css'; function App() { @@ -51,6 +53,8 @@ function App() { } /> } /> } /> + } /> + )} diff --git a/src/components/PremiumOnboarding/CareerOnboarding.js b/src/components/PremiumOnboarding/CareerOnboarding.js new file mode 100644 index 0000000..599935e --- /dev/null +++ b/src/components/PremiumOnboarding/CareerOnboarding.js @@ -0,0 +1,36 @@ +// CareerOnboarding.js +import React, { useState } from 'react'; + +const CareerOnboarding = ({ nextStep, prevStep }) => { + const [careerData, setCareerData] = useState({ + currentJob: '', + industry: '', + employmentStatus: '', + careerGoal: '', + }); + + const handleChange = (e) => { + setCareerData({ ...careerData, [e.target.name]: e.target.value }); + }; + + return ( +
+

Career Details

+ + + + + + + +
+ ); +}; + +export default CareerOnboarding; diff --git a/src/components/PremiumOnboarding/CollegeOnboarding.js b/src/components/PremiumOnboarding/CollegeOnboarding.js new file mode 100644 index 0000000..eb7d6e2 --- /dev/null +++ b/src/components/PremiumOnboarding/CollegeOnboarding.js @@ -0,0 +1,35 @@ +// CollegeOnboarding.js +import React, { useState } from 'react'; + +const CollegeOnboarding = ({ nextStep, prevStep }) => { + const [collegeData, setCollegeData] = useState({ + studentStatus: '', + school: '', + program: '', + creditHoursPerYear: '', + }); + + const handleChange = (e) => { + setCollegeData({ ...collegeData, [e.target.name]: e.target.value }); + }; + + return ( +
+

College Plans (optional)

+ + + + + + + +
+ ); +}; + +export default CollegeOnboarding; diff --git a/src/components/PremiumOnboarding/FinancialOnboarding.js b/src/components/PremiumOnboarding/FinancialOnboarding.js new file mode 100644 index 0000000..edd9876 --- /dev/null +++ b/src/components/PremiumOnboarding/FinancialOnboarding.js @@ -0,0 +1,30 @@ +// FinancialOnboarding.js +import React, { useState } from 'react'; + +const FinancialOnboarding = ({ nextStep, prevStep }) => { + const [financialData, setFinancialData] = useState({ + salary: '', + expenses: '', + savings: '', + debts: '', + }); + + const handleChange = (e) => { + setFinancialData({ ...financialData, [e.target.name]: e.target.value }); + }; + + return ( +
+

Financial Details

+ + + + + + + +
+ ); +}; + +export default FinancialOnboarding; diff --git a/src/components/PremiumOnboarding/OnboardingContainer.js b/src/components/PremiumOnboarding/OnboardingContainer.js new file mode 100644 index 0000000..70b86d3 --- /dev/null +++ b/src/components/PremiumOnboarding/OnboardingContainer.js @@ -0,0 +1,28 @@ +// OnboardingContainer.js +import React, { useState } from 'react'; +import PremiumWelcome from './PremiumWelcome.js'; +import CareerOnboarding from './CareerOnboarding.js'; +import FinancialOnboarding from './FinancialOnboarding.js'; +import CollegeOnboarding from './CollegeOnboarding.js'; + +const OnboardingContainer = () => { + const [step, setStep] = useState(0); + + const nextStep = () => setStep(step + 1); + const prevStep = () => setStep(step - 1); + + const onboardingSteps = [ + , + , + , + , + ]; + + return ( +
+ {onboardingSteps[step]} +
+ ); +}; + +export default OnboardingContainer; diff --git a/src/components/PremiumOnboarding/PremiumWelcome.js b/src/components/PremiumOnboarding/PremiumWelcome.js new file mode 100644 index 0000000..c5fdbc6 --- /dev/null +++ b/src/components/PremiumOnboarding/PremiumWelcome.js @@ -0,0 +1,14 @@ +// PremiumWelcome.js +import React from 'react'; + +const PremiumWelcome = ({ nextStep }) => ( +
+

Welcome to AptivaAI Premium!

+

+ Let's get started by gathering some quick information to personalize your experience. +

+ +
+); + +export default PremiumWelcome; diff --git a/user_profile.db b/user_profile.db index 5853dd7..1aa1b65 100644 Binary files a/user_profile.db and b/user_profile.db differ