feat: Anna University CGPA formula, credit fixes, academic overview dashboard, lab/theory badges
This commit is contained in:
@@ -9,6 +9,8 @@ import { getBackendUrl } from '@/lib/utils';
|
||||
import { StaggerContainer, StaggerItem } from '@/components/AnimatedContainer/AnimatedContainer';
|
||||
import AnimatedContainer from '@/components/AnimatedContainer/AnimatedContainer';
|
||||
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
|
||||
const TRENDING_TAGS = ['hostel', 'academics', 'clubs', 'campus', 'canteen', 'sports', 'placement', 'library', 'cat exam', 'semester', 'labs', 'exams'];
|
||||
|
||||
const AVATARS: Record<string, string> = {
|
||||
|
||||
@@ -45,11 +45,13 @@ function normalizeDepartmentName(input?: string | null): string | null {
|
||||
|
||||
export default function Faculty() {
|
||||
const [searchParams] = useSearchParams();
|
||||
const [searchFaculty, setSearchFaculty] = useState('');
|
||||
const [searchFaculty, setSearchFaculty] = useState(() => searchParams.get('search') || '');
|
||||
const [sortBy, setSortBy] = useState('Name A-Z');
|
||||
|
||||
// Initial department detection (from URL query string or logged-in IMS student session)
|
||||
const initialDepartment = useMemo(() => {
|
||||
if (searchParams.has('search')) return 'All Departments';
|
||||
|
||||
const queryDept = searchParams.get('dept');
|
||||
const matchedQuery = normalizeDepartmentName(queryDept);
|
||||
if (matchedQuery) return matchedQuery;
|
||||
@@ -65,10 +67,16 @@ export default function Faculty() {
|
||||
|
||||
const [selectedDept, setSelectedDept] = useState<string>(initialDepartment);
|
||||
|
||||
// Update selectedDept if URL parameter changes
|
||||
// Update selectedDept and searchFaculty if URL parameter changes
|
||||
useEffect(() => {
|
||||
setSelectedDept(initialDepartment);
|
||||
}, [initialDepartment]);
|
||||
const querySearch = searchParams.get('search');
|
||||
if (querySearch !== null) {
|
||||
setSearchFaculty(querySearch);
|
||||
setSelectedDept('All Departments');
|
||||
} else {
|
||||
setSelectedDept(initialDepartment);
|
||||
}
|
||||
}, [searchParams, initialDepartment]);
|
||||
|
||||
const studentSession = useMemo(() => getStoredImsSession(), []);
|
||||
const isStudentDeptAutoFiltered = selectedDept !== 'All Departments' && (
|
||||
|
||||
@@ -2,9 +2,10 @@ import { useState, useEffect } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import {
|
||||
Trophy, Search, Plus, RefreshCw, ExternalLink, Code2,
|
||||
Sparkles, Flame, Award, CheckCircle2, Shield, User, Filter, X, Clock
|
||||
Sparkles, Flame, Award, CheckCircle2, Shield, User, Filter, X, Clock, Lock
|
||||
} from 'lucide-react';
|
||||
import { getBackendUrl } from '@/lib/utils';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
|
||||
interface LeetcodeProfile {
|
||||
id: number;
|
||||
@@ -25,6 +26,7 @@ const DEPARTMENTS = ['All', 'CSE', 'IT', 'AI&DS', 'ECE', 'EEE', 'MECH', 'CIVIL',
|
||||
const YEARS = ['All', '1st Year', '2nd Year', '3rd Year', '4th Year'];
|
||||
|
||||
export default function LeetcodeLeaderboard() {
|
||||
const { isAuthenticated, openAuthModal } = useAuth();
|
||||
const [profiles, setProfiles] = useState<LeetcodeProfile[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
@@ -42,8 +44,36 @@ export default function LeetcodeLeaderboard() {
|
||||
const [year, setYear] = useState('1st Year');
|
||||
|
||||
useEffect(() => {
|
||||
fetchLeaderboard();
|
||||
}, []);
|
||||
if (isAuthenticated) {
|
||||
fetchLeaderboard();
|
||||
}
|
||||
}, [isAuthenticated]);
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return (
|
||||
<div className="min-h-screen pt-24 pb-16 bg-[#FAF9FC] text-[#1A0B2E] px-4 flex flex-col items-center justify-center text-center">
|
||||
<div className="w-full max-w-md bg-white border border-[#E9E5EE] rounded-3xl p-8 shadow-xl space-y-5">
|
||||
<div className="w-16 h-16 rounded-2xl bg-orange-100 text-[#FF6B00] flex items-center justify-center mx-auto border border-orange-200 shadow-md">
|
||||
<Lock className="w-8 h-8" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-xl font-extrabold text-[#1A0B2E]" style={{ fontFamily: 'Plus Jakarta Sans, sans-serif' }}>
|
||||
Student Sign In Required
|
||||
</h2>
|
||||
<p className="text-xs text-[#4A3E5E] mt-1.5 leading-relaxed">
|
||||
RIT LeetCode Arena & Campus Rankings are accessible exclusively to verified RIT students. Please sign in with your student credentials to view the rankings and register your handle.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={openAuthModal}
|
||||
className="w-full py-3.5 px-4 rounded-xl text-white font-bold text-xs bg-gradient-to-r from-[#FF6B00] to-[#F97316] hover:opacity-95 shadow-lg shadow-orange-500/20 transition-all cursor-pointer"
|
||||
>
|
||||
Sign In to LeetCode Arena
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const fetchLeaderboard = async () => {
|
||||
setLoading(true);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user