Fixed UserProfile values for career_situation
This commit is contained in:
parent
48e68d47b7
commit
146061a9b9
@ -392,9 +392,9 @@ app.get('/api/cip/:socCode', (req, res) => {
|
||||
**************************************************/
|
||||
app.get('/api/schools', (req, res) => {
|
||||
const { cipCode, state } = req.query;
|
||||
console.log('Query Params:', { cipCode, state });
|
||||
console.log('Query Params:', { cipCode });
|
||||
if (!cipCode || !state) {
|
||||
return res.status(400).json({ error: 'CIP Code and State are required.' });
|
||||
return res.status(400).json({ error: 'CIP Code is required' });
|
||||
}
|
||||
try {
|
||||
const matchedCIP = cipCode.replace('.', '').slice(0, 4);
|
||||
|
@ -19,6 +19,7 @@ import PlanningLanding from './components/PlanningLanding.js';
|
||||
import CareerExplorer from './components/CareerExplorer.js';
|
||||
import EducationalPrograms from './components/EducationalPrograms.js';
|
||||
import PreparingLanding from './components/PreparingLanding.js';
|
||||
import EducationalProgramsPage from './components/EducationalProgramsPage.js';
|
||||
import EnhancingLanding from './components/EnhancingLanding.js';
|
||||
import RetirementLanding from './components/RetirementLanding.js';
|
||||
import InterestInventory from './components/InterestInventory.js';
|
||||
@ -244,7 +245,7 @@ function App() {
|
||||
<Route path="/profile" element={<UserProfile />} />
|
||||
<Route path="/planning" element={<PlanningLanding />} />
|
||||
<Route path="/career-explorer" element={<CareerExplorer />} />
|
||||
<Route path="/educational-programs" element={<EducationalPrograms />} />
|
||||
<Route path="/educational-programs" element={<EducationalProgramsPage/>}/>
|
||||
<Route path="/preparing" element={<PreparingLanding />} />
|
||||
<Route path="/enhancing" element={<EnhancingLanding />} />
|
||||
<Route path="/retirement" element={<RetirementLanding />} />
|
||||
|
@ -404,7 +404,7 @@ function CareerExplorer({ }) {
|
||||
: fitRatingMap[career.fit] || masterRatings.interests || 3;
|
||||
|
||||
const meaningRating = parseInt(
|
||||
prompt("How meaningful is this career to you? (1-5):", "3"),
|
||||
prompt("How important do you feel this job is to society or the world? (1-5):", "3"),
|
||||
10
|
||||
);
|
||||
|
||||
|
284
src/components/EducationalProgramsPage.js
Normal file
284
src/components/EducationalProgramsPage.js
Normal file
@ -0,0 +1,284 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
// Your existing search component
|
||||
import CareerSearch from './CareerSearch.js';
|
||||
|
||||
// The existing utility calls
|
||||
import { fetchSchools, clientGeocodeZip, haversineDistance } from '../utils/apiUtils.js';
|
||||
|
||||
// A simple Button component (if you don’t already import from elsewhere)
|
||||
function Button({ onClick, children, ...props }) {
|
||||
return (
|
||||
<button
|
||||
className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-500"
|
||||
onClick={onClick}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* EducationalProgramsPage
|
||||
* - If we have a CIP code (from location.state or otherwise), we fetch + display schools.
|
||||
* - If no CIP code is provided, user sees a CareerSearch to pick a career => sets CIP code.
|
||||
* - Then the user can filter & sort (tuition, distance, optional in-state only).
|
||||
*/
|
||||
function EducationalProgramsPage() {
|
||||
// 1) Get CIP code from React Router location.state (if available)
|
||||
// If no CIP code in route state, default to an empty string
|
||||
const location = useLocation();
|
||||
const [cipCode, setCipCode] = useState(location.state?.cipCode || '');
|
||||
|
||||
// Optionally, you can also read userState / userZip from location.state or from user’s profile
|
||||
const [userState, setUserState] = useState(location.state?.userState || '');
|
||||
const [userZip, setUserZip] = useState(location.state?.userZip || '');
|
||||
|
||||
// ============ Data + UI state ============
|
||||
const [schools, setSchools] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
// Filter states
|
||||
const [sortBy, setSortBy] = useState('tuition'); // 'tuition' or 'distance'
|
||||
const [maxTuition, setMaxTuition] = useState(99999);
|
||||
const [maxDistance, setMaxDistance] = useState(99999);
|
||||
// Optional “in-state only” toggle
|
||||
const [inStateOnly, setInStateOnly] = useState(false);
|
||||
|
||||
// ============ Handle Career Search -> CIP code ============
|
||||
const handleCareerSelected = (foundObj) => {
|
||||
// foundObj = { title, soc_code, cip_code } from CareerSearch
|
||||
if (foundObj?.cip_code) {
|
||||
setCipCode(foundObj.cip_code);
|
||||
}
|
||||
};
|
||||
|
||||
// ============ Fetch + Compute Distance once we have a CIP code ============
|
||||
useEffect(() => {
|
||||
// If no CIP code is set yet, do nothing.
|
||||
if (!cipCode) return;
|
||||
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
// 1) Fetch schools by CIP code (and userState if your API still uses it)
|
||||
const fetchedSchools = await fetchSchools(cipCode, userState);
|
||||
|
||||
// 2) Optionally geocode user ZIP to compute distances
|
||||
let userLat = null;
|
||||
let userLng = null;
|
||||
if (userZip) {
|
||||
try {
|
||||
const geoResult = await clientGeocodeZip(userZip);
|
||||
userLat = geoResult.lat;
|
||||
userLng = geoResult.lng;
|
||||
} catch (geoErr) {
|
||||
console.warn('Unable to geocode user ZIP:', geoErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Compute distance for each school (if lat/lng is available)
|
||||
const schoolsWithDistance = fetchedSchools.map((sch) => {
|
||||
const lat2 = sch.LATITUDE ? parseFloat(sch.LATITUDE) : null;
|
||||
const lon2 = sch.LONGITUD ? parseFloat(sch.LONGITUD) : null;
|
||||
|
||||
if (userLat && userLng && lat2 && lon2) {
|
||||
const distMiles = haversineDistance(userLat, userLng, lat2, lon2);
|
||||
return { ...sch, distance: distMiles.toFixed(1) };
|
||||
} else {
|
||||
return { ...sch, distance: null };
|
||||
}
|
||||
});
|
||||
|
||||
setSchools(schoolsWithDistance);
|
||||
} catch (err) {
|
||||
console.error('Error fetching/processing schools:', err);
|
||||
setError('Failed to load schools.');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [cipCode, userState, userZip]);
|
||||
|
||||
// ============ Filter + Sort ============
|
||||
const filteredAndSortedSchools = useMemo(() => {
|
||||
if (!schools) return [];
|
||||
let result = [...schools];
|
||||
|
||||
// 1) (Optional) In-state only
|
||||
if (inStateOnly && userState) {
|
||||
result = result.filter((sch) => sch.STABBR === userState);
|
||||
}
|
||||
|
||||
// 2) Filter by max tuition
|
||||
// We’ll use “In_state cost” if your data references that, or you can adapt.
|
||||
result = result.filter((sch) => {
|
||||
const inStateCost = sch['In_state cost']
|
||||
? parseFloat(sch['In_state cost'])
|
||||
: 999999;
|
||||
return inStateCost <= maxTuition;
|
||||
});
|
||||
|
||||
// 3) Filter by max distance
|
||||
result = result.filter((sch) => {
|
||||
if (sch.distance === null) {
|
||||
// If distance is unknown, decide if you want to include or exclude it
|
||||
return true; // let’s include unknown
|
||||
}
|
||||
return parseFloat(sch.distance) <= maxDistance;
|
||||
});
|
||||
|
||||
// 4) Sort
|
||||
if (sortBy === 'distance') {
|
||||
result.sort((a, b) => {
|
||||
const distA = a.distance !== null ? parseFloat(a.distance) : Infinity;
|
||||
const distB = b.distance !== null ? parseFloat(b.distance) : Infinity;
|
||||
return distA - distB;
|
||||
});
|
||||
} else {
|
||||
// sort by tuition
|
||||
result.sort((a, b) => {
|
||||
const tA = a['In_state cost'] ? parseFloat(a['In_state cost']) : Infinity;
|
||||
const tB = b['In_state cost'] ? parseFloat(b['In_state cost']) : Infinity;
|
||||
return tA - tB;
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [schools, sortBy, maxTuition, maxDistance, inStateOnly, userState]);
|
||||
|
||||
// ============ Render UI ============
|
||||
|
||||
// 1) If we have NO CIP code yet, show the fallback “CareerSearch”
|
||||
if (!cipCode) {
|
||||
return (
|
||||
<div className="p-4">
|
||||
<h2 className="text-2xl font-bold mb-4">Educational Programs</h2>
|
||||
<p className="mb-4 text-gray-600">
|
||||
You have not selected a career yet. Please search for one below:
|
||||
</p>
|
||||
<CareerSearch onCareerSelected={handleCareerSelected} />
|
||||
<p className="mt-2 text-sm text-gray-500">
|
||||
After you pick a career, we’ll display matching educational programs.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 2) If we DO have a CIP code, show the filterable school list
|
||||
if (loading) {
|
||||
return <div className="p-4">Loading schools...</div>;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="p-4 text-red-600">
|
||||
<p>Error: {error}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<h2 className="text-2xl font-bold mb-4">
|
||||
Schools Offering Programs for CIP: {cipCode}
|
||||
</h2>
|
||||
|
||||
{/* Filter Bar */}
|
||||
<div className="mb-4 flex flex-wrap items-center space-x-4">
|
||||
{/* Sort */}
|
||||
<label className="text-sm text-gray-600">
|
||||
Sort:
|
||||
<select
|
||||
className="ml-2 rounded border px-2 py-1 text-sm"
|
||||
value={sortBy}
|
||||
onChange={(e) => setSortBy(e.target.value)}
|
||||
>
|
||||
<option value="tuition">Tuition</option>
|
||||
<option value="distance">Distance</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
{/* Tuition */}
|
||||
<label className="text-sm text-gray-600">
|
||||
Tuition (max):
|
||||
<input
|
||||
type="number"
|
||||
className="ml-2 w-20 rounded border px-2 py-1 text-sm"
|
||||
value={maxTuition}
|
||||
onChange={(e) => setMaxTuition(Number(e.target.value))}
|
||||
/>
|
||||
</label>
|
||||
|
||||
{/* Distance */}
|
||||
<label className="text-sm text-gray-600">
|
||||
Distance (max):
|
||||
<input
|
||||
type="number"
|
||||
className="ml-2 w-20 rounded border px-2 py-1 text-sm"
|
||||
value={maxDistance}
|
||||
onChange={(e) => setMaxDistance(Number(e.target.value))}
|
||||
/>
|
||||
</label>
|
||||
|
||||
{/* Optional: In-State Only Toggle */}
|
||||
{userState && (
|
||||
<label className="inline-flex items-center space-x-2 text-sm text-gray-600">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={inStateOnly}
|
||||
onChange={(e) => setInStateOnly(e.target.checked)}
|
||||
/>
|
||||
<span>In-State Only</span>
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* School List */}
|
||||
{filteredAndSortedSchools.length > 0 ? (
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{filteredAndSortedSchools.map((school, idx) => (
|
||||
<div key={idx} className="rounded border p-3 text-sm">
|
||||
<strong>{school['INSTNM'] || 'Unnamed School'}</strong>
|
||||
<p>Degree Type: {school['CREDDESC'] || 'N/A'}</p>
|
||||
<p>In-State Tuition: ${school['In_state cost'] || 'N/A'}</p>
|
||||
<p>Out-of-State Tuition: ${school['Out_state cost'] || 'N/A'}</p>
|
||||
<p>
|
||||
Distance:{' '}
|
||||
{school.distance !== null ? `${school.distance} mi` : 'N/A'}
|
||||
</p>
|
||||
<p>
|
||||
Website:{' '}
|
||||
{school['Website'] ? (
|
||||
<a
|
||||
href={school['Website']}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-600 hover:underline"
|
||||
>
|
||||
{school['Website']}
|
||||
</a>
|
||||
) : (
|
||||
'N/A'
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-gray-500">
|
||||
No schools matching your filters.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default EducationalProgramsPage;
|
@ -252,7 +252,7 @@ function SignUp() {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<h2 className="mb-4 text-xl font-semibold text-center">Choose Your Career Stage</h2>
|
||||
<h2 className="mb-4 text-xl font-semibold text-center">Where are you in your career journey right now?</h2>
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
{careerSituations.map((situation) => (
|
||||
<SituationCard
|
||||
|
@ -15,6 +15,7 @@ function UserProfile() {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Helper to do authorized fetch
|
||||
const authFetch = async (url, options = {}) => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (!token) {
|
||||
@ -48,10 +49,6 @@ function UserProfile() {
|
||||
|
||||
const res = await authFetch('/api/user-profile', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!res || !res.ok) return;
|
||||
@ -70,6 +67,7 @@ function UserProfile() {
|
||||
setIsPremiumUser(true);
|
||||
}
|
||||
|
||||
// If we have a state, load its areas
|
||||
if (data.state) {
|
||||
setLoadingAreas(true);
|
||||
try {
|
||||
@ -92,8 +90,10 @@ function UserProfile() {
|
||||
};
|
||||
|
||||
fetchProfileAndAreas();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []); // only runs once
|
||||
|
||||
// Whenever user changes "selectedState", re-fetch areas
|
||||
useEffect(() => {
|
||||
const fetchAreasByState = async () => {
|
||||
if (!selectedState) {
|
||||
@ -144,9 +144,6 @@ function UserProfile() {
|
||||
try {
|
||||
const response = await authFetch('/api/user-profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(profileData),
|
||||
});
|
||||
|
||||
@ -159,59 +156,45 @@ function UserProfile() {
|
||||
}
|
||||
};
|
||||
|
||||
// FULL list of states, including all 50 states (+ DC if desired)
|
||||
// FULL list of states for your dropdown
|
||||
const states = [
|
||||
{ name: 'Alabama', code: 'AL' },
|
||||
{ name: 'Alaska', code: 'AK' },
|
||||
{ name: 'Arizona', code: 'AZ' },
|
||||
{ name: 'Arkansas', code: 'AR' },
|
||||
{ name: 'California', code: 'CA' },
|
||||
{ name: 'Colorado', code: 'CO' },
|
||||
{ name: 'Connecticut', code: 'CT' },
|
||||
{ name: 'Delaware', code: 'DE' },
|
||||
{ name: 'District of Columbia', code: 'DC' },
|
||||
{ name: 'Florida', code: 'FL' },
|
||||
{ name: 'Georgia', code: 'GA' },
|
||||
{ name: 'Hawaii', code: 'HI' },
|
||||
{ name: 'Idaho', code: 'ID' },
|
||||
{ name: 'Illinois', code: 'IL' },
|
||||
{ name: 'Indiana', code: 'IN' },
|
||||
{ name: 'Iowa', code: 'IA' },
|
||||
{ name: 'Kansas', code: 'KS' },
|
||||
{ name: 'Kentucky', code: 'KY' },
|
||||
{ name: 'Louisiana', code: 'LA' },
|
||||
{ name: 'Maine', code: 'ME' },
|
||||
{ name: 'Maryland', code: 'MD' },
|
||||
{ name: 'Massachusetts', code: 'MA' },
|
||||
{ name: 'Michigan', code: 'MI' },
|
||||
{ name: 'Minnesota', code: 'MN' },
|
||||
{ name: 'Mississippi', code: 'MS' },
|
||||
{ name: 'Missouri', code: 'MO' },
|
||||
{ name: 'Montana', code: 'MT' },
|
||||
{ name: 'Nebraska', code: 'NE' },
|
||||
{ name: 'Nevada', code: 'NV' },
|
||||
{ name: 'New Hampshire', code: 'NH' },
|
||||
{ name: 'New Jersey', code: 'NJ' },
|
||||
{ name: 'New Mexico', code: 'NM' },
|
||||
{ name: 'New York', code: 'NY' },
|
||||
{ name: 'North Carolina', code: 'NC' },
|
||||
{ name: 'North Dakota', code: 'ND' },
|
||||
{ name: 'Ohio', code: 'OH' },
|
||||
{ name: 'Oklahoma', code: 'OK' },
|
||||
{ name: 'Oregon', code: 'OR' },
|
||||
{ name: 'Pennsylvania', code: 'PA' },
|
||||
{ name: 'Rhode Island', code: 'RI' },
|
||||
{ name: 'South Carolina', code: 'SC' },
|
||||
{ name: 'South Dakota', code: 'SD' },
|
||||
{ name: 'Tennessee', code: 'TN' },
|
||||
{ name: 'Texas', code: 'TX' },
|
||||
{ name: 'Utah', code: 'UT' },
|
||||
{ name: 'Vermont', code: 'VT' },
|
||||
{ name: 'Virginia', code: 'VA' },
|
||||
{ name: 'Washington', code: 'WA' },
|
||||
{ name: 'West Virginia', code: 'WV' },
|
||||
{ name: 'Wisconsin', code: 'WI' },
|
||||
{ name: 'Wyoming', code: 'WY' },
|
||||
{ name: 'Alabama', code: 'AL' }, { name: 'Alaska', code: 'AK' }, { name: 'Arizona', code: 'AZ' },
|
||||
{ name: 'Arkansas', code: 'AR' }, { name: 'California', code: 'CA' }, { name: 'Colorado', code: 'CO' },
|
||||
{ name: 'Connecticut', code: 'CT' }, { name: 'Delaware', code: 'DE' }, { name: 'District of Columbia', code: 'DC' },
|
||||
{ name: 'Florida', code: 'FL' }, { name: 'Georgia', code: 'GA' }, { name: 'Hawaii', code: 'HI' },
|
||||
{ name: 'Idaho', code: 'ID' }, { name: 'Illinois', code: 'IL' }, { name: 'Indiana', code: 'IN' },
|
||||
{ name: 'Iowa', code: 'IA' }, { name: 'Kansas', code: 'KS' }, { name: 'Kentucky', code: 'KY' },
|
||||
{ name: 'Louisiana', code: 'LA' }, { name: 'Maine', code: 'ME' }, { name: 'Maryland', code: 'MD' },
|
||||
{ name: 'Massachusetts', code: 'MA' }, { name: 'Michigan', code: 'MI' }, { name: 'Minnesota', code: 'MN' },
|
||||
{ name: 'Mississippi', code: 'MS' }, { name: 'Missouri', code: 'MO' }, { name: 'Montana', code: 'MT' },
|
||||
{ name: 'Nebraska', code: 'NE' }, { name: 'Nevada', code: 'NV' }, { name: 'New Hampshire', code: 'NH' },
|
||||
{ name: 'New Jersey', code: 'NJ' }, { name: 'New Mexico', code: 'NM' }, { name: 'New York', code: 'NY' },
|
||||
{ name: 'North Carolina', code: 'NC' }, { name: 'North Dakota', code: 'ND' }, { name: 'Ohio', code: 'OH' },
|
||||
{ name: 'Oklahoma', code: 'OK' }, { name: 'Oregon', code: 'OR' }, { name: 'Pennsylvania', code: 'PA' },
|
||||
{ name: 'Rhode Island', code: 'RI' }, { name: 'South Carolina', code: 'SC' }, { name: 'South Dakota', code: 'SD' },
|
||||
{ name: 'Tennessee', code: 'TN' }, { name: 'Texas', code: 'TX' }, { name: 'Utah', code: 'UT' },
|
||||
{ name: 'Vermont', code: 'VT' }, { name: 'Virginia', code: 'VA' }, { name: 'Washington', code: 'WA' },
|
||||
{ name: 'West Virginia', code: 'WV' }, { name: 'Wisconsin', code: 'WI' }, { name: 'Wyoming', code: 'WY' },
|
||||
];
|
||||
|
||||
// The updated career situations (same as in SignUp.js)
|
||||
const careerSituations = [
|
||||
{
|
||||
id: 'planning',
|
||||
title: 'Planning Your Career',
|
||||
},
|
||||
{
|
||||
id: 'preparing',
|
||||
title: 'Preparing for Your (Next) Career',
|
||||
},
|
||||
{
|
||||
id: 'enhancing',
|
||||
title: 'Enhancing Your Career',
|
||||
},
|
||||
{
|
||||
id: 'retirement',
|
||||
title: 'Retirement Planning',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
@ -296,54 +279,52 @@ function UserProfile() {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{loadingAreas && <p className="text-sm text-gray-500">Loading areas...</p>}
|
||||
|
||||
{/* Areas Dropdown */}
|
||||
{loadingAreas ? (
|
||||
{/* Loading indicator for areas */}
|
||||
{loadingAreas && (
|
||||
<p className="text-sm text-gray-500">Loading areas...</p>
|
||||
) : (
|
||||
areas.length > 0 && (
|
||||
<div>
|
||||
<label className="mb-1 block text-sm font-medium text-gray-700">
|
||||
Area:
|
||||
</label>
|
||||
<select
|
||||
value={selectedArea}
|
||||
onChange={(e) => setSelectedArea(e.target.value)}
|
||||
required
|
||||
className="w-full rounded border border-gray-300 px-3 py-2 text-sm focus:border-blue-600 focus:outline-none"
|
||||
>
|
||||
<option value="">Select an Area</option>
|
||||
{areas.map((area, index) => (
|
||||
<option key={index} value={area}>
|
||||
{area}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
|
||||
{/* Premium-Only Field */}
|
||||
{isPremiumUser && (
|
||||
{/* Areas Dropdown */}
|
||||
{!loadingAreas && areas.length > 0 && (
|
||||
<div>
|
||||
<label className="mb-1 block text-sm font-medium text-gray-700">
|
||||
What best describes your current career situation?
|
||||
Area:
|
||||
</label>
|
||||
<select
|
||||
value={careerSituation}
|
||||
onChange={(e) => setCareerSituation(e.target.value)}
|
||||
value={selectedArea}
|
||||
onChange={(e) => setSelectedArea(e.target.value)}
|
||||
required
|
||||
className="w-full rounded border border-gray-300 px-3 py-2 text-sm focus:border-blue-600 focus:outline-none"
|
||||
>
|
||||
<option value="">Select One</option>
|
||||
<option value="highSchool">High School Student</option>
|
||||
<option value="collegeStudent">College Student</option>
|
||||
<option value="transitioningPro">Transitioning Professional</option>
|
||||
<option value="advancingPro">Advancing Professional</option>
|
||||
<option value="">Select an Area</option>
|
||||
{areas.map((area, index) => (
|
||||
<option key={index} value={area}>
|
||||
{area}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Career Situation */}
|
||||
<div>
|
||||
<label className="mb-1 block text-sm font-medium text-gray-700">
|
||||
What best describes your current career situation?
|
||||
</label>
|
||||
<select
|
||||
value={careerSituation}
|
||||
onChange={(e) => setCareerSituation(e.target.value)}
|
||||
className="w-full rounded border border-gray-300 px-3 py-2 text-sm focus:border-blue-600 focus:outline-none"
|
||||
>
|
||||
<option value="">Select One</option>
|
||||
{careerSituations.map((cs) => (
|
||||
<option key={cs.id} value={cs.id}>
|
||||
{cs.title}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Form Buttons */}
|
||||
<div className="mt-6 flex items-center justify-end space-x-3">
|
||||
<button
|
||||
|
@ -48,13 +48,12 @@ export function haversineDistance(lat1, lon1, lat2, lon2) {
|
||||
}
|
||||
|
||||
// Fetch schools
|
||||
export const fetchSchools = async (cipCode, state = '', level = '', type = '') => {
|
||||
export const fetchSchools = async (cipCode) => {
|
||||
try {
|
||||
const apiUrl = process.env.REACT_APP_API_URL || '';
|
||||
const response = await axios.get(`${apiUrl}/schools`, {
|
||||
params: {
|
||||
cipCode,
|
||||
state,
|
||||
cipCode
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
[
|
||||
{
|
||||
"soc_code": "19-4071.00",
|
||||
"title": "Forest and Conservation Technicians",
|
||||
"ratings": {
|
||||
"growth": 1,
|
||||
"balance": 3,
|
||||
"recognition": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"soc_code": "15-1241.00",
|
||||
"title": "Computer Network Architects",
|
||||
"ratings": {
|
||||
"growth": 5,
|
||||
"balance": 4,
|
||||
"recognition": 3
|
||||
}
|
||||
}
|
||||
]
|
BIN
user_profile.db
BIN
user_profile.db
Binary file not shown.
Loading…
Reference in New Issue
Block a user