+ {memoizedPopoutPanel}
- {/* Pass context to Chatbot */}
-
-
Career results and RIASEC scores are provided by
O*Net, in conjunction with the
diff --git a/src/components/MilestoneTracker.js b/src/components/MilestoneTracker.js
deleted file mode 100644
index 1d071f3..0000000
--- a/src/components/MilestoneTracker.js
+++ /dev/null
@@ -1,226 +0,0 @@
-import React, { useState } from "react";
-import { Card, CardContent } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { Progress } from "@/components/ui/progress";
-import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
-import { CheckCircle, Clock, Target, PlusCircle, Search } from "lucide-react";
-import { Input } from "@/components/ui/input";
-import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
-
-
-
-const MilestoneTracker = () => {
- const location = useLocation();
- const initialCareer = location.state?.career || "";
- const [careerClusters, setCareerClusters] = useState({});
- const [selectedCluster, setSelectedCluster] = useState(null);
- const [selectedSubdivision, setSelectedSubdivision] = useState(null);
- const [selectedCareer, setSelectedCareer] = useState(initialCareer);
- const [filteredClusters, setFilteredClusters] = useState([]);
- const [activeTab, setActiveTab] = useState("career");
- const [customMilestones, setCustomMilestones] = useState({ career: [], financial: [], retirement: [] });
- const [isDialogOpen, setIsDialogOpen] = useState(false);
- const [newMilestone, setNewMilestone] = useState("");
- const [careerSearch, setCareerSearch] = useState("");
- const [filteredCareers, setFilteredCareers] = useState(careerClusters);
-
-
- useEffect(() => {
- const fetchUserProfile = async () => {
- try {
- const response = await fetch("/api/user/profile", {
- method: "GET",
- credentials: "include", // Ensure cookies/session are sent
- });
- if (response.ok) {
- const data = await response.json();
- setIsPremiumUser(data.is_premium === 1); // Expecting { is_premium: 0 or 1 }
- } else {
- setIsPremiumUser(false); // Default to false if there's an error
- }
- } catch (error) {
- console.error("Error fetching user profile:", error);
- setIsPremiumUser(false);
- }
- };
- fetchUserProfile();
- }, []);
-
- if (isPremiumUser === null) {
- return
Loading...
; // Show loading state while fetching
- }
-
- if (!isPremiumUser) {
- return (
-
-
-
Access Restricted
-
Upgrade to Aptiva Premium to access the Milestone Tracker.
-
-
- );
- }
-
- useEffect(() => {
- fetch("/data/career_clusters.json")
- .then((response) => response.json())
- .then((data) => {
- setCareerClusters(data);
- setFilteredClusters(Object.keys(data));
- })
- .catch((error) => console.error("Error loading career clusters:", error));
- }, []);
-
- const handleAddMilestone = () => {
- if (newMilestone.trim() !== "") {
- setCustomMilestones((prev) => ({
- ...prev,
- [activeTab]: [...prev[activeTab], { title: newMilestone, status: "upcoming", progress: 0 }],
- }));
- setNewMilestone("");
- setIsDialogOpen(false);
- }
- };
-
- const handleCareerSearch = (e) => {
- const query = e.target.value.toLowerCase();
- setCareerSearch(query);
- setFilteredCareers(
- careerClusters.filter((career) => career.toLowerCase().includes(query))
- );
- };
-
- return (
-
-
Milestone Tracker
-
- {/* Career Cluster Selection */}
-
-
Search & Select a Career Cluster
-
-
- {filteredClusters.map((cluster, index) => (
-
{
- setSelectedCluster(cluster);
- setSelectedSubdivision(null);
- setSelectedCareer(null);
- }}
- >
- {cluster}
-
- ))}
-
-
-
- {/* Subdivision Selection within Cluster */}
- {selectedCluster && careerClusters[selectedCluster] && (
-
-
Select a Specialization in {selectedCluster}
-
- {Object.keys(careerClusters[selectedCluster]).map((subdivision, index) => (
-
{
- setSelectedSubdivision(subdivision);
- setSelectedCareer(null);
- }}
- >
- {subdivision}
-
- ))}
-
-
- )}
-
- {/* Career Selection within Subdivision */}
- {selectedSubdivision && careerClusters[selectedCluster][selectedSubdivision] && (
-
-
Select a Career in {selectedSubdivision}
-
- {Object.keys(careerClusters[selectedCluster][selectedSubdivision]).map((career, index) => (
-
setSelectedCareer(career)}
- >
- {career}
-
- ))}
-
-
- )}
-
- {/* Milestone Tracker Section */}
-
-
- Career
- Financial
- Retirement
-
-
-
- {/* Add Milestone Section */}
-
-
-
-
- {/* Display User-Added Milestones */}
-
- {customMilestones[activeTab].map((milestone, index) => (
-
-
-
- {milestone.status === "completed" && }
- {milestone.status === "in-progress" && }
- {milestone.status === "upcoming" && }
-
{milestone.title}
-
-
-
-
- ))}
-
-
-
-
-
-
-
- );
-};
-
-
-export default MilestoneTracker;
\ No newline at end of file
diff --git a/src/components/PopoutPanel.js b/src/components/PopoutPanel.js
index 7c680f9..d179632 100644
--- a/src/components/PopoutPanel.js
+++ b/src/components/PopoutPanel.js
@@ -1,3 +1,5 @@
+import React from "react";
+import { useNavigate } from "react-router-dom";
import { ClipLoader } from 'react-spinners';
import LoanRepayment from './LoanRepayment.js';
import SchoolFilters from './SchoolFilters';
@@ -21,6 +23,8 @@ function PopoutPanel({
const [sortBy, setSortBy] = useState('tuition'); // Default sorting
const [maxTuition, setMaxTuition] = useState(50000); // Set default max tuition value
const [maxDistance, setMaxDistance] = useState(200); // Set default max distance value
+ const navigate = useNavigate();
+
const {
jobDescription = null,
@@ -41,7 +45,6 @@ function PopoutPanel({
}, [schools]);
useEffect(() => {
- console.log("📩 Updating Chatbot Context from PopoutPanel:", data);
if (data && Object.keys(data).length > 0) {
updateChatbotContext({
@@ -53,7 +56,6 @@ function PopoutPanel({
persistedROI, // ✅ Make sure ROI is included!
});
} else {
- console.log("⚠️ No valid PopoutPanel data to update chatbot context.");
}
}, [data, schools, salaryData, economicProjections, results, persistedROI, updateChatbotContext]);
@@ -110,7 +112,15 @@ function PopoutPanel({
{/* Header with Close & Plan My Path Buttons */}
-
+
{title}
diff --git a/src/components/ui/button.js b/src/components/ui/button.js
new file mode 100644
index 0000000..0537ae3
--- /dev/null
+++ b/src/components/ui/button.js
@@ -0,0 +1,17 @@
+import * as React from "react";
+import { cn } from "../../utils/cn.js";
+
+const Button = React.forwardRef(({ className, ...props }, ref) => {
+ return (
+
+ );
+});
+
+export { Button };
diff --git a/src/components/ui/card.js b/src/components/ui/card.js
new file mode 100644
index 0000000..c55af01
--- /dev/null
+++ b/src/components/ui/card.js
@@ -0,0 +1,10 @@
+import * as React from "react";
+import { cn } from "../../utils/cn.js";
+
+export const Card = ({ className, ...props }) => (
+
+);
+
+export const CardContent = ({ className, ...props }) => (
+
+);
diff --git a/src/components/ui/dialog.js b/src/components/ui/dialog.js
new file mode 100644
index 0000000..f608bc0
--- /dev/null
+++ b/src/components/ui/dialog.js
@@ -0,0 +1,27 @@
+import * as React from "react";
+import * as DialogPrimitive from "@radix-ui/react-dialog";
+
+const Dialog = DialogPrimitive.Root;
+const DialogTrigger = DialogPrimitive.Trigger;
+const DialogContent = React.forwardRef(({ className, ...props }, ref) => {
+ return (
+
+ );
+});
+
+const DialogHeader = ({ children }) => {
+ return
{children}
;
+ };
+
+const DialogFooter = ({ children }) => {
+ return
{children}
;
+ };
+
+ const DialogTitle = DialogPrimitive.Title;
+
+
+ export { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle };
diff --git a/src/components/ui/input.js b/src/components/ui/input.js
new file mode 100644
index 0000000..45e78a4
--- /dev/null
+++ b/src/components/ui/input.js
@@ -0,0 +1,17 @@
+import * as React from "react";
+import { cn } from "../../utils/cn.js";
+
+const Input = React.forwardRef(({ className, ...props }, ref) => {
+ return (
+
+ );
+});
+
+export { Input };
diff --git a/src/components/ui/progress.js b/src/components/ui/progress.js
new file mode 100644
index 0000000..bc952c3
--- /dev/null
+++ b/src/components/ui/progress.js
@@ -0,0 +1,20 @@
+import * as React from "react";
+import * as ProgressPrimitive from "@radix-ui/react-progress";
+
+const Progress = ({ value, max = 100, className, ...props }) => {
+ return (
+
+
+
+ );
+};
+
+export { Progress };
diff --git a/src/components/ui/tabs.js b/src/components/ui/tabs.js
new file mode 100644
index 0000000..a7df1e0
--- /dev/null
+++ b/src/components/ui/tabs.js
@@ -0,0 +1,9 @@
+import * as React from "react";
+import * as TabsPrimitive from "@radix-ui/react-tabs";
+
+const Tabs = TabsPrimitive.Root;
+const TabsList = TabsPrimitive.List;
+const TabsTrigger = TabsPrimitive.Trigger;
+const TabsContent = TabsPrimitive.Content;
+
+export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/src/index.css b/src/index.css
index ec2585e..17df0e7 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,3 +1,7 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
diff --git a/src/utils/cn.js b/src/utils/cn.js
new file mode 100644
index 0000000..bd0f9c5
--- /dev/null
+++ b/src/utils/cn.js
@@ -0,0 +1,4 @@
+export function cn(...classes) {
+ return classes.filter(Boolean).join(" ");
+ }
+
\ No newline at end of file
diff --git a/tailwind.config.js b/tailwind.config.js
new file mode 100644
index 0000000..2cb95da
--- /dev/null
+++ b/tailwind.config.js
@@ -0,0 +1,9 @@
+module.exports = {
+ content: [
+ './src/**/*.{js,jsx,ts,tsx}', // Ensure this matches your file structure
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+};