diff --git a/jportal/src/components/Grades.jsx b/jportal/src/components/Grades.jsx index bc42f1a..cbc6a4a 100644 --- a/jportal/src/components/Grades.jsx +++ b/jportal/src/components/Grades.jsx @@ -4,9 +4,10 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import GradeCard from "./GradeCard"; import { Button } from "@/components/ui/button"; -import { Download } from "lucide-react"; +import { CalculatorIcon, Download } from "lucide-react"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import MarksCard from "./MarksCard"; +import CGPATargetCalculator from "./TargetCPA"; import { generate_local_name, API } from "https://cdn.jsdelivr.net/npm/jsjiit@0.0.16/dist/jsjiit.esm.js"; import MockWebPortal from "./MockWebPortal"; @@ -392,7 +393,12 @@ export default function Grades({ )} -
+
+ + + + + + + GPA Calculator + + + + + + + SGPA + + + Target GPA + + + + +
+ + + {isLoadingSemesters && ( +
+ + Loading semesters... +
+ )} +
+ + {selectedSemester && ( + <> + {isLoadingSubjects ? ( +
+ + Loading subjects... +
+ ) : sgpaSubjects.length > 0 ? ( + <> +
+ {sgpaSubjects.map((subject, index) => ( +
+
+
+ {subject.name} +
+
+ {subject.code} + {subject.credits} credits +
+
+
+ + +
+
+ ))} +
+
+
+ Calculated SGPA + + {calculateSGPA()} + +
+
+ Projected CGPA + + {calculateProjectedCGPA()} + +
+
+ + ) : ( +
+

+ No subjects found for this semester +

+
+ )} + + )} +
+ + +
+
+

+ Enter your desired final CGPA, and we'll calculate the SGPA you need to achieve in the selected semester. +

+ +
+
+ + +
+ +
+ + setTargetCGPA(e.target.value)} + placeholder="Enter target CGPA (e.g., 9.0)" + className="rounded-lg" + /> +
+ + +
+ + {targetError && ( +
+ {targetError} +
+ )} + + {requiredSGPA !== null && !targetError && ( +
+
+
+

+ {targetSemester?.registration_code || targetSemester?.coursename || targetSemester?.stynumber || "Selected Semester"} +

+

+ Required SGPA +

+ {requiredSGPA > 10 ? ( +
+

+ Not Achievable +

+

+ Target CGPA of {formatGPA(parseFloat(targetCGPA))} cannot be achieved this semester. + The required SGPA ({formatGPA(requiredSGPA)}) exceeds the maximum possible (10.0). +

+
+ ) : requiredSGPA < 0 ? ( +
+

+ Already Achieved! +

+

+ Your current CGPA already meets or exceeds your target of {formatGPA(parseFloat(targetCGPA))}. +

+
+ ) : ( +
+

+ {formatGPA(requiredSGPA)} +

+

+ Achieve an SGPA of {formatGPA(requiredSGPA)} this semester to reach your target CGPA of {formatGPA(parseFloat(targetCGPA))}. +

+
+ )} +
+
+ + {sd && sd.length > 0 && ( +
+

+ Current Stats: + • Previous semesters: {sd.length} + • Current CGPA: { + formatGPA( + sd.reduce((sum, sem) => sum + (parseFloat(sem.sgpa) * parseFloat(sem.totalcoursecredit)), 0) / + sd.reduce((sum, sem) => sum + parseFloat(sem.totalcoursecredit), 0) + ) + } +

+
+ )} +
+ )} +
+
+
+
+
+
+ + ); +} diff --git a/jportal/src/lib/utils.js b/jportal/src/lib/utils.js index b20bf01..ead7941 100644 --- a/jportal/src/lib/utils.js +++ b/jportal/src/lib/utils.js @@ -4,3 +4,26 @@ import { twMerge } from "tailwind-merge" export function cn(...inputs) { return twMerge(clsx(inputs)); } + +export function getDecimalPlaces() { + return 2; +} + +export function formatDecimal(value, places = 2) { + if (typeof value === "number") { + return value.toFixed(places); + } + return value; +} + +export function getAttendanceDecimal() { + return 2; +} + +export function getGpaDecimal() { + return 2; +} + +export function getTargetGpaDecimal() { + return 2; +}