// src/components/MilestoneAddModal.js import React, { useState, useEffect } from 'react'; import authFetch from '../utils/authFetch.js'; /* ───────────────────────────────────────────────────────── CONSTANTS ───────────────────────────────────────────────────────── */ const IMPACT_TYPES = ['salary', 'cost', 'tuition', 'note']; const FREQ_OPTIONS = ['ONE_TIME', 'MONTHLY']; export default function MilestoneAddModal({ show, onClose, scenarioId, // active scenario UUID editMilestone = null // pass full row when editing }) { /* ────────────── state ────────────── */ const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const [impacts, setImpacts] = useState([]); /* ────────────── init / reset ────────────── */ useEffect(() => { if (!show) return; if (editMilestone) { setTitle(editMilestone.title || ''); setDescription(editMilestone.description || ''); setImpacts(editMilestone.impacts || []); } else { setTitle(''); setDescription(''); setImpacts([]); } }, [show, editMilestone]); /* ────────────── helpers ────────────── */ const addImpactRow = () => setImpacts(prev => [ ...prev, { impact_type : 'cost', frequency : 'ONE_TIME', direction : 'subtract', amount : 0, start_date : '', // ISO yyyy‑mm‑dd end_date : '' // blank ⇒ indefinite } ]); const updateImpact = (idx, field, value) => setImpacts(prev => { const copy = [...prev]; copy[idx] = { ...copy[idx], [field]: value }; return copy; }); const removeImpact = idx => setImpacts(prev => prev.filter((_, i) => i !== idx)); /* ────────────── save ────────────── */ async function handleSave() { try { /* 1️⃣ create OR update the milestone row */ let milestoneId = editMilestone?.id; if (milestoneId) { await authFetch(`api/premium/milestones/${milestoneId}`, { method : 'PUT', headers: { 'Content-Type':'application/json' }, body : JSON.stringify({ title, description }) }); } else { const res = await authFetch('api/premium/milestones', { method : 'POST', headers: { 'Content-Type':'application/json' }, body : JSON.stringify({ title, description, career_profile_id: scenarioId }) }); if (!res.ok) throw new Error('Milestone create failed'); const json = await res.json(); milestoneId = json.id ?? json[0]?.id; // array OR obj } /* 2️⃣ upsert each impact (one call per row) */ for (const imp of impacts) { const body = { milestone_id : milestoneId, impact_type : imp.impact_type, frequency : imp.frequency, // ONE_TIME / MONTHLY direction : imp.direction, amount : parseFloat(imp.amount) || 0, start_date : imp.start_date || null, end_date : imp.frequency === 'MONTHLY' && imp.end_date ? imp.end_date : null }; await authFetch('api/premium/milestone-impacts', { method : 'POST', headers: { 'Content-Type':'application/json' }, body : JSON.stringify(body) }); } onClose(true); // ← parent will refetch } catch (err) { console.error('Save failed:', err); alert('Sorry, something went wrong – please try again.'); } } /* ────────────── UI ────────────── */ if (!show) return null; return (