From 906e9c757b1a4d377e064a72ddd0f860a93c5061 Mon Sep 17 00:00:00 2001 From: Anbu-dev-creator Date: Fri, 21 Aug 2026 09:26:47 +0530 Subject: [PATCH] New --- package-lock.json | 28 +- src/constants/index.ts | 4 - src/pages/Faculty/Faculty.tsx | 2 +- src/pages/Toolkit/Toolkit.tsx | 794 ++++++++++++++++++++++------------ 4 files changed, 535 insertions(+), 293 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0674289..9bbdf1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,6 +102,7 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -1636,17 +1637,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@emnapi/runtime": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", - "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", @@ -4432,6 +4422,7 @@ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.3.tgz", "integrity": "sha512-ZjgcRwmQUSCythDPj6pE2NKFi9bpQegxIBxgt3hPytXI1ElFHNaa3A7aWW8vFaLCIRjPv467rbREYHbxcdgQbg==", "license": "MIT", + "peer": true, "dependencies": { "@tanstack/query-core": "5.101.3" }, @@ -4517,6 +4508,7 @@ "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.18.0" } @@ -4527,6 +4519,7 @@ "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -4537,6 +4530,7 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -4612,6 +4606,7 @@ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -4870,6 +4865,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.42", "caniuse-lite": "^1.0.30001803", @@ -6545,7 +6541,8 @@ "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "peer": true }, "node_modules/leven": { "version": "3.1.0", @@ -7173,6 +7170,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", @@ -7216,6 +7214,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -7225,6 +7224,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -7237,6 +7237,7 @@ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.82.0.tgz", "integrity": "sha512-Zw/uFZ2dO+02GHlBn7JFGn8kZJ7LdM33B/0BXOovzFay+CMhf94JMw5BVu+F1tVkUKjNvBuaE3fz5BJhga10Tg==", "license": "MIT", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -7543,6 +7544,7 @@ "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.9" }, @@ -8088,6 +8090,7 @@ "integrity": "sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -8413,6 +8416,7 @@ "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", diff --git a/src/constants/index.ts b/src/constants/index.ts index 213e909..fdff766 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -3832,9 +3832,5 @@ export const DEPARTMENTS = [ 'Computer Science & Engineering', 'Electronics & Communication Engineering', 'Electronics Engineering VLSI (Design and Technology)', - 'Humanities & Sciences', - 'M.E. (VLSI Design)', - 'M.Tech (Data Science)', - 'Mathematics', 'Mechanical Engineering', ]; diff --git a/src/pages/Faculty/Faculty.tsx b/src/pages/Faculty/Faculty.tsx index 64405f0..52637cc 100644 --- a/src/pages/Faculty/Faculty.tsx +++ b/src/pages/Faculty/Faculty.tsx @@ -294,7 +294,7 @@ export default function Faculty() { className="h-full pl-10 pr-10 py-3.5 rounded-2xl bg-[#F8FAFC] border-none text-sm font-medium text-[#475569] focus:ring-2 focus:ring-[#FF7A00]/20 focus:outline-none transition-all appearance-none cursor-pointer min-w-[200px]" style={{ fontFamily: 'Inter, sans-serif', backgroundImage: 'url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%2394A3B8%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E")', backgroundRepeat: 'no-repeat', backgroundPosition: 'right 1rem top 50%', backgroundSize: '0.65rem auto' }} > - {DEPARTMENTS.filter(dept => dept === 'All Departments' || FACULTY_DATA.filter((f) => f.department === dept).length > 0).map((dept) => { + {Array.from(new Set(['All Departments', ...DEPARTMENTS, ...FACULTY_DATA.map(f => f.department)])).filter(dept => dept === 'All Departments' || FACULTY_DATA.filter((f) => f.department === dept).length > 0).map((dept) => { const count = dept === 'All Departments' ? FACULTY_DATA.length : FACULTY_DATA.filter((f) => f.department === dept).length; return ; })} diff --git a/src/pages/Toolkit/Toolkit.tsx b/src/pages/Toolkit/Toolkit.tsx index 6226283..2af01d3 100644 --- a/src/pages/Toolkit/Toolkit.tsx +++ b/src/pages/Toolkit/Toolkit.tsx @@ -670,8 +670,24 @@ export default function Toolkit() { const [calculationType, setCalculationType] = useState<'gpa' | 'internal' | null>(null); const [gpaStep, setGpaStep] = useState<1 | 2>(1); const [calculatedScore, setCalculatedScore] = useState(null); + const resultCardRef = useRef(null); const [imsData, setImsData] = useState(null); const [isImsAutoFilled, setIsImsAutoFilled] = useState(false); + const [cat1Input, setCat1Input] = useState(''); + const [cat2Input, setCat2Input] = useState(''); + const [cat3Input, setCat3Input] = useState(''); + const [assignmentInput, setAssignmentInput] = useState(''); + const [internalError, setInternalError] = useState(null); + const [showWeightages, setShowWeightages] = useState>({ + cat1: false, + cat2: false, + cat3: false, + assignment: false, + }); + + const toggleWeightage = (key: string) => { + setShowWeightages((prev) => ({ ...prev, [key]: !prev[key] })); + }; useEffect(() => { const session = getStoredImsSession(); @@ -699,6 +715,7 @@ export default function Toolkit() { grade: string; cat1: string; cat2: string; + cat3: string; assignment: string; attendance: string; isElective?: boolean; @@ -706,13 +723,7 @@ export default function Toolkit() { electiveCode?: string; } - const [subjects, setSubjects] = useState([ - { name: 'Subject 1', credits: 4, grade: 'O', cat1: '45', cat2: '48', assignment: '10', attendance: '95' }, - { name: 'Subject 2', credits: 3, grade: 'A+', cat1: '42', cat2: '44', assignment: '9', attendance: '92' }, - { name: 'Subject 3', credits: 3, grade: 'A', cat1: '38', cat2: '40', assignment: '8', attendance: '88' }, - { name: 'Subject 4', credits: 4, grade: 'O', cat1: '46', cat2: '47', assignment: '10', attendance: '96' }, - { name: 'Subject 5', credits: 2, grade: 'A+', cat1: '44', cat2: '45', assignment: '9', attendance: '94' }, - ]); + const [subjects, setSubjects] = useState([]); const handleProceedToStep2 = (type: 'gpa' | 'internal') => { if (!gpaDepartment || !gpaSemester) return; @@ -766,62 +777,47 @@ export default function Toolkit() { foundAnyImsMatch = true; } - const gradeVal = matchedGrade?.grade || 'O'; - const cat1Val = matchedCat?.cat1 ? String(matchedCat.cat1) : '45'; - const cat2Val = matchedCat?.cat2 ? String(matchedCat.cat2) : '45'; - const assgnVal = matchedCat?.assignment ? String(matchedCat.assignment) : '9'; - - if (isElective) { - const slot = s.electiveSlot || electiveCounter++; - const defaultElectiveObj = PROFESSIONAL_ELECTIVES_LIST[(slot - 1) % PROFESSIONAL_ELECTIVES_LIST.length] || PROFESSIONAL_ELECTIVES_LIST[0]; - return { - name: `${defaultElectiveObj.code} - ${defaultElectiveObj.name}`, - credits: s.credits, - grade: gradeVal, - cat1: cat1Val, - cat2: cat2Val, - assignment: assgnVal, - attendance: '95', - isElective: true, - electiveSlot: slot, - electiveCode: defaultElectiveObj.code, - }; - } + const gradeVal = matchedGrade?.grade || ''; + const cat1Val = matchedCat?.cat1 ? String(matchedCat.cat1) : ''; + const cat2Val = matchedCat?.cat2 ? String(matchedCat.cat2) : ''; + const cat3Val = matchedCat?.cat3 ? String(matchedCat.cat3) : ''; + const assgnVal = matchedCat?.assignment ? String(matchedCat.assignment) : ''; return { name: s.name, credits: s.credits, grade: gradeVal, cat1: cat1Val, cat2: cat2Val, + cat3: cat3Val, assignment: assgnVal, attendance: '95', - isElective: false, }; }); setSubjects(loaded); if (type === 'gpa') { - setIsImsAutoFilled(foundAnyImsMatch || imsGrades.length > 0); - let totalCredits = 0; - let totalPoints = 0; - const GRADE_POINTS: Record = { 'O': 10, 'A+': 9, 'A': 8, 'B+': 7, 'B': 6, 'C': 5, 'RA': 0 }; - loaded.forEach((sub: any) => { - const pts = GRADE_POINTS[sub.grade] ?? 10; - totalCredits += sub.credits; - totalPoints += pts * sub.credits; - }); - if (totalCredits > 0) { - setCalculatedScore((totalPoints / totalCredits).toFixed(2)); + setIsImsAutoFilled(foundAnyImsMatch && imsGrades.length > 0); + if (foundAnyImsMatch && imsGrades.length > 0) { + let totalCredits = 0; + let totalPoints = 0; + const GRADE_POINTS: Record = { 'O': 10, 'A+': 9, 'A': 8, 'B+': 7, 'B': 6, 'C': 5, 'UA': 0, 'RA': 0 }; + loaded.forEach((sub: any) => { + if (sub.grade) { + const pts = GRADE_POINTS[sub.grade] ?? 0; + totalCredits += sub.credits; + totalPoints += pts * sub.credits; + } + }); + if (totalCredits > 0) { + setCalculatedScore((totalPoints / totalCredits).toFixed(2)); + } + } else { + setCalculatedScore(null); } } } else { - setSubjects([ - { name: 'Subject 1', credits: 4, grade: 'O', cat1: '45', cat2: '48', assignment: '10', attendance: '95' }, - { name: 'Subject 2', credits: 3, grade: 'A+', cat1: '42', cat2: '44', assignment: '9', attendance: '92' }, - { name: 'Subject 3', credits: 3, grade: 'A', cat1: '38', cat2: '40', assignment: '8', attendance: '88' }, - { name: 'Subject 4', credits: 4, grade: 'O', cat1: '46', cat2: '47', assignment: '10', attendance: '96' }, - { name: 'Subject 5', credits: 2, grade: 'A+', cat1: '44', cat2: '45', assignment: '9', attendance: '94' }, - ]); + setSubjects([]); + setCalculatedScore(null); } setGpaStep(2); @@ -946,21 +942,105 @@ export default function Toolkit() { {/* Main Content Area */} {selectedToolkit === 'gpa' ? ( - {gpaStep === 1 ? ( - /* ── STEP 1: Department and Semester Selection ── */ + {calculationType === null ? ( + /* ── INITIAL MODE SELECTION: Calculate Internal Mark vs Calculate GPA ── */ +
+
+ +
+

+ GPA & Internal Calculator +

+

+ Select what you would like to calculate to begin. +

+
+ +
+ {/* Option 1: Internal Mark Calculator */} +
{ + setCalculationType('internal'); + setGpaStep(2); + setCalculatedScore(null); + setInternalError(null); + }} + className="p-6 md:p-8 rounded-3xl bg-gradient-to-br from-[#F5F3FF] via-[#FAF5FF] to-white border-2 border-[#DDD6FE] hover:border-[#7C3AED] hover:shadow-lg transition-all cursor-pointer group flex flex-col justify-between" + > +
+
+ +
+
+

+ Calculate Internal Mark +

+

+ Calculate your converted internal mark out of 40 directly from CAT I, CAT II, CAT III, and Assignment marks. Direct calculation with no department or subject inputs needed. +

+
+
+
+ Open Internal Calculator + +
+
+ + {/* Option 2: GPA Calculator */} +
{ + setCalculationType('gpa'); + setGpaStep(1); + setCalculatedScore(null); + setInternalError(null); + }} + className="p-6 md:p-8 rounded-3xl bg-gradient-to-br from-[#FFF7ED] via-[#FFFBEB] to-white border-2 border-[#FED7AA] hover:border-[#FF6B00] hover:shadow-lg transition-all cursor-pointer group flex flex-col justify-between" + > +
+
+ +
+
+

+ Calculate GPA +

+

+ Select your department and semester to load curriculum subjects, enter your grades, and compute your Semester Grade Point Average (SGPA / 10.00). +

+
+
+
+ Select Department & Semester + +
+
+
+
+ ) : calculationType === 'gpa' && gpaStep === 1 ? ( + /* ── STEP 1: Department and Semester Selection for GPA ── */
+ +

- GPA & Internal Calculator + GPA Calculator

- Step 1 of 2: Select your department and semester to begin. + Select your department and semester to load curriculum subjects.

@@ -1002,26 +1082,11 @@ export default function Toolkit() {
- {/* Two Action Buttons to proceed to Step 2 */} -
- - +
) : ( - /* ── STEP 2: Subject Input and Marks Section ── */ + /* ── STEP 2: Calculation Form (GPA or Direct Internal) ── */

- {calculationType === 'gpa' ? 'GPA Calculation' : 'Internal Marks Calculation'} + {calculationType === 'gpa' ? 'GPA Calculation' : 'Internal Mark Calculator'}

-

- {gpaDepartment} — {gpaSemester} -

+ {calculationType === 'gpa' && ( +

+ {gpaDepartment} — {gpaSemester} +

+ )}
{calculationType === 'gpa' ? : } @@ -1086,190 +1160,273 @@ export default function Toolkit() { Grade Achieved
- {(() => { - const selectedElectiveCodes = new Set(subjects.filter((s) => s.isElective && s.electiveCode).map((s) => s.electiveCode)); - - return subjects.filter(s => s.credits > 0).map((sub, idx) => ( -
-
- {sub.isElective ? ( -
-
- Professional Elective {sub.electiveSlot} -
- -
- ) : ( -

- {sub.name} -

- )} - - {sub.credits} {sub.credits === 1 ? 'Credit' : 'Credits'} - -
-
- -
+ {subjects.filter(s => s.credits > 0).map((sub, idx) => ( +
+
+

+ {sub.name} +

+ + {sub.credits} {sub.credits === 1 ? 'Credit' : 'Credits'} +
- )); - })()} -
- ) : ( - /* ── Internal Marks Layout ── */ -
-
- Subject Details - {subjects.length} Subjects -
- - {subjects.map((sub, idx) => ( -
-
- + { - const updated = [...subjects]; - updated[idx].cat1 = e.target.value; - setSubjects(updated); - setCalculatedScore(null); - }} - className="w-full px-2.5 py-1.5 rounded-xl bg-white border border-[#CBD5E1] text-xs font-medium text-[#1E293B] outline-none" - /> -
-
- - { - const updated = [...subjects]; - updated[idx].cat2 = e.target.value; - setSubjects(updated); - setCalculatedScore(null); - }} - className="w-full px-2.5 py-1.5 rounded-xl bg-white border border-[#CBD5E1] text-xs font-medium text-[#1E293B] outline-none" - /> -
-
- - { - const updated = [...subjects]; - updated[idx].assignment = e.target.value; - setSubjects(updated); - setCalculatedScore(null); - }} - className="w-full px-2.5 py-1.5 rounded-xl bg-white border border-[#CBD5E1] text-xs font-medium text-[#1E293B] outline-none" - /> -
-
- - { - const updated = [...subjects]; - updated[idx].attendance = e.target.value; - setSubjects(updated); - setCalculatedScore(null); - }} - className="w-full px-2.5 py-1.5 rounded-xl bg-white border border-[#CBD5E1] text-xs font-medium text-[#1E293B] outline-none" - /> -
+ className={`w-full px-3.5 py-2.5 rounded-xl bg-white border ${!sub.grade ? 'border-amber-300 bg-amber-50/20 text-[#64748B]' : 'border-[#CBD5E1] text-[#1E293B] focus:border-[#FF6B00]'} text-xs font-bold focus:ring-2 focus:ring-[#FF6B00]/20 outline-none cursor-pointer shadow-2xs`} + style={{ fontFamily: 'Inter, sans-serif' }} + > + + + + + + + + +
))} +
+ ) : ( + /* ── Direct Internal Marks Layout (Assigned 40-Mark Weightages & Per-Field Weightage Calculations) ── */ + (() => { + const n1 = cat1Input === '' ? NaN : Number(cat1Input); + const isCat1Err = cat1Input !== '' && (isNaN(n1) || n1 < 0 || n1 > 50); - + const n2 = cat2Input === '' ? NaN : Number(cat2Input); + const isCat2Err = cat2Input !== '' && (isNaN(n2) || n2 < 0 || n2 > 25); + + const n3 = cat3Input === '' ? NaN : Number(cat3Input); + const isCat3Err = cat3Input !== '' && (isNaN(n3) || n3 < 0 || n3 > 50); + + const nAss = assignmentInput === '' ? NaN : Number(assignmentInput); + const isAssErr = assignmentInput !== '' && (isNaN(nAss) || nAss < 0 || nAss > 50); + + return ( +
+
+ {/* CAT I */} +
+
+ CAT I Mark +
+ + Max 50 + + + Assigned: 11.43 / 40 + +
+
+ { + setCat1Input(e.target.value); + setCalculatedScore(null); + setInternalError(null); + setShowWeightages((prev) => ({ ...prev, cat1: false })); + }} + placeholder="Enter CAT 1 mark (0 - 50)" + className={`w-full px-3.5 py-2.5 rounded-xl bg-white border ${isCat1Err ? 'border-red-500 text-red-600 focus:ring-red-500/20' : 'border-[#CBD5E1] text-[#1E293B] focus:border-[#8B5CF6] focus:ring-[#8B5CF6]/20'} text-sm font-bold focus:ring-2 outline-none`} + /> + {isCat1Err ? ( +

+ Enter a valid mark between 0 and 50 +

+ ) : ( +
+ + {showWeightages['cat1'] && !isNaN(n1) && n1 >= 0 && n1 <= 50 && ( + + Obtained: {((n1 / 50) * 11.43).toFixed(2)} / 11.43 + + )} +
+ )} +
+ + {/* CAT II */} +
+
+ CAT II Mark +
+ + Max 25 + + + Assigned: 5.71 / 40 + +
+
+ { + setCat2Input(e.target.value); + setCalculatedScore(null); + setInternalError(null); + setShowWeightages((prev) => ({ ...prev, cat2: false })); + }} + placeholder="Enter CAT 2 mark (0 - 25)" + className={`w-full px-3.5 py-2.5 rounded-xl bg-white border ${isCat2Err ? 'border-red-500 text-red-600 focus:ring-red-500/20' : 'border-[#CBD5E1] text-[#1E293B] focus:border-[#8B5CF6] focus:ring-[#8B5CF6]/20'} text-sm font-bold focus:ring-2 outline-none`} + /> + {isCat2Err ? ( +

+ Enter a valid mark between 0 and 25 +

+ ) : ( +
+ + {showWeightages['cat2'] && !isNaN(n2) && n2 >= 0 && n2 <= 25 && ( + + Obtained: {((n2 / 25) * 5.71).toFixed(2)} / 5.71 + + )} +
+ )} +
+ + {/* CAT III */} +
+
+ CAT III Mark +
+ + Max 50 + + + Assigned: 11.43 / 40 + +
+
+ { + setCat3Input(e.target.value); + setCalculatedScore(null); + setInternalError(null); + setShowWeightages((prev) => ({ ...prev, cat3: false })); + }} + placeholder="Enter CAT 3 mark (0 - 50)" + className={`w-full px-3.5 py-2.5 rounded-xl bg-white border ${isCat3Err ? 'border-red-500 text-red-600 focus:ring-red-500/20' : 'border-[#CBD5E1] text-[#1E293B] focus:border-[#8B5CF6] focus:ring-[#8B5CF6]/20'} text-sm font-bold focus:ring-2 outline-none`} + /> + {isCat3Err ? ( +

+ Enter a valid mark between 0 and 50 +

+ ) : ( +
+ + {showWeightages['cat3'] && !isNaN(n3) && n3 >= 0 && n3 <= 50 && ( + + Obtained: {((n3 / 50) * 11.43).toFixed(2)} / 11.43 + + )} +
+ )} +
+ + {/* Assignment */} +
+
+ Assignment Mark +
+ + Max 50 + + + Assigned: 11.43 / 40 + +
+
+ { + setAssignmentInput(e.target.value); + setCalculatedScore(null); + setInternalError(null); + setShowWeightages((prev) => ({ ...prev, assignment: false })); + }} + placeholder="Enter Assignment mark (0 - 50)" + className={`w-full px-3.5 py-2.5 rounded-xl bg-white border ${isAssErr ? 'border-red-500 text-red-600 focus:ring-red-500/20' : 'border-[#CBD5E1] text-[#1E293B] focus:border-[#8B5CF6] focus:ring-[#8B5CF6]/20'} text-sm font-bold focus:ring-2 outline-none`} + /> + {isAssErr ? ( +

+ Enter a valid mark between 0 and 50 +

+ ) : ( +
+ + {showWeightages['assignment'] && !isNaN(nAss) && nAss >= 0 && nAss <= 50 && ( + + Obtained: {((nAss / 50) * 11.43).toFixed(2)} / 11.43 + + )} +
+ )} +
+
+
+ ); + })() + )} + + {internalError && ( +
+ + {internalError}
)} @@ -1277,26 +1434,52 @@ export default function Toolkit() { {/* Calculated Result Card */} {calculatedScore !== null && (
- {calculationType === 'gpa' ? 'Calculated SGPA' : 'Average Internal Score'} - - - {gpaSemester} + {calculationType === 'gpa' ? 'Calculated SGPA' : 'Total Internal Mark'} + {gpaSemester && ( + + {gpaSemester} + + )}
-
+
-

{gpaDepartment}

+

+ {calculationType === 'gpa' ? gpaDepartment : 'Converted Internal Score'} +

{calculatedScore} {calculationType === 'gpa' ? '/ 10.00' : '/ 40.0'}
- - {calculationType === 'gpa' - ? (Number(calculatedScore) >= 9.0 ? 'First Class with Distinction (O)' : Number(calculatedScore) >= 8.5 ? 'First Class with Distinction' : Number(calculatedScore) >= 7.0 ? 'First Class' : Number(calculatedScore) >= 5.0 ? 'Second Class' : 'UA / Reappear') - : (Number(calculatedScore) >= 35 ? 'Excellent' : 'Good')} - +
+ {calculationType === 'internal' && (() => { + const c1 = Math.min(50, Math.max(0, Number(cat1Input) || 0)); + const c2 = Math.min(25, Math.max(0, Number(cat2Input) || 0)); + const c3 = Math.min(50, Math.max(0, Number(cat3Input) || 0)); + const ass = Math.min(50, Math.max(0, Number(assignmentInput) || 0)); + const totalRaw = c1 + c2 + c3 + ass; + return ( +
+

Total Raw Marks Obtained

+

+ {totalRaw} / 175 Marks +

+
+ ); + })()} +
+ + {calculationType === 'internal' && (() => { + const c1 = Math.min(50, Math.max(0, Number(cat1Input) || 0)); + const c2 = Math.min(25, Math.max(0, Number(cat2Input) || 0)); + const c3 = Math.min(50, Math.max(0, Number(cat3Input) || 0)); + const ass = Math.min(50, Math.max(0, Number(assignmentInput) || 0)); + + const w1 = ((c1 / 50) * 11.43).toFixed(2); + const w2 = ((c2 / 25) * 5.71).toFixed(2); + const w3 = ((c3 / 50) * 11.43).toFixed(2); + const wAss = ((ass / 50) * 11.43).toFixed(2); + + return ( +
+

+ Assigned 40-Mark Weightage Breakdown +

+
+
+

CAT I (11.43)

+

{w1} / 11.43

+

{c1}/50

+
+
+

CAT II (5.71)

+

{w2} / 5.71

+

{c2}/25

+
+
+

CAT III (11.43)

+

{w3} / 11.43

+

{c3}/50

+
+
+

Assignment (11.43)

+

{wAss} / 11.43

+

{ass}/50

+
+
+
+ ); + })()} )}