dev1/src/components/CollegeProfileList.js

188 lines
6.9 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.

// src/components/CollegeProfileList.js
import React, { useEffect, useState } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import CareerSelectDropdown from "./CareerSelectDropdown.js";
import apiFetch from '../auth/apiFetch.js';
export default function CollegeProfileList() {
const { careerId } = useParams(); // may be undefined
const navigate = useNavigate();
/* ───────── existing lists ───────── */
const [rows, setRows] = useState([]);
const [careerRows, setCareerRows] = useState([]);
/* ───────── ui state ───────── */
const [showPicker, setShowPicker] = useState(false);
const [loadingCareers, setLoadingCareers] = useState(true);
const authFetch = apiFetch;
/* ───────── load college plans ───────── */
/* ───────── load college plans ───────── */
useEffect(() => {
(async () => {
try {
const r = await authFetch("/api/premium/college-profile/all");
if (!r.ok) throw new Error(`load college-profile/all → ${r.status}`);
const d = await r.json();
setRows(d.collegeProfiles || []);
} catch (err) {
console.error("College profiles load failed:", err);
setRows([]);
}
})();
}, []);
/* ───────── load career profiles for the picker ───────── */
useEffect(() => {
(async () => {
try {
const res = await authFetch("/api/premium/career-profile/all");
if (!res.ok) throw new Error(`load career-profile/all → ${res.status}`);
const data = await res.json();
setCareerRows(data.careerProfiles || []);
} catch (err) {
console.error("Career profiles load failed:", err);
} finally {
setLoadingCareers(false);
}
})();
}, []);
/* ───────── delete helper ───────── */
async function handleDelete(row) {
if (!window.confirm("Delete this college plan?")) return;
try {
const res = await authFetch(`/api/premium/college-profile/by-fields`, {
method: "DELETE",
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
career_title : row.career_title || null,
selected_school: row.selected_school || null,
selected_program: row.selected_program || null,
created_at : row.created_at || null // optional disambiguator
})
});
if (!res.ok) throw new Error(`delete failed → ${res.status}`);
setRows((r) => r.filter(x =>
!(
(x.career_title||'') === (row.career_title||'') &&
(x.selected_school||'') === (row.selected_school||'') &&
(x.selected_program||'')=== (row.selected_program||'') &&
(x.created_at||'') === (row.created_at||'')
)
));
if (!res.ok) throw new Error(`delete failed → ${res.status}`);
setRows((r) => r.filter(x =>
!(
(x.career_title||'') === (row.career_title||'') &&
(x.selected_school||'') === (row.selected_school||'') &&
(x.selected_program||'')=== (row.selected_program||'') &&
(x.created_at||'') === (row.created_at||'')
)
));
} catch (err) {
console.error("Delete failed:", err);
alert("Could not delete see console.");
}
}
return (
<div className="max-w-5xl mx-auto space-y-6">
{/* ───────── header row ───────── */}
<div className="flex items-center justify-between">
<h2 className="text-2xl font-semibold">College Plans</h2>
{/* newplan button & inline picker */}
{!showPicker ? (
<button
onClick={() => setShowPicker(true)}
className="px-3 py-2 bg-blue-600 text-white rounded"
>
+ New College Plan
</button>
) : (
<div className="p-4 border rounded bg-gray-50 max-w-md">
<CareerSelectDropdown
existingCareerProfiles={careerRows}
selectedCareer={null}
loading={loadingCareers}
authFetch={authFetch}
onChange={(careerObj) => {
if (!careerObj) return;
const title = careerObj.scenario_title || careerObj.career_name || '';
const start = careerObj.start_date || '';
navigate(`/profile/college/new?career=${encodeURIComponent(title)}&start=${encodeURIComponent(start)}`);
}}
/>
<div className="mt-2 text-right">
<button
onClick={() => setShowPicker(false)}
className="text-sm text-gray-600 underline"
>
cancel
</button>
</div>
</div>
)}
</div>
{/* ───────── table of existing college plans ───────── */}
<table className="w-full border text-sm">
<thead className="bg-gray-100">
<tr>
<th className="p-2 text-left">Career</th>
<th className="p-2 text-left">School</th>
<th className="p-2 text-left">Program</th>
<th className="p-2">Created</th>
<th className="p-2"></th>
</tr>
</thead>
<tbody>
{rows.map((r) => (
<tr key={`${r.career_title}|${r.selected_school}|${r.selected_program}|${r.created_at}`} className="border-t">
<td className="p-2">{r.career_title}</td>
<td className="p-2">{r.selected_school}</td>
<td className="p-2">{r.selected_program}</td>
<td className="p-2">{r.created_at?.slice(0, 10)}</td>
<td className="p-2 space-x-2 whitespace-nowrap">
<Link
to={`/profile/college/${encodeURIComponent(r.career_profile_id)}/edit`}
className="underline text-blue-600"
>edit</Link>
<button
onClick={() => handleDelete(r)}
className="underline text-red-600"
>
delete
</button>
</td>
</tr>
))}
{rows.length === 0 && (
<tr>
<td colSpan={6} className="p-8 text-center text-gray-500">
No college profiles yet.&nbsp;
<button
className="text-blue-600 underline"
onClick={() =>
careerId
? navigate(`/profile/college/${careerId}/new`)
: setShowPicker(true)
}
>
Create one now.
</button>
</td>
</tr>
)}
</tbody>
</table>
</div>
);
}