127 lines
3.9 KiB
JavaScript
127 lines
3.9 KiB
JavaScript
// src/components/AISuggestedMilestones.js
|
||
import React, { useEffect, useState } from 'react';
|
||
|
||
|
||
const AISuggestedMilestones = ({ userId, career, careerPathId, authFetch, activeView, projectionData }) => {
|
||
const [suggestedMilestones, setSuggestedMilestones] = useState([]);
|
||
const [selected, setSelected] = useState([]);
|
||
const [loading, setLoading] = useState(false);
|
||
|
||
useEffect(() => {
|
||
if (!Array.isArray(projectionData)) {
|
||
console.warn('⚠️ projectionData is not an array:', projectionData);
|
||
return;
|
||
}
|
||
|
||
console.log('📊 projectionData sample:', projectionData.slice(0, 3));
|
||
}, [projectionData]);
|
||
|
||
|
||
useEffect(() => {
|
||
if (!career || !Array.isArray(projectionData)) return;
|
||
|
||
// Dynamically suggest milestones based on projection data
|
||
const suggested = [];
|
||
|
||
// Find salary or savings growth points from projectionData:
|
||
projectionData.forEach((monthData, index) => {
|
||
if (index === 0) return; // Skip first month for comparison
|
||
const prevMonth = projectionData[index - 1];
|
||
|
||
// Example logic: suggest milestones when retirement savings hit certain thresholds
|
||
if (monthData.totalRetirementSavings >= 50000 && prevMonth.totalRetirementSavings < 50000) {
|
||
suggested.push({
|
||
title: `Reach $50k Retirement Savings`,
|
||
date: monthData.month + '-01',
|
||
progress: 0,
|
||
});
|
||
}
|
||
|
||
// Milestone when loan is paid off
|
||
if (monthData.loanBalance <= 0 && prevMonth.loanBalance > 0) {
|
||
suggested.push({
|
||
title: `Student Loans Paid Off`,
|
||
date: monthData.month + '-01',
|
||
progress: 0,
|
||
});
|
||
}
|
||
});
|
||
|
||
// Career-based suggestions still possible (add explicitly if desired)
|
||
suggested.push(
|
||
{ title: `Entry-Level ${career}`, date: projectionData[6]?.month + '-01' || '2025-06-01', progress: 0 },
|
||
{ title: `Mid-Level ${career}`, date: projectionData[24]?.month + '-01' || '2027-01-01', progress: 0 },
|
||
{ title: `Senior-Level ${career}`, date: projectionData[60]?.month + '-01' || '2030-01-01', progress: 0 }
|
||
);
|
||
|
||
setSuggestedMilestones(suggested);
|
||
setSelected([]);
|
||
}, [career, projectionData]);
|
||
|
||
|
||
const toggleSelect = (index) => {
|
||
setSelected(prev =>
|
||
prev.includes(index) ? prev.filter(i => i !== index) : [...prev, index]
|
||
);
|
||
};
|
||
|
||
const confirmSelectedMilestones = async () => {
|
||
const milestonesToSend = selected.map(index => {
|
||
const m = suggestedMilestones[index];
|
||
return {
|
||
title: m.title,
|
||
description: m.title,
|
||
date: m.date,
|
||
progress: m.progress,
|
||
milestone_type: activeView || 'Career',
|
||
career_path_id: careerPathId,
|
||
};
|
||
});
|
||
|
||
try {
|
||
setLoading(true);
|
||
const res = await authFetch(`/api/premium/milestone`, {
|
||
method: 'POST',
|
||
body: JSON.stringify({ milestones: milestonesToSend }),
|
||
headers: { 'Content-Type': 'application/json' },
|
||
});
|
||
|
||
if (!res.ok) throw new Error('Failed to save selected milestones');
|
||
const data = await res.json();
|
||
console.log('Confirmed milestones:', data);
|
||
setSelected([]); // Clear selection
|
||
window.location.reload();
|
||
} catch (error) {
|
||
console.error('Error saving selected milestones:', error);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
|
||
if (!suggestedMilestones.length) return null;
|
||
|
||
return (
|
||
<div className="suggested-milestones">
|
||
<h4>AI-Suggested Milestones</h4>
|
||
<ul>
|
||
{suggestedMilestones.map((m, i) => (
|
||
<li key={i}>
|
||
<input
|
||
type="checkbox"
|
||
checked={selected.includes(i)}
|
||
onChange={() => toggleSelect(i)}
|
||
/>
|
||
{m.title} – {m.date}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
<button onClick={confirmSelectedMilestones} disabled={loading || selected.length === 0}>
|
||
{loading ? 'Saving...' : 'Confirm Selected'}
|
||
</button>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default AISuggestedMilestones;
|