From 4bbac9e26779a28616cfd486cc08b383898ffea5 Mon Sep 17 00:00:00 2001 From: KidCharles Date: Sun, 17 Aug 2025 20:06:02 -0400 Subject: [PATCH 1/7] centered text and added' View Saved Sessions' button --- app/GradeCalculator/page.js | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/app/GradeCalculator/page.js b/app/GradeCalculator/page.js index 2157c34..01cb0bd 100644 --- a/app/GradeCalculator/page.js +++ b/app/GradeCalculator/page.js @@ -24,7 +24,8 @@ import { function GradeCalculator() { const router = useRouter(); - // State for session title and the list of assignments + + // States for session title and the list of assignments const [title, setTitle] = useState(""); const [assignments, setAssignments] = useState([ { assignment_type: "", assignment_name: "", grade: "", weight: "" }, @@ -35,11 +36,12 @@ function GradeCalculator() { // handle general changes to assignment fields const handleChange = (index, field, value) => { - // Ensure values between 0-100 for grade & weight + // Restrict values between 0-100 for grade & weight if (field === "grade" || field === "weight") { const num = Number(value); if (num < 0 || num > 100) return; } + // Make a copy of the assignments, change the specific field in row, then update state const updated = [...assignments]; updated[index][field] = value; @@ -95,17 +97,19 @@ function GradeCalculator() { } }; + // Save current session (total & calculated grade) const handleSaveSession = () => { // Check if title is empty or if there are no assignments defined - if (!title || assignments.length === 0) { - alert("Please provide a sesssion title and at least one assignment"); + if (!title || !finalGrade) { + alert("Please calculate grade and provide a sesssion title before saving"); return; } // Get previously saved sessions from local storage. Use empty array if no saved sessions exist (note: reason for local storage is to develop MVP for saved sessions page) const savedSessions = JSON.parse(localStorage.getItem("savedSessions")) || []; - // add session to the list + + // add a new session to the list with a unique id savedSessions.push({ id: Date.now(), title, assignments }); localStorage.setItem("savedSessions", JSON.stringify(savedSessions)); @@ -116,7 +120,7 @@ function GradeCalculator() { return (
- + Grade Calculator Enter grades and weights to calculate your grade. @@ -132,7 +136,7 @@ function GradeCalculator() { /> {/*Column headers */} -
+
Assignment Type Assignment Name Grade (%) @@ -212,22 +216,22 @@ function GradeCalculator() {
))} + - {/* Add another assignment button */} + {/* Footer with action buttons */} + - - - + + - {/* Display calculated final grade */} + {/* Display calculated grade */} {finalGrade && ( -

Final Grade: {finalGrade}

+

Final Grade: {finalGrade}

)} -
); From a404bca5cb3a2d2c93da81b0f7657a7c88a71ace Mon Sep 17 00:00:00 2001 From: KidCharles Date: Sun, 17 Aug 2025 20:30:46 -0400 Subject: [PATCH 2/7] Removed session card content. Added an edit button. Added a New Session button to redirect users to Grade Calculator page. --- app/CalculatorSessions/page.js | 35 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/app/CalculatorSessions/page.js b/app/CalculatorSessions/page.js index dee60b1..6b5936a 100644 --- a/app/CalculatorSessions/page.js +++ b/app/CalculatorSessions/page.js @@ -10,8 +10,11 @@ import { } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; +import { useRouter } from "next/navigation"; function SavedSessions() { + const router = useRouter(); + // State to store all saved sessions and user search text const [sessions, setSessions] = useState([]); const [search, setSearch] = useState(""); @@ -27,6 +30,7 @@ function SavedSessions() { // remove session from the session list const updated = sessions.filter((session) => session.id !== id); setSessions(updated); + localStorage.setItem("savedSessions", JSON.stringify(updated)); }; // Filter sessions based on user search text input (note: case-insensitive) @@ -36,8 +40,11 @@ function SavedSessions() { return (
- {/* Page Title*/} -

Saved Sessions

+ {/* Page Title and "Save Session" button aligned right*/} +
+

Saved Sessions

+ +
{/* Search Input */} {session.title} - - {/* Assignments within session card */} - - {session.assignments.map((a, i) => ( -
- {a.assignment_type} - {a.assignment_name} - {a.grade} % - {a.weight}% -
- ))} -
+ {/* Show calculated grade within session card*/} + {session.finalGrade && ( +

+ Final Grade: {session.finalGrade} +

+ )}
- {/* Delete button and trash icon*/} - + {/* Edit and Delete button via trash icon*/} + + + + +
+

+ Saved Assignments +

+
{/* Search Input */} setSearch(e.target.value)} className="mb-4 w-full max-w-lg" /> {/* List of filtered sessions */} -
- {filteredSessions.map((session) => ( - -
- - {session.title} - - {/* Show calculated grade within session card*/} - {session.finalGrade && ( -

- Final Grade: {session.finalGrade} -

- )} -
- - {/* Edit and Delete button via trash icon*/} - - + {/* List of assignments */} +
+ {grades.map((grade) => ( + + + + {grade.assignment_name} + + + +

Grade: {grade.assignment_grade ?? "N/A"}

+

Weight: {grade.assignment_weight ?? "N/A"}%

+
+ + + + +
+ ))} - - - - ))} + {grades.length === 0 && ( +

No grades found.

+ )} +
- {/* Message to user when no sessions match their text search*/} - {filteredSessions.length === 0 && ( -

No sessions found.

- )} -
); } -export default SavedSessions; \ No newline at end of file +export default SavedSessions; diff --git a/app/GradeCalculator/page.js b/app/GradeCalculator/page.js index a7e330c..1a3c2ae 100644 --- a/app/GradeCalculator/page.js +++ b/app/GradeCalculator/page.js @@ -25,8 +25,13 @@ import { function GradeCalculator() { const router = useRouter(); - const searchParams = useSearchParams(); - const editTitle = searchParams.get("editTitle"); + const [editTitle, setEditTitle] = useState(null); + + useEffect(() => { + const params = new URLSearchParams(window.location.search); + const title = params.get("editTitle"); + if (title) setEditTitle(title); + }, []); // States for session title and the list of assignments const [title, setTitle] = useState(""); @@ -43,7 +48,7 @@ function GradeCalculator() { const fetchSessionAssignments = async () => { try { const userId = 1; // hardcoded for now - const response = await axios.get(`/api/Calculator/grade-entries/${userId}`); + const response = await axios.get(`http://localhost:8080/api/grade-calculator/grade-entries/${userId}`); // filter assignments matching this session title const sessionAssignments = response.data.filter( (a) => a.session_title === editTitle @@ -143,13 +148,13 @@ function GradeCalculator() { try { for (let assignment of assignments) { if (assignment.id) { - await axios.put(`/api/Calculator/grade-entry/${editId}`, { + await axios.put(`http://localhost:8080/api/Calculator/grade-entry`, { assignment_grade: assignment.grade, assignment_weight: assignment.weight, }); } else { // POST axios call to new-grade-entry. "If not editing, then create new session - await axios.post("/api/Calculator/new-grade-entry", { + await axios.post(`http://localhost:8080/api/grade-calculator/new-grade-entry`, { user_id: 1, assignment_type: assignment.assignment_type, assignment_name: assignment.assignment_name, From f82c9a0c8760d59982220388bb717b6379632664 Mon Sep 17 00:00:00 2001 From: KidCharles Date: Tue, 19 Aug 2025 21:10:58 -0400 Subject: [PATCH 7/7] fixes axios calls and removed session functionality :( --- app/CalculatorSessions/page.js | 91 ++++++----- app/GradeCalculator/page.js | 265 ++++++++++++++++++--------------- components/NavBar.jsx | 1 + 3 files changed, 198 insertions(+), 159 deletions(-) diff --git a/app/CalculatorSessions/page.js b/app/CalculatorSessions/page.js index 4359c27..60cc14e 100644 --- a/app/CalculatorSessions/page.js +++ b/app/CalculatorSessions/page.js @@ -41,7 +41,9 @@ function SavedSessions() { // axios function to delete a session via ID const handleDelete = async (id) => { try { - await axios.delete(`http://localhost:8080/api/grade-calculator/grade-entry/${id}`); + await axios.delete( + `http://localhost:8080/api/grade-calculator/grade-entry/${id}` + ); // remove session from the session list const updated = grades.filter((grade) => grade.id !== id); setGrades(updated); @@ -56,9 +58,9 @@ function SavedSessions() { router.push(`/GradeCalculator?editId=$[id]`); }; - // Filter sessions based on user search text input (note: case-insensitive) - const filteredSessions = sessions.filter((session) => - session.title.toLowerCase().includes(search.toLowerCase()) + // Filter assignments based on user search text input (note: case-insensitive) + const filteredGrades = grades.filter((grade) => + grade.assignment_name.toLowerCase().includes(search.toLowerCase()) ); return ( @@ -72,7 +74,7 @@ function SavedSessions() { className="ml-auto" onClick={() => router.push("/GradeCalculator")} > - New Session + New Assignment @@ -85,40 +87,55 @@ function SavedSessions() { className="mb-4 w-full max-w-lg" /> - {/* List of filtered sessions */} {/* List of assignments */} -
- {grades.map((grade) => ( - - - - {grade.assignment_name} - - - -

Grade: {grade.assignment_grade ?? "N/A"}

-

Weight: {grade.assignment_weight ?? "N/A"}%

-
- - - - -
- ))} - - {grades.length === 0 && ( -

No grades found.

- )} -
+
+ {filteredGrades.map((grade) => ( + + + + {grade.assignment_name} + + + +

+ Assignment Type:{" "} + {grade.assignment_type ?? "N/A"} +

+

+ Grade:{" "} + {grade.assignment_grade ?? "N/A"} +

+

+ Weight:{" "} + {grade.assignment_weight ?? "N/A"}% +

+
+ + {/* */} + + +
+ ))} + {grades.length === 0 && ( +

No grades found.

+ )} +
); } diff --git a/app/GradeCalculator/page.js b/app/GradeCalculator/page.js index 1a3c2ae..69af2b2 100644 --- a/app/GradeCalculator/page.js +++ b/app/GradeCalculator/page.js @@ -1,27 +1,27 @@ "use client"; -import React, { useState, useEffect } from "react"; -import axios from "axios" +import axios from "axios"; import { useRouter } from "next/navigation"; +import { useEffect, useState } from "react"; import { Card, - CardHeader, - CardTitle, - CardDescription, CardContent, + CardDescription, CardFooter, + CardHeader, + CardTitle, } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { CalculatorSelect, - CalculatorSelectTrigger, CalculatorSelectContent, CalculatorSelectItem, + CalculatorSelectTrigger, CalculatorSelectValue, } from "@/components/ui/calculator-select"; +import { Input } from "@/components/ui/input"; function GradeCalculator() { const router = useRouter(); @@ -48,7 +48,9 @@ function GradeCalculator() { const fetchSessionAssignments = async () => { try { const userId = 1; // hardcoded for now - const response = await axios.get(`http://localhost:8080/api/grade-calculator/grade-entries/${userId}`); + const response = await axios.get( + `http://localhost:8080/api/grade-calculator/grade-entries/${userId}` + ); // filter assignments matching this session title const sessionAssignments = response.data.filter( (a) => a.session_title === editTitle @@ -141,7 +143,9 @@ function GradeCalculator() { const handleSaveSession = async () => { // Check if title is empty or if there are no assignments defined if (!title || !finalGrade) { - alert("Please calculate grade and provide a sesssion title before saving"); + alert( + "Please calculate grade and provide a sesssion title before saving" + ); return; } @@ -154,141 +158,158 @@ function GradeCalculator() { }); } else { // POST axios call to new-grade-entry. "If not editing, then create new session - await axios.post(`http://localhost:8080/api/grade-calculator/new-grade-entry`, { + await axios.post( + `http://localhost:8080/api/grade-calculator/new-grade-entry`, + { user_id: 1, assignment_type: assignment.assignment_type, assignment_name: assignment.assignment_name, assignment_grade: assignment.grade, assignment_weight: assignment.weight, - }); - } + } + ); } - - // After saving to db, redirect user to saved sessions page - router.push("/CalculatorSessions"); - } catch(error) { - console.error("Error saving grade entry: ", error); - alert("Failed to save session. Please try again."); } - }; + + // After saving to db, redirect user to saved assignments page + router.push("/CalculatorSessions"); + } catch (error) { + console.error("Error saving grade entry: ", error); + alert("Failed to save assignment(s). Please try again."); + } + }; return ( -
- - - Grade Calculator - - Enter grades and weights to calculate your grade. - - +
+ + + Grade Calculator + + Enter grades and weights to calculate your grade. + + - - setTitle(e.target.value)} - /> + + setTitle(e.target.value)} + /> - {/*Column headers */} -
- Assignment Type - Assignment Name - Grade (%) - Weight (%) - {/* trash icon column */} - -
+ {/*Column headers */} +
+ Assignment Type + Assignment Name + Grade (%) + Weight (%) + {/* trash icon column */} + +
- {/* Assignment rows */} - {assignments.map((assignments, index) => ( -
- {/* Assignment type dropdown */} - - handleChange(index, "assignment_type", value) - } - > - - - - - Homework - Quiz - Midterm - Final Exam - - + {/* Assignment rows */} + {assignments.map((assignments, index) => ( +
+ {/* Assignment type dropdown */} + + handleChange(index, "assignment_type", value) + } + > + + + + + + Homework + + + Quiz + + + Midterm + + + Final Exam + + + - {/* Assignment Name Input*/} - - handleChange(index, "assignment_name", e.target.value) - } - /> + {/* Assignment Name Input*/} + + handleChange(index, "assignment_name", e.target.value) + } + /> - {/* Grade Input */} - handleChange(index, "grade", e.target.value)} - /> + {/* Grade Input */} + handleChange(index, "grade", e.target.value)} + /> - {/* Weight Input */} - handleChange(index, "weight", e.target.value)} - /> + {/* Weight Input */} + + handleChange(index, "weight", e.target.value) + } + /> - {/* Delete assignment button */} - -
- ))} - + {/* trash icon */} + + + + +
+ ))} +
- {/* Footer with action buttons */} - - - - - - + {/* Footer with action buttons */} + + + + + + {/* Display calculated grade */} {finalGrade && ( -

Final Grade: {finalGrade}

+

+ Final Grade: {finalGrade} +

)} -
-
+
+
); } diff --git a/components/NavBar.jsx b/components/NavBar.jsx index 65ef63e..eac1cb8 100644 --- a/components/NavBar.jsx +++ b/components/NavBar.jsx @@ -18,6 +18,7 @@ const navigationLinks = [ { href: "/LockInChat", label: "Study with AI", active: false }, { href: "/StudySession", label: "Study Timer", active: false }, { href: "/Tasks", label: "Tasks", active: false }, + { href: "/GradeCalculator", label: "Grade Calculator", active: false }, ]; export default function NavBarComponent() {