dev1/src/components/CareerProfileForm.js
2025-08-21 16:45:02 +00:00

237 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 repick
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. DataScientist 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 datascientist 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>
);
}