From ae2e08c8eb1f2291a8f85aafa10c6b857b386834 Mon Sep 17 00:00:00 2001 From: jaffer325 Date: Sun, 16 Aug 2026 20:47:12 +0530 Subject: [PATCH 1/2] feat : Added theme Change --- client/index.html | 1 + client/package-lock.json | 1 + client/src/main.jsx | 251 +++++++++++++++++++++++++++---------- client/src/styles.css | 258 ++++++++++++++++++++++++++++----------- package-lock.json | 16 +-- server/package-lock.json | 16 +++ server/src/data/db.json | 214 ++++++++++++++++++-------------- 7 files changed, 523 insertions(+), 234 deletions(-) diff --git a/client/index.html b/client/index.html index c880bd36..e0cea69e 100644 --- a/client/index.html +++ b/client/index.html @@ -4,6 +4,7 @@ PyBe +
diff --git a/client/package-lock.json b/client/package-lock.json index 15e52316..b7f58099 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -17,6 +17,7 @@ } }, "..": { + "name": "pybe-mern-app", "version": "1.0.0", "dependencies": { "concurrently": "^9.1.2" diff --git a/client/src/main.jsx b/client/src/main.jsx index ef3da3a9..936bb9d8 100644 --- a/client/src/main.jsx +++ b/client/src/main.jsx @@ -1,5 +1,5 @@ -import React, { useEffect, useMemo, useState } from 'react'; -import { createRoot } from 'react-dom/client'; +import React, { useEffect, useMemo, useState } from "react"; +import { createRoot } from "react-dom/client"; import { Brain, ChartNoAxesCombined, @@ -7,20 +7,22 @@ import { Compass, Lightbulb, MessageSquareText, + MoonStar, Play, Route, Search, Send, - Sparkles -} from 'lucide-react'; -import './styles.css'; + Sparkles, + SunMedium, +} from "lucide-react"; +import "./styles.css"; -const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:5000/api'; +const API_URL = import.meta.env.VITE_API_URL || "http://localhost:5000/api"; async function api(path, options) { const response = await fetch(`${API_URL}${path}`, { - headers: { 'Content-Type': 'application/json' }, - ...options + headers: { "Content-Type": "application/json" }, + ...options, }); if (!response.ok) throw new Error(await response.text()); return response.json(); @@ -32,22 +34,52 @@ function App() { const [sessions, setSessions] = useState([]); const [analytics, setAnalytics] = useState(null); const [roadmap, setRoadmap] = useState([]); - const [filters, setFilters] = useState({ q: '', difficulty: '', concept: '' }); - const [form, setForm] = useState({ learnerName: 'Guest learner', reasoning: '', promptText: '', reflection: '' }); + const [filters, setFilters] = useState({ + q: "", + difficulty: "", + concept: "", + }); + const [form, setForm] = useState({ + learnerName: "Guest learner", + reasoning: "", + promptText: "", + reflection: "", + }); const [activeResult, setActiveResult] = useState(null); const [loading, setLoading] = useState(true); const [submitting, setSubmitting] = useState(false); + const [theme, setTheme] = useState(() => { + const savedTheme = localStorage.getItem("pybe-theme"); + if (savedTheme) return savedTheme; + return window.matchMedia("(prefers-color-scheme: dark)").matches + ? "dark" + : "light"; + }); + + useEffect(() => { + document.documentElement.setAttribute("data-theme", theme); + localStorage.setItem("pybe-theme", theme); + }, [theme]); - const concepts = useMemo(() => [...new Set(scenarios.flatMap((scenario) => scenario.concepts || []))].sort(), [scenarios]); + const concepts = useMemo( + () => + [ + ...new Set(scenarios.flatMap((scenario) => scenario.concepts || [])), + ].sort(), + [scenarios], + ); async function refresh() { - const params = new URLSearchParams(Object.entries(filters).filter(([, value]) => value)); - const [scenarioData, sessionData, analyticsData, roadmapData] = await Promise.all([ - api(`/scenarios?${params}`), - api('/sessions'), - api('/analytics'), - api('/roadmap') - ]); + const params = new URLSearchParams( + Object.entries(filters).filter(([, value]) => value), + ); + const [scenarioData, sessionData, analyticsData, roadmapData] = + await Promise.all([ + api(`/scenarios?${params}`), + api("/sessions"), + api("/analytics"), + api("/roadmap"), + ]); setScenarios(scenarioData); setSessions(sessionData); setAnalytics(analyticsData); @@ -65,12 +97,12 @@ function App() { if (!selected || !form.reasoning.trim()) return; setSubmitting(true); try { - const result = await api('/sessions', { - method: 'POST', - body: JSON.stringify({ ...form, scenarioId: selected._id }) + const result = await api("/sessions", { + method: "POST", + body: JSON.stringify({ ...form, scenarioId: selected._id }), }); setActiveResult(result); - setForm({ ...form, reasoning: '', promptText: '', reflection: '' }); + setForm({ ...form, reasoning: "", promptText: "", reflection: "" }); await refresh(); } finally { setSubmitting(false); @@ -82,40 +114,78 @@ function App() { return (