237 lines
7.7 KiB
JavaScript
237 lines
7.7 KiB
JavaScript
// CareerProfileForm.js
|
||
import React, { useEffect, useState } from 'react';
|
||
import { useNavigate, useParams } from 'react-router-dom';
|
||
import authFetch from '../utils/authFetch.js';
|
||
import CareerSearch from './CareerSearch.js'; // ← same component as onboarding
|
||
|
||
export default function CareerProfileForm() {
|
||
const { id } = useParams(); // "new" or an existing uuid
|
||
const nav = useNavigate();
|
||
|
||
/* ---------- 1. local state ---------- */
|
||
const [form, setForm] = useState({
|
||
scenario_title : '',
|
||
career_name : '',
|
||
soc_code : '',
|
||
status : 'current',
|
||
start_date : '',
|
||
retirement_start_date : '',
|
||
college_enrollment_status : '',
|
||
career_goals : '',
|
||
desired_retirement_income_monthly : ''
|
||
});
|
||
|
||
const [careerLocked, setCareerLocked] = useState(id !== 'new'); // lock unless new
|
||
|
||
/* ---------- 2. helpers ---------- */
|
||
const handleChange = e =>
|
||
setForm(prev => ({ ...prev, [e.target.name]: e.target.value }));
|
||
|
||
const handleCareerSelected = obj => {
|
||
// obj = { title, soc_code, … }
|
||
setForm(prev => ({
|
||
...prev,
|
||
career_name : obj.title,
|
||
soc_code : obj.soc_code
|
||
}));
|
||
setCareerLocked(true);
|
||
};
|
||
|
||
const unlockCareer = () => {
|
||
// allow user to re‑pick
|
||
setCareerLocked(false);
|
||
setForm(prev => ({ ...prev, career_name: '', soc_code: '' }));
|
||
};
|
||
|
||
/* ---------- 3. load an existing row (edit mode) ---------- */
|
||
useEffect(() => {
|
||
if (id === 'new') return;
|
||
(async () => {
|
||
const res = await authFetch(`/api/premium/career-profile/${id}`);
|
||
if (!res.ok) return;
|
||
const d = await res.json();
|
||
setForm(prev => ({
|
||
...prev,
|
||
scenario_title : d.scenario_title ?? '',
|
||
career_name : d.career_name ?? '',
|
||
soc_code : d.soc_code ?? '',
|
||
status : d.status ?? 'current',
|
||
start_date : (d.start_date || '').slice(0, 10), // ← trim
|
||
retirement_start_date : (d.retirement_start_date || '').slice(0, 10),
|
||
college_enrollment_status : d.college_enrollment_status ?? '',
|
||
career_goals : d.career_goals ?? '',
|
||
desired_retirement_income_monthly :
|
||
d.desired_retirement_income_monthly ?? ''
|
||
}));
|
||
})();
|
||
}, [id]);
|
||
|
||
/* ---------- 4. save ---------- */
|
||
async function save() {
|
||
if (!careerLocked && !form.soc_code) {
|
||
alert('Please pick a valid career from the list first.');
|
||
return;
|
||
}
|
||
try {
|
||
const res = await authFetch('/api/premium/career-profile', {
|
||
method : 'POST',
|
||
headers : { 'Content-Type': 'application/json' },
|
||
body : JSON.stringify({
|
||
...form,
|
||
start_date : form.start_date?.slice(0, 10) || null,
|
||
retirement_start_date : form.retirement_start_date?.slice(0, 10) || null,
|
||
id: id === 'new' ? undefined : id // upsert
|
||
})
|
||
});
|
||
if (!res.ok) throw new Error(await res.text());
|
||
const data = await res.json(); // { career_profile_id: '...' }
|
||
const activeId = data.career_profile_id || id; // handle edit vs new
|
||
localStorage.setItem('lastSelectedCareerProfileId', activeId);
|
||
nav(`/career-roadmap/${activeId}`, { replace: true }); // guarantees Roadmap selects this one
|
||
} catch (err) {
|
||
console.error(err);
|
||
alert(err.message);
|
||
}
|
||
}
|
||
|
||
/* ---------- 5. render ---------- */
|
||
return (
|
||
<div className="max-w-lg mx-auto space-y-4">
|
||
<h2 className="text-2xl font-semibold">
|
||
{id === 'new' ? 'New' : 'Edit'} Career Profile
|
||
</h2>
|
||
|
||
{/* Scenario title */}
|
||
<label className="block">
|
||
<span className="font-medium">Scenario Title</span>
|
||
<input
|
||
name="scenario_title"
|
||
className="mt-1 w-full border rounded p-2"
|
||
placeholder="e.g. Data‑Scientist Plan"
|
||
value={form.scenario_title}
|
||
onChange={handleChange}
|
||
/>
|
||
</label>
|
||
|
||
{/* Career picker (locked vs editable) */}
|
||
<label className="block font-medium">Career *</label>
|
||
{careerLocked ? (
|
||
<div className="flex items-center space-x-2">
|
||
<input
|
||
className="flex-1 border rounded p-2 bg-gray-100"
|
||
value={form.career_name}
|
||
disabled
|
||
/>
|
||
<button
|
||
type="button"
|
||
className="text-blue-600 underline text-sm"
|
||
onClick={unlockCareer}
|
||
>
|
||
Change
|
||
</button>
|
||
</div>
|
||
) : (
|
||
<CareerSearch onCareerSelected={handleCareerSelected} required />
|
||
)}
|
||
|
||
{/* Status */}
|
||
<label className="block">
|
||
<span className="font-medium">Status</span>
|
||
<select
|
||
name="status"
|
||
className="mt-1 w-full border rounded p-2"
|
||
value={form.status}
|
||
onChange={handleChange}
|
||
>
|
||
<option value="current">current</option>
|
||
<option value="future">future</option>
|
||
<option value="retired">retired</option>
|
||
</select>
|
||
</label>
|
||
|
||
{/* Dates */}
|
||
<label className="block">
|
||
<span className="font-medium">Start Date</span>
|
||
<input
|
||
type="date"
|
||
name="start_date"
|
||
className="mt-1 w-full border rounded p-2"
|
||
value={form.start_date}
|
||
onChange={handleChange}
|
||
/>
|
||
</label>
|
||
|
||
<label className="block">
|
||
<span className="font-medium">Retirement Start Date</span>
|
||
<input
|
||
type="date"
|
||
name="retirement_start_date"
|
||
className="mt-1 w-full border rounded p-2"
|
||
value={form.retirement_start_date}
|
||
onChange={handleChange}
|
||
/>
|
||
</label>
|
||
|
||
{/* College status */}
|
||
<label className="block">
|
||
<span className="font-medium">College Enrollment Status</span>
|
||
<select
|
||
name="college_enrollment_status"
|
||
className="mt-1 w-full border rounded p-2"
|
||
value={form.college_enrollment_status}
|
||
onChange={handleChange}
|
||
>
|
||
<option value="">-- select --</option>
|
||
<option value="not_enrolled">Not Enrolled / Not Planning</option>
|
||
<option value="currently_enrolled">Currently Enrolled</option>
|
||
<option value="prospective_student">Planning to Enroll (Prospective)</option>
|
||
</select>
|
||
</label>
|
||
|
||
{/* Career goals */}
|
||
<label className="block">
|
||
<span className="font-medium">Career Goals</span>
|
||
<textarea
|
||
rows={3}
|
||
name="career_goals"
|
||
className="mt-1 w-full border rounded p-2"
|
||
placeholder="e.g. Become a senior data‑scientist in five years…"
|
||
value={form.career_goals}
|
||
onChange={handleChange}
|
||
/>
|
||
</label>
|
||
|
||
{/* Desired retirement income */}
|
||
<label className="block">
|
||
<span className="font-medium">Desired Retirement Income / Month ($)</span>
|
||
<input
|
||
type="number"
|
||
name="desired_retirement_income_monthly"
|
||
className="mt-1 w-full border rounded p-2"
|
||
placeholder="e.g. 6000"
|
||
value={form.desired_retirement_income_monthly}
|
||
onChange={handleChange}
|
||
/>
|
||
</label>
|
||
|
||
{/* Action buttons */}
|
||
<div className="pt-4 flex justify-between">
|
||
<button
|
||
type="button"
|
||
onClick={() => nav(-1)}
|
||
className="bg-gray-200 hover:bg-gray-300 text-gray-700 font-semibold py-2 px-4 rounded"
|
||
>
|
||
← Back
|
||
</button>
|
||
<button
|
||
type="button"
|
||
onClick={save}
|
||
className="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded"
|
||
>
|
||
Save
|
||
</button>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|