diff --git a/src/components/EductionPortal/EducationPortalSideNav/EducationPortalSideNav.jsx b/src/components/EductionPortal/EducationPortalSideNav/EducationPortalSideNav.jsx
new file mode 100644
index 0000000000..2352e5969c
--- /dev/null
+++ b/src/components/EductionPortal/EducationPortalSideNav/EducationPortalSideNav.jsx
@@ -0,0 +1,90 @@
+import React from 'react';
+import { NavLink, useLocation } from 'react-router-dom';
+import { useSelector } from 'react-redux';
+import { useSidebar } from '../SidebarContext';
+import styles from './EducationPortalSideNav.module.css';
+
+const EducationPortalSideNav = () => {
+ const location = useLocation();
+ const authUser = useSelector(state => state.auth?.user);
+ const { isMinimized, setIsMinimized } = useSidebar();
+
+ const menuItems = [
+ { icon: '🏠', label: 'Homepage', path: '/educationportal' },
+ { icon: '📊', label: 'Knowledge Evaluation', path: '#' },
+ { icon: '📋', label: 'Past Lesson Plans', path: '#' },
+ { icon: '⭐', label: 'My Saved Interests', path: '#' },
+ { icon: '📈', label: 'Evaluation results', path: '/educationportal/evaluation-results' },
+ { icon: '🏗️', label: 'Build Lesson Plan', path: '#' },
+ ];
+
+ const isActive = path => path !== '#' && location.pathname === path;
+
+ return (
+
+ {/* User Welcome Section */}
+
+
👋
+ {!isMinimized && (
+ <>
+
+
Welcome
+
{authUser?.firstName || 'Student'}
+
+
🔔
+ >
+ )}
+ {isMinimized && (
+
setIsMinimized(!isMinimized)}
+ title="Expand sidebar"
+ aria-label="Expand sidebar"
+ >
+ ➜
+
+ )}
+
+
+ {/* Toggle Button - Only show when expanded */}
+ {!isMinimized && (
+
+ setIsMinimized(!isMinimized)}
+ title="Minimize sidebar"
+ aria-label="Minimize sidebar"
+ >
+ ⬅️
+
+
+ )}
+
+ {/* Navigation Menu */}
+
+
+
+
+ );
+};
+
+export default EducationPortalSideNav;
diff --git a/src/components/EductionPortal/EducationPortalSideNav/EducationPortalSideNav.module.css b/src/components/EductionPortal/EducationPortalSideNav/EducationPortalSideNav.module.css
new file mode 100644
index 0000000000..5ae4c501b8
--- /dev/null
+++ b/src/components/EductionPortal/EducationPortalSideNav/EducationPortalSideNav.module.css
@@ -0,0 +1,447 @@
+/* ===== SIDEBAR CONTAINER ===== */
+.sidebar {
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 200px;
+ height: 100vh;
+ background-color: #f5f5f5;
+ border-right: 1px solid #ddd;
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ z-index: 1000;
+ transition: width 0.3s ease;
+}
+
+.sidebar.minimized {
+ width: 70px;
+}
+
+.sidebar.minimized .label,
+.sidebar.minimized .welcomeText,
+.sidebar.minimized .toggleButtonContainer {
+ display: none;
+}
+
+/* ===== USER SECTION ===== */
+.userSection {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 12px;
+ border-bottom: 1px solid #ddd;
+ background-color: #fff;
+}
+
+.welcomeIcon {
+ font-size: 20px;
+ flex-shrink: 0;
+}
+
+.welcomeText {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ min-width: 0;
+}
+
+.welcomeLabel {
+ font-size: 11px;
+ color: #999;
+ font-weight: 500;
+ text-transform: uppercase;
+}
+
+.userName {
+ font-size: 12px;
+ font-weight: 600;
+ color: #333;
+ word-break: break-word;
+}
+
+.notifyIcon {
+ font-size: 16px;
+ flex-shrink: 0;
+ cursor: pointer;
+}
+
+/* ===== NAVIGATION ===== */
+.nav {
+ flex: 1;
+ overflow-y: auto;
+ padding: 8px 0;
+}
+
+.menuList {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.menuItem {
+ margin: 0;
+ padding: 0;
+}
+
+.menuLink {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 10px 12px;
+ color: #333;
+ text-decoration: none;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ width: 100%;
+ text-align: left;
+ font-size: 13px;
+ font-weight: 500;
+ transition: background-color 0.2s ease;
+ min-height: 44px;
+}
+
+.menuLink:hover {
+ background-color: #efefef;
+}
+
+.menuLink.active {
+ background-color: #e0e7ff;
+ color: #4f46e5;
+}
+
+.icon {
+ font-size: 14px;
+ flex-shrink: 0;
+ width: 18px;
+ text-align: center;
+}
+
+.label {
+ flex: 1;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+/* ===== TOGGLE BUTTONS ===== */
+.toggleButtonContainer {
+ display: flex;
+ justify-content: center;
+ padding: 8px;
+ border-top: 1px solid #ddd;
+ background-color: #fff;
+}
+
+.minimizeBtn {
+ background: none;
+ border: 1px solid #ddd;
+ padding: 8px 12px;
+ cursor: pointer;
+ border-radius: 4px;
+ font-size: 14px;
+ transition: all 0.2s ease;
+ width: 100%;
+}
+
+.minimizeBtn:hover {
+ background-color: #f0f0f0;
+ border-color: #999;
+}
+
+.toggleButton {
+ background: none;
+ border: none;
+ padding: 8px;
+ cursor: pointer;
+ font-size: 18px;
+ transition: all 0.2s ease;
+ width: 100%;
+ height: 48px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+}
+
+.toggleButton:hover {
+ background-color: #efefef;
+}
+
+/* ===== RESPONSIVE - DESKTOP (≥992px) ===== */
+@media (min-width: 992px) {
+ /* Desktop: sidebar visible by default */
+}
+
+/* ===== RESPONSIVE - TABLET (768px - 991px) ===== */
+@media (max-width: 991px) {
+ .sidebar {
+ width: 180px;
+ }
+
+ .sidebar.minimized {
+ width: 70px;
+ }
+
+ .userSection {
+ padding: 10px;
+ gap: 6px;
+ }
+
+ .welcomeIcon {
+ font-size: 16px;
+ }
+
+ .welcomeLabel {
+ font-size: 10px;
+ }
+
+ .userName {
+ font-size: 11px;
+ }
+
+ .notifyIcon {
+ font-size: 14px;
+ }
+
+ .menuLink {
+ padding: 8px 10px;
+ font-size: 12px;
+ gap: 6px;
+ }
+
+ .icon {
+ font-size: 12px;
+ width: 16px;
+ }
+}
+
+/* ===== RESPONSIVE - MOBILE (≤767px) ===== */
+@media (max-width: 767px) {
+ .sidebar {
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 240px;
+ height: 100vh;
+ background-color: #f5f5f5;
+ border-right: 1px solid #ddd;
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ z-index: 1000;
+ transition: width 0.3s ease;
+ }
+
+ .sidebar.minimized {
+ width: 70px;
+ }
+
+ .sidebar.minimized .label,
+ .sidebar.minimized .welcomeText,
+ .sidebar.minimized .toggleButtonContainer {
+ display: none;
+ }
+
+ .userSection {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 14px 12px;
+ border-bottom: 1px solid #ddd;
+ background-color: #fff;
+ }
+
+ .welcomeIcon {
+ font-size: 18px;
+ flex-shrink: 0;
+ }
+
+ .welcomeText {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ min-width: 0;
+ }
+
+ .welcomeLabel {
+ font-size: 10px;
+ color: #999;
+ font-weight: 500;
+ text-transform: uppercase;
+ }
+
+ .userName {
+ font-size: 12px;
+ font-weight: 600;
+ color: #333;
+ word-break: break-word;
+ }
+
+ .notifyIcon {
+ font-size: 16px;
+ flex-shrink: 0;
+ cursor: pointer;
+ padding: 6px;
+ border-radius: 4px;
+ transition: background-color 0.2s ease;
+ }
+
+ .notifyIcon:active {
+ background-color: #e0e0e0;
+ }
+
+ .nav {
+ flex: 1;
+ overflow-y: auto;
+ padding: 8px 0;
+ }
+
+ .menuList {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
+
+ .menuItem {
+ margin: 0;
+ padding: 0;
+ }
+
+ .menuLink {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 12px 14px;
+ color: #333;
+ text-decoration: none;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ width: 100%;
+ text-align: left;
+ font-size: 13px;
+ font-weight: 500;
+ transition: all 0.2s ease;
+ min-height: 48px;
+ }
+
+ .menuLink:active {
+ background-color: #f0f0f0;
+ }
+
+ .menuLink:hover {
+ background-color: #efefef;
+ }
+
+ .menuLink.active {
+ background-color: #e0e7ff;
+ color: #4f46e5;
+ border-left: 3px solid #4f46e5;
+ padding-left: 11px;
+ }
+
+ .icon {
+ font-size: 16px;
+ flex-shrink: 0;
+ width: 20px;
+ text-align: center;
+ }
+
+ .label {
+ flex: 1;
+ white-space: normal;
+ overflow: visible;
+ text-overflow: clip;
+ word-wrap: break-word;
+ }
+}
+
+/* ===== RESPONSIVE - SMALL PHONES (≤480px) ===== */
+@media (max-width: 480px) {
+ .sidebar {
+ width: 220px;
+ }
+
+ .sidebar.minimized {
+ width: 70px;
+ }
+
+ .sidebar.minimized .label,
+ .sidebar.minimized .welcomeText,
+ .sidebar.minimized .toggleButtonContainer {
+ display: none;
+ }
+
+ .userSection {
+ padding: 12px 10px;
+ }
+
+ .welcomeIcon {
+ font-size: 16px;
+ }
+
+ .userName {
+ font-size: 11px;
+ }
+
+ .menuLink {
+ padding: 11px 12px;
+ font-size: 12px;
+ gap: 8px;
+ }
+
+ .icon {
+ font-size: 14px;
+ width: 18px;
+ }
+}
+
+/* ===== RESPONSIVE - EXTRA SMALL (≤360px) ===== */
+@media (max-width: 359px) {
+ .sidebar {
+ width: 200px;
+ }
+
+ .sidebar.minimized {
+ width: 70px;
+ }
+
+ .sidebar.minimized .label,
+ .sidebar.minimized .welcomeText,
+ .sidebar.minimized .toggleButtonContainer {
+ display: none;
+ }
+
+ .userSection {
+ padding: 10px 8px;
+ gap: 6px;
+ }
+
+ .welcomeIcon {
+ font-size: 14px;
+ }
+
+ .welcomeLabel {
+ font-size: 9px;
+ }
+
+ .userName {
+ font-size: 10px;
+ }
+
+ .menuLink {
+ padding: 10px 10px;
+ font-size: 11px;
+ gap: 6px;
+ min-height: 44px;
+ }
+
+ .icon {
+ font-size: 12px;
+ width: 16px;
+ }
+}
diff --git a/src/components/EductionPortal/EvaluationResults/CategoryBreakdown.jsx b/src/components/EductionPortal/EvaluationResults/CategoryBreakdown.jsx
new file mode 100644
index 0000000000..c1033b4375
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/CategoryBreakdown.jsx
@@ -0,0 +1,317 @@
+import React from 'react';
+import { Card, CardBody, CardHeader, Progress, Badge, Row, Col } from 'reactstrap';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {
+ faChartPie,
+ faClipboardCheck,
+ faQuestion,
+ faGraduationCap,
+ faProjectDiagram,
+ faWeight,
+ faCheckCircle,
+ faClock,
+ faExclamationTriangle,
+} from '@fortawesome/free-solid-svg-icons';
+import { getPerformanceLevel, calculateCategoryProgress } from './mockData_new';
+import styles from './CategoryBreakdown.module.css';
+
+const CategoryBreakdown = ({ categories, selectedCategory = 'all', isLoading }) => {
+ if (isLoading) {
+ return (
+
+
+
+
+
Loading category breakdown...
+
+
+
+ );
+ }
+
+ if (!categories || categories.length === 0) {
+ return (
+
+
+
+
+
No category data available yet.
+
+
+
+ );
+ }
+
+ // Filter categories based on selected category
+ const filteredCategories =
+ selectedCategory === 'all'
+ ? categories
+ : categories.filter(category => category.name.toLowerCase() === selectedCategory);
+
+ const getCategoryIcon = categoryId => {
+ const icons = {
+ assignments: faClipboardCheck,
+ quizzes: faQuestion,
+ exams: faGraduationCap,
+ projects: faProjectDiagram,
+ };
+ return icons[categoryId] || faClipboardCheck;
+ };
+
+ const getStatusIcon = status => {
+ if (status === 'excellent') return faCheckCircle;
+ if (status === 'good') return faCheckCircle;
+ if (status === 'fair') return faClock;
+ return faExclamationTriangle;
+ };
+
+ return (
+
+
+
+
+
+
+
+ {selectedCategory === 'all'
+ ? 'Category Breakdown'
+ : `${selectedCategory.charAt(0).toUpperCase() +
+ selectedCategory.slice(1)} Performance`}
+
+
+ {selectedCategory === 'all'
+ ? `Showing all ${categories.length} categories`
+ : `Showing ${filteredCategories.length} selected category`}
+
+
+
+
+
+ Instructor: Dr. Emily Rodriguez • Professor of Computer Science
+
+
+
+
+
+
+
+ {filteredCategories.map(category => {
+ const performanceInfo = getPerformanceLevel(category.percentage);
+ const progressInfo = calculateCategoryProgress(category);
+ const isOverdue = new Date(category.dueDate) < new Date() && !progressInfo.isComplete;
+
+ return (
+
+
+ {/* Category Header */}
+
+
+
+
+
+
+
{category.name}
+
{category.description}
+
+
+
+
+
+ {performanceInfo.label}
+
+
+
+ {category.weightage}%
+
+
+
+
+ {/* Score Display */}
+
+
+
{category.percentage.toFixed(1)}%
+
+ {category.earnedMarks}
+ /
+ {category.totalMarks}
+
+
+
+
+ {/* Clear visual indicator instead of confusing lines */}
+
+
+
+
+ {/* Completion Status */}
+
+
+
Completion:
+
+ {category.completedItems}/{category.totalItems} (
+ {progressInfo.completionRate}%)
+
+
+
+
+
+
+ On Time: {category.submissions?.onTime || 0}
+
+
+
+
+
+ Late: {category.submissions?.late || 0}
+
+
+
+
+
+ Missing: {category.submissions?.missing || 0}
+
+
+
+
+
+ {/* Date Alerts Section */}
+ {(isOverdue || (!isOverdue && category.dueDate)) && (
+
+ {/* Overdue Alert */}
+ {isOverdue && (
+
+
+
+ Overdue:{' '}
+ {new Date(category.dueDate).toLocaleDateString('en-US', {
+ month: 'short',
+ day: 'numeric',
+ year: 'numeric',
+ })}
+
+
+ )}
+
+ {/* Due Date Info */}
+ {!isOverdue && category.dueDate && (
+
+
+
+ Due:{' '}
+ {new Date(category.dueDate).toLocaleDateString('en-US', {
+ month: 'short',
+ day: 'numeric',
+ year: 'numeric',
+ })}
+
+
+ )}
+
+ )}
+
+
+ );
+ })}
+
+
+ {/* Summary Statistics */}
+
+
Summary Statistics
+
+
+
+
+ {categories.reduce((sum, cat) => sum + cat.totalItems, 0)}
+
+
Total Items
+
+
+
+
+
+ {categories.reduce((sum, cat) => sum + cat.completedItems, 0)}
+
+
Completed
+
+
+
+
+
+ {Math.round(
+ categories.reduce((sum, cat) => sum + cat.percentage * cat.weightage, 0) /
+ categories.reduce((sum, cat) => sum + cat.weightage, 0),
+ )}
+ %
+
+
Weighted Average
+
+
+
+
+
+ {
+ categories.filter(
+ cat => getPerformanceLevel(cat.percentage).level === 'excellent',
+ ).length
+ }
+
+
Excellent Categories
+
+
+
+
+
+
+ );
+};
+
+export default CategoryBreakdown;
diff --git a/src/components/EductionPortal/EvaluationResults/CategoryBreakdown.module.css b/src/components/EductionPortal/EvaluationResults/CategoryBreakdown.module.css
new file mode 100644
index 0000000000..0d0e622c95
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/CategoryBreakdown.module.css
@@ -0,0 +1,803 @@
+/* CategoryBreakdown Component Styles */
+
+/* Main breakdown container */
+.breakdownCard {
+ border: 1px solid #e5e7eb;
+ border-radius: 16px;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+ background: #ffffff;
+ overflow: hidden;
+ transition: all 0.3s ease;
+}
+
+.breakdownCard:hover {
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
+}
+
+.breakdownCard.filtered {
+ border: 2px solid #4f46e5;
+ box-shadow: 0 10px 15px -3px rgba(79, 70, 229, 0.1), 0 4px 6px -2px rgba(79, 70, 229, 0.05);
+}
+
+.breakdownCard.filtered .categoryHeader {
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
+}
+
+/* Individual category cards */
+.categoryCard {
+ background: #ffffff;
+ border: 1px solid #e5e7eb;
+ border-radius: 16px;
+ margin-bottom: 1.5rem;
+ overflow: hidden;
+ transition: all 0.3s ease;
+ position: relative;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+}
+
+.categoryCard:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
+ border-color: #d1d5db;
+}
+
+.categoryCard.filtered {
+ border: 2px solid #4f46e5;
+ background: #f8faff;
+ box-shadow: 0 10px 15px -3px rgba(79, 70, 229, 0.1), 0 4px 6px -2px rgba(79, 70, 229, 0.05);
+}
+
+.categoryCard.filtered:hover {
+ box-shadow: 0 20px 25px -5px rgba(79, 70, 229, 0.1), 0 10px 10px -5px rgba(79, 70, 229, 0.04);
+}
+
+.breakdownCard.filtered .categoryHeader {
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
+}
+
+.categoryCard::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 4px;
+ background: var(--category-accent);
+ z-index: 1;
+}
+
+.categoryCard.excellent::before {
+ --category-accent: linear-gradient(90deg, #10b981, #065f46);
+}
+
+.categoryCard.excellent {
+ border-color: #d1fae5;
+}
+
+.categoryCard.excellent:hover {
+ border-color: #10b981;
+ box-shadow: 0 10px 15px -3px rgba(16, 185, 129, 0.1), 0 4px 6px -2px rgba(16, 185, 129, 0.05);
+}
+
+.categoryCard.good::before {
+ --category-accent: linear-gradient(90deg, #3b82f6, #1e40af);
+}
+
+.categoryCard.good {
+ border-color: #dbeafe;
+}
+
+.categoryCard.good:hover {
+ border-color: #3b82f6;
+ box-shadow: 0 10px 15px -3px rgba(59, 130, 246, 0.1), 0 4px 6px -2px rgba(59, 130, 246, 0.05);
+}
+
+.categoryCard.fair::before {
+ --category-accent: linear-gradient(90deg, #f59e0b, #92400e);
+}
+
+.categoryCard.fair {
+ border-color: #fef3c7;
+}
+
+.categoryCard.fair:hover {
+ border-color: #f59e0b;
+ box-shadow: 0 10px 15px -3px rgba(245, 158, 11, 0.1), 0 4px 6px -2px rgba(245, 158, 11, 0.05);
+}
+
+.categoryCard.poor::before {
+ --category-accent: linear-gradient(90deg, #ef4444, #991b1b);
+}
+
+.categoryCard.poor {
+ border-color: #fee2e2;
+}
+
+.categoryCard.poor:hover {
+ border-color: #ef4444;
+ box-shadow: 0 10px 15px -3px rgba(239, 68, 68, 0.1), 0 4px 6px -2px rgba(239, 68, 68, 0.05);
+}
+
+/* Clear Performance Indicator Bar - replaces confusing line charts */
+.performanceIndicatorBar {
+ width: 100%;
+ height: 8px;
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 4px;
+ overflow: hidden;
+ margin-top: 0.5rem;
+ position: relative;
+}
+
+.performanceLevel {
+ height: 100%;
+ border-radius: 4px;
+ transition: width 0.8s ease;
+ position: relative;
+}
+
+.performanceLevel.excellent {
+ background: linear-gradient(90deg, #10b981, #065f46);
+}
+
+.performanceLevel.good {
+ background: linear-gradient(90deg, #3b82f6, #1e40af);
+}
+
+.performanceLevel.fair {
+ background: linear-gradient(90deg, #f59e0b, #92400e);
+}
+
+.performanceLevel.poor {
+ background: linear-gradient(90deg, #ef4444, #991b1b);
+}
+
+/* Add a subtle pulse animation for better visibility */
+.performanceLevel::after {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(255, 255, 255, 0.2);
+ animation: shimmer 2s infinite;
+}
+
+@keyframes shimmer {
+ 0% { transform: translateX(-100%); }
+ 100% { transform: translateX(100%); }
+}
+
+.categoryHeader {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ padding: 2rem 1.5rem;
+ border-bottom: none;
+ position: relative;
+ overflow: hidden;
+}
+
+.categoryHeader::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 1px;
+ background: rgba(255, 255, 255, 0.2);
+}
+
+/* Category card content styles */
+.categoryInfo {
+ display: flex;
+ align-items: flex-start;
+ gap: 1rem;
+ flex: 1;
+}
+
+.categoryIconWrapper {
+ width: 48px;
+ height: 48px;
+ border-radius: 12px;
+ background: rgba(255, 255, 255, 0.15);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ backdrop-filter: blur(10px);
+}
+
+.categoryIcon {
+ font-size: 1.25rem;
+ color: rgba(255, 255, 255, 0.9) !important;
+}
+
+.categoryDetails {
+ flex: 1;
+}
+
+.categoryName {
+ margin: 0 0 0.5rem 0;
+ font-size: 1.25rem;
+ font-weight: 700;
+ color: #ffffff !important;
+ line-height: 1.2;
+ transition: all 0.3s ease;
+}
+
+.categoryDescription {
+ margin: 0;
+ font-size: 0.875rem;
+ color: rgba(255, 255, 255, 0.85) !important;
+ line-height: 1.4;
+ font-weight: 400;
+ transition: all 0.3s ease;
+}
+
+/* Improve text visibility on hover */
+.categoryCard:hover .categoryName {
+ color: #000000 !important;
+ font-weight: 800;
+}
+
+.categoryCard:hover .categoryDescription {
+ color: rgba(0, 0, 0, 0.75) !important;
+}
+
+.categoryBadges {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ align-items: flex-end;
+}
+
+/* Score section styles */
+.scoreSection {
+ padding: 1.5rem;
+ background: rgba(255, 255, 255, 0.05);
+ backdrop-filter: blur(10px);
+}
+
+.mainScore {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 1rem;
+}
+
+.scoreNumber {
+ font-size: 2rem;
+ font-weight: 800;
+ color: #ffffff !important;
+ line-height: 1;
+}
+
+/* Performance-based color coding for percentages - Clean light shades */
+.categoryCard.excellent .scoreNumber {
+ color: #34d399 !important;
+}
+
+.categoryCard.good .scoreNumber {
+ color: #60a5fa !important;
+}
+
+.categoryCard.fair .scoreNumber {
+ color: #fbbf24 !important;
+}
+
+.categoryCard.poor .scoreNumber {
+ color: #f87171 !important;
+}
+
+.scoreDetails {
+ font-size: 0.875rem;
+ color: rgba(255, 255, 255, 0.8) !important;
+ font-weight: 500;
+}
+
+.earnedMarks {
+ color: rgba(255, 255, 255, 0.9) !important;
+ font-weight: 600;
+}
+
+.separator {
+ color: rgba(255, 255, 255, 0.6) !important;
+ margin: 0 0.25rem;
+}
+
+.totalMarks {
+ color: rgba(255, 255, 255, 0.7) !important;
+}
+
+.progressWrapper {
+ margin-top: 0.5rem;
+}
+
+/* Completion section styles */
+.completionSection {
+ padding: 1.5rem;
+ background: rgba(255, 255, 255, 0.95);
+ color: #374151;
+}
+
+.completionRow {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1rem;
+}
+
+.completionLabel {
+ font-weight: 600;
+ color: #374151 !important;
+ font-size: 0.875rem;
+}
+
+.completionValue {
+ font-weight: 700;
+ color: #1f2937 !important;
+ font-size: 0.875rem;
+}
+
+.submissionStats {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+}
+
+.statItem {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.statDot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+}
+
+.statLabel {
+ font-size: 0.75rem;
+ color: #4b5563 !important;
+ font-weight: 500;
+}
+
+.headerContent {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+}
+
+.headerLeft {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.headerRight {
+ flex-shrink: 0;
+}
+
+.instructorInfo {
+ font-size: 0.875rem;
+ color: #6b7280;
+ margin: 0;
+ font-weight: 500;
+}
+
+/* Header styles */
+.breakdownHeader {
+ background: #f9fafb;
+ border-bottom: 1px solid #e5e7eb;
+ padding: 1.5rem 2rem;
+}
+
+.headerIcon {
+ font-size: 1.5rem;
+ color: #6366f1;
+}
+
+.headerTitle {
+ margin: 0;
+ font-size: 1.5rem;
+ font-weight: 600;
+ color: #111827;
+}
+
+.headerSubtitle {
+ margin: 0.25rem 0 0 0;
+ font-size: 0.875rem;
+ color: #6b7280;
+ font-weight: 400;
+}
+
+.headerRight {
+ display: flex;
+ align-items: center;
+}
+
+.countBadge {
+ background: rgba(255, 255, 255, 0.2);
+ color: white;
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ font-weight: 500;
+}
+
+.categoryBody {
+ padding: 0;
+}
+
+.categoryTable {
+ margin: 0;
+ border-collapse: separate;
+ border-spacing: 0;
+}
+
+.categoryTable thead th {
+ background: #f8f9fa;
+ color: #374151;
+ font-weight: 600;
+ font-size: 0.875rem;
+ padding: 1rem;
+ border-bottom: 2px solid #e5e7eb;
+ text-align: left;
+ position: sticky;
+ top: 0;
+ z-index: 10;
+}
+
+.categoryTable thead th:first-child {
+ border-top-left-radius: 0;
+}
+
+.categoryTable thead th:last-child {
+ border-top-right-radius: 0;
+}
+
+.categoryTable tbody tr {
+ transition: all 0.2s ease;
+}
+
+.categoryTable tbody tr:hover {
+ background: #f8f9fa;
+}
+
+.categoryTable tbody td {
+ padding: 1rem;
+ border-bottom: 1px solid #e5e7eb;
+ vertical-align: middle;
+}
+
+.categoryName {
+ font-weight: 600;
+ color: #1f2937;
+ font-size: 0.95rem;
+}
+
+.categoryIcon {
+ margin-right: 0.5rem;
+ width: 16px;
+ text-align: center;
+}
+
+.weightageCell {
+ font-weight: 600;
+ color: #4b5563;
+}
+
+.countCell {
+ font-size: 0.875rem;
+ color: #6b7280;
+}
+
+.marksCell {
+ font-weight: 500;
+ color: #374151;
+}
+
+.percentageCell {
+ font-weight: 600;
+ font-size: 1rem;
+}
+
+.performanceCell {
+ text-align: center;
+}
+
+.performanceIndicator {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 80px;
+ padding: 0.375rem 0.75rem;
+ border-radius: 20px;
+ font-size: 0.75rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.025em;
+}
+
+.performanceIndicator.excellent {
+ background: #d1fae5;
+ color: #065f46;
+ border: 1px solid #a7f3d0;
+}
+
+.performanceIndicator.good {
+ background: #dbeafe;
+ color: #1e40af;
+ border: 1px solid #93c5fd;
+}
+
+.performanceIndicator.fair {
+ background: #fef3c7;
+ color: #92400e;
+ border: 1px solid #fcd34d;
+}
+
+.performanceIndicator.poor {
+ background: #fee2e2;
+ color: #991b1b;
+ border: 1px solid #fca5a5;
+}
+
+.progressBar {
+ width: 100%;
+ height: 8px;
+ background: #e5e7eb;
+ border-radius: 4px;
+ overflow: hidden;
+ margin-top: 0.25rem;
+}
+
+.progressFill {
+ height: 100%;
+ border-radius: 4px;
+ transition: width 0.6s ease;
+}
+
+.progressFill.excellent {
+ background: linear-gradient(90deg, #10b981 0%, #065f46 100%);
+}
+
+.progressFill.good {
+ background: linear-gradient(90deg, #3b82f6 0%, #1e40af 100%);
+}
+
+.progressFill.fair {
+ background: linear-gradient(90deg, #f59e0b 0%, #92400e 100%);
+}
+
+.progressFill.poor {
+ background: linear-gradient(90deg, #ef4444 0%, #991b1b 100%);
+}
+
+.loadingContainer {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 3rem;
+ text-align: center;
+}
+
+.loadingSpinner {
+ width: 40px;
+ height: 40px;
+ border: 3px solid #e5e7eb;
+ border-top: 3px solid #4f46e5;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin-bottom: 1rem;
+}
+
+.loadingText {
+ color: #6b7280;
+ font-size: 0.875rem;
+ margin: 0;
+}
+
+.noDataContainer {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 3rem;
+ text-align: center;
+}
+
+.noDataIcon {
+ font-size: 3rem;
+ color: #d1d5db;
+ margin-bottom: 1rem;
+}
+
+.noDataText {
+ color: #6b7280;
+ font-size: 1rem;
+ margin: 0;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .categoryHeader {
+ padding: 1rem;
+ }
+
+ .headerContent {
+ flex-direction: column;
+ gap: 0.75rem;
+ align-items: flex-start;
+ }
+
+ .categoryTable {
+ font-size: 0.875rem;
+ }
+
+ .categoryTable thead th,
+ .categoryTable tbody td {
+ padding: 0.75rem 0.5rem;
+ }
+
+ .categoryName {
+ font-size: 0.875rem;
+ }
+
+ .performanceIndicator {
+ width: 70px;
+ font-size: 0.6875rem;
+ padding: 0.25rem 0.5rem;
+ }
+}
+
+@media (max-width: 480px) {
+ .categoryTable thead th,
+ .categoryTable tbody td {
+ padding: 0.5rem 0.375rem;
+ font-size: 0.8125rem;
+ }
+
+ .categoryName {
+ font-size: 0.8125rem;
+ }
+
+ .performanceIndicator {
+ width: 60px;
+ font-size: 0.625rem;
+ padding: 0.2rem 0.4rem;
+ }
+
+ .categoryIcon {
+ display: none;
+ }
+}
+
+.alertSection {
+ margin-top: 1rem;
+ display: flex;
+ gap: 1rem;
+ flex-wrap: wrap;
+}
+
+.overdueAlert {
+ background-color: #fee2e2; /* Light red background */
+ border: 1px solid #fca5a5;
+ border-radius: 8px;
+ padding: 0.75rem 1rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ flex: 1;
+ min-width: 250px;
+}
+
+.alertIcon {
+ color: #dc2626; /* Red color for icon */
+ font-size: 1rem;
+}
+
+.alertText {
+ color: #7f1d1d; /* Dark red text */
+ font-weight: 500;
+ font-size: 0.875rem;
+}
+
+.dueDateSection {
+ margin-top: 1rem;
+ display: flex;
+ gap: 1rem;
+ flex-wrap: wrap;
+}
+
+.dueDateInfo {
+ background-color: #dbeafe; /* Light blue background */
+ border: 1px solid #93c5fd;
+ border-radius: 8px;
+ padding: 0.75rem 1rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ flex: 1;
+ min-width: 250px;
+}
+
+.dueDateIcon {
+ color: #2563eb; /* Blue color for icon */
+ font-size: 1rem;
+}
+
+.dueDateText {
+ color: #1e3a8a; /* Dark blue text */
+ font-weight: 500;
+ font-size: 0.875rem;
+}
+
+/* Summary Statistics Styles */
+.summarySection {
+ margin-top: 2rem;
+ padding-top: 2rem;
+ border-top: 1px solid #e5e7eb;
+}
+
+.summaryTitle {
+ text-align: center;
+ font-size: 1.5rem;
+ font-weight: 600;
+ color: #111827;
+ margin-bottom: 2rem;
+}
+
+.summaryStats {
+ margin: 0;
+}
+
+.summaryCard {
+ background: #ffffff;
+ border: 1px solid #e5e7eb;
+ border-radius: 12px;
+ padding: 1.5rem 1rem;
+ text-align: center;
+ position: relative;
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
+ transition: all 0.3s ease;
+ margin-bottom: 1rem;
+}
+
+.summaryCard::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 4px;
+ background: linear-gradient(90deg, #6366f1, #8b5cf6);
+ border-radius: 12px 12px 0 0;
+}
+
+.summaryCard:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+}
+
+.summaryNumber {
+ font-size: 2.5rem;
+ font-weight: 700;
+ color: #111827;
+ line-height: 1;
+ margin-bottom: 0.5rem;
+}
+
+.summaryLabel {
+ font-size: 0.875rem;
+ font-weight: 500;
+ color: #6b7280;
+ text-transform: uppercase;
+ letter-spacing: 0.025em;
+}
\ No newline at end of file
diff --git a/src/components/EductionPortal/EvaluationResults/EvaluationResults.jsx b/src/components/EductionPortal/EvaluationResults/EvaluationResults.jsx
new file mode 100644
index 0000000000..92a2b52e29
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/EvaluationResults.jsx
@@ -0,0 +1,584 @@
+import React, { useState, useEffect } from 'react';
+import { connect } from 'react-redux';
+import { Container, Alert, Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {
+ faUser,
+ faBell,
+ faEye,
+ faGraduationCap,
+ faExclamationTriangle,
+ faTimes,
+ faCalendarAlt,
+ faPercent,
+ faAward,
+} from '@fortawesome/free-solid-svg-icons';
+
+import styles from './EvaluationResults.module.css';
+import SideBar from '../SideBar/SideBar';
+import { useSidebar } from '../SidebarContext';
+import EvaluationNotificationService from './evaluationNotificationService';
+import { mockEvaluationData } from './mockData_new';
+
+const EvaluationResults = ({ auth }) => {
+ const { isMinimized } = useSidebar();
+ const [evaluationData, setEvaluationData] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [selectedCategory, setSelectedCategory] = useState('all');
+ const [feedbackModal, setFeedbackModal] = useState({
+ isOpen: false,
+ task: null,
+ });
+
+ useEffect(() => {
+ // Load evaluation data immediately since we're using mock data
+ const loadEvaluationData = () => {
+ try {
+ // Personalize the evaluation data with actual user name
+ const userName = auth?.user?.firstName || 'Student';
+ const userLastName = auth?.user?.lastName || '';
+ const fullName = `${userName} ${userLastName}`.trim();
+ const userEmail = auth?.user?.email || 'student@school.edu';
+
+ const personalizedData = {
+ ...mockEvaluationData,
+ student: {
+ ...mockEvaluationData.student,
+ name: fullName,
+ email: userEmail,
+ },
+ teacherFeedback: {
+ ...mockEvaluationData.teacherFeedback,
+ overall: mockEvaluationData.teacherFeedback.overall.replace('Alex', userName),
+ },
+ tasks: mockEvaluationData.tasks.map(task => ({
+ ...task,
+ teamMembers: task.teamMembers
+ ? task.teamMembers.map(member => (member === 'Alex Johnson' ? fullName : member))
+ : task.teamMembers,
+ })),
+ };
+
+ setEvaluationData(personalizedData);
+
+ // Trigger notification for new results (simulate this is new data)
+ if (auth?.user?.userid && mockEvaluationData) {
+ EvaluationNotificationService.showPerformanceNotification(
+ mockEvaluationData.student.overallScore,
+ auth.user.firstName || 'Student',
+ );
+
+ // Mark results as viewed when user opens the page
+ EvaluationNotificationService.markResultsAsViewed(
+ auth.user.userid,
+ mockEvaluationData.student.id,
+ );
+ }
+ } catch (error) {
+ // Set fallback data to prevent infinite loading
+ setEvaluationData(mockEvaluationData);
+ } finally {
+ // Ensure loading is always set to false
+ setLoading(false);
+ }
+ };
+
+ loadEvaluationData();
+ }, [auth]);
+
+ if (loading) {
+ return (
+
+
+
+
Loading Your Academic Performance...
+
+
+
+ );
+ }
+
+ if (!evaluationData) {
+ return (
+
+
+
+ No evaluation results available at this time.
+
+
+ );
+ }
+
+ const { student, overallScore, categories, tasks, summary } = evaluationData;
+
+ // Calculate total score for new design (77/100 format)
+ const totalEarnedPoints = categories.reduce((sum, cat) => sum + cat.earnedMarks, 0);
+ const totalPossiblePoints = categories.reduce((sum, cat) => sum + cat.totalMarks, 0);
+ const percentageScore = Math.round((totalEarnedPoints / totalPossiblePoints) * 100);
+
+ // Helper functions
+ const getPerformanceColor = percentage => {
+ if (percentage >= 80) return 'excellent';
+ if (percentage >= 70) return 'good';
+ if (percentage >= 60) return 'fair';
+ return 'poor';
+ };
+
+ const getStatusClass = status => {
+ if (status === 'On time' || status === 'completed') return 'onTime';
+ if (status?.toLowerCase().includes('late')) return 'late';
+ return 'onTime';
+ };
+
+ const getPerformanceColorClass = percentage => {
+ if (percentage >= 80) return styles.excellent;
+ if (percentage >= 70) return styles.good;
+ if (percentage >= 60) return styles.fair;
+ return styles.poor;
+ };
+
+ // Generate dynamic performance insights based on actual data
+ const getPerformanceInsights = () => {
+ const strongAreas = categories.filter(cat => cat.percentage >= 80);
+ const improvementAreas = categories.filter(cat => cat.percentage < 70);
+
+ const strongText =
+ strongAreas.length > 0
+ ? strongAreas
+ .slice(0, 3)
+ .map(cat => `${cat.name} (${Math.round(cat.percentage)}%)`)
+ .join(', ')
+ : 'various areas';
+
+ const improvementText =
+ improvementAreas.length > 0 && improvementAreas[0]
+ ? `${improvementAreas[0].name} (${Math.round(improvementAreas[0].percentage)}%)`
+ : 'certain areas';
+
+ return { strongText, improvementText, hasImprovementAreas: improvementAreas.length > 0 };
+ };
+
+ const { strongText, improvementText, hasImprovementAreas } = getPerformanceInsights();
+
+ // Calculate summary statistics dynamically
+ const calculateSummaryStats = () => {
+ const totalAssignments = tasks.length;
+ const onTimeCount = tasks.filter(
+ task => task.status === 'On time' || task.status === 'completed',
+ ).length;
+ const lateCount = tasks.filter(task => task.status?.toLowerCase().includes('late')).length;
+ const averageScore = Math.round(
+ tasks.reduce((sum, task) => sum + task.percentage, 0) / tasks.length,
+ );
+
+ return { totalAssignments, onTimeCount, lateCount, averageScore };
+ };
+
+ const { totalAssignments, onTimeCount, lateCount, averageScore } = calculateSummaryStats();
+
+ const openFeedbackModal = task => {
+ setFeedbackModal({ isOpen: true, task });
+ };
+
+ const closeFeedbackModal = () => {
+ setFeedbackModal({ isOpen: false, task: null });
+ };
+
+ return (
+ <>
+
+
+ {/* New Clean Header */}
+
+
+
+
+
Evaluation Results
+
+ Comprehensive overview of your grades, performance on assignments, and detailed
+ feedback from teachers
+
+
+
+
+
+ Welcome, {auth?.user?.firstName || 'Student Name'}
+
+
+
+
+
+
+
+
+ {/* Overall Performance Summary */}
+
+
+
Overall Performance Summary
+
+ {percentageScore}%
+ Overall Grade
+
+
+
+
+
+
+ Total Score: {totalEarnedPoints}/{totalPossiblePoints} points
+
+
+
+
+
+ {/* Category Performance Table */}
+
+
Overall Performance Summary
+
+
+
+
+ Category
+ Weightage
+ Items
+ Total Points
+ Your Score
+ Percentage
+ Performance
+
+
+
+ {categories.map(category => (
+
+ {category.name}
+ {category.weightage}%
+ {category.completedItems}
+ {category.totalMarks}
+ {category.earnedMarks}
+ {Math.round(category.percentage)}%
+
+
+
+
+ ))}
+
+
+
+
+
+ {/* Performance Insights */}
+
+
+
Performance Insights
+
+ You performed strongly in {strongText} .
+ {hasImprovementAreas && (
+ <>
+ {' '}
+ You may improve your performance in {improvementText} -
+ consider reviewing preparation strategies.
+ >
+ )}
+
+
+ Review Assignment Messages
+ Study Schedule Tips
+
+
+
+
+ {/* Individual Assignment & Task Results */}
+
+
Individual Assignment & Task Results
+
+
+
+
+ Assignment Name
+ Weightage
+ Your Marks
+ Percentage
+ Status
+ Feedback
+
+
+
+ {tasks.slice(0, 6).map(task => (
+
+
+
+
{task.name}
+
+ Submitted: {new Date(task.submissionDate).toLocaleDateString()}
+
+
+
+ {task.weightage || '8'}%
+
+ {task.earnedMarks}/{task.totalMarks}
+
+
+
+ {Math.round(task.percentage)}%
+
+
+
+
+ {task.status || 'On time'}
+
+
+
+ openFeedbackModal(task)}
+ >
+
+ View Feedback
+
+
+
+ ))}
+
+
+
+
+ {/* Mobile Cards (shown on small screens) */}
+
+ {tasks.slice(0, 6).map(task => (
+
+
+
{task.name}
+
+ {task.status || 'On time'}
+
+
+
+
+ Weightage: {task.weightage || '8'}%
+
+
+ Score: {task.earnedMarks}/{task.totalMarks}
+
+ {' '}
+ ({Math.round(task.percentage)}%)
+
+
+
+ Submitted: {' '}
+ {new Date(task.submissionDate).toLocaleDateString()}
+
+
+
+ openFeedbackModal(task)}
+ >
+
+ View Feedback
+
+
+
+ ))}
+
+
+
+ {/* Teacher Feedback Section */}
+
+
+
+
+ Teacher Feedback - Structured feedback display with strengths and recommendations
+
+
+
+ {evaluationData.teacherFeedback.teacherName}
+
+
+ {evaluationData.teacherFeedback.teacherTitle}
+
+
+
+
+
+ {/* Overall Feedback */}
+
+
Overall Assessment
+
{evaluationData.teacherFeedback.overall}
+
+
+ {/* Strengths and Improvements */}
+
+
+
+
+ Strengths
+
+
+ {evaluationData.teacherFeedback.strengths.map((strength, index) => (
+
+ ✓
+ {strength}
+
+ ))}
+
+
+
+
+
+
+ Areas for Improvement
+
+
+ {evaluationData.teacherFeedback.improvements.map((improvement, index) => (
+
+ →
+ {improvement}
+
+ ))}
+
+
+
+
+
+
+ {/* Summary Cards */}
+
+
+
{totalAssignments}
+
Total Assignments
+
+
+
{onTimeCount}
+
On Time
+
+
+
{lateCount}
+
Late Submissions
+
+
+
{averageScore}%
+
Avg Score
+
+
+
+
+ {/* Feedback Detail Modal */}
+
+
+
+ Assignment Feedback Details
+
+
+ {feedbackModal.task && (
+
+ {/* Assignment Header */}
+
+
{feedbackModal.task.name}
+
+
+
+ {feedbackModal.task.type}
+
+
+
+ Due: {new Date(feedbackModal.task.dueDate).toLocaleDateString()}
+
+
+
+
+ {/* Performance Summary */}
+
+
+
Your Score
+
+ {feedbackModal.task.earnedMarks}/{feedbackModal.task.totalMarks}
+ ({feedbackModal.task.percentage}%)
+
+
+
+
Weightage
+
+
+ {feedbackModal.task.weightage}%
+
+
+
+
Status
+
+ {feedbackModal.task.status}
+
+
+
+
+ {/* Teacher Feedback */}
+
+
+
+ Teacher Feedback
+
+
{feedbackModal.task.teacherFeedback}
+
+
+ {/* Additional Details */}
+
+
+ Submission Date:
+
+ {new Date(feedbackModal.task.submissionDate).toLocaleDateString()} at{' '}
+ {new Date(feedbackModal.task.submissionDate).toLocaleTimeString()}
+
+
+
+ Grade Category:
+ {feedbackModal.task.category}
+
+
+
+ )}
+
+
+
+
+ Close
+
+
+
+
+ >
+ );
+};
+
+const mapStateToProps = state => ({
+ auth: state.auth,
+});
+
+export default connect(mapStateToProps)(EvaluationResults);
diff --git a/src/components/EductionPortal/EvaluationResults/EvaluationResults.module.css b/src/components/EductionPortal/EvaluationResults/EvaluationResults.module.css
new file mode 100644
index 0000000000..529758454d
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/EvaluationResults.module.css
@@ -0,0 +1,1718 @@
+/* ============================================================================
+ EVALUATION RESULTS - CLEAN ACADEMIC DASHBOARD
+ Modern table-based design matching the provided mockup
+ ============================================================================ */
+
+/* CSS Variables for clean academic theme */
+:root {
+ --primary-color: #007bff;
+ --success-color: #28a745;
+ --warning-color: #ffc107;
+ --danger-color: #dc3545;
+ --info-color: #17a2b8;
+ --text-dark: #333333;
+ --text-muted: #6c757d;
+ --bg-white: #ffffff;
+ --bg-light: #f8f9fa;
+ --border-color: #dee2e6;
+ --table-border: #e9ecef;
+ --box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
+ --border-radius: 0.375rem;
+}
+
+/* ============================================================================
+ MAIN PAGE LAYOUT - Clean White Background
+ ============================================================================ */
+
+.evaluationResultsPage {
+ min-height: 100vh;
+ background-color: var(--bg-light);
+ padding: 0;
+ margin-left: 200px;
+ transition: margin-left 0.3s ease;
+}
+
+/* When sidebar is minimized, expand the content */
+.evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+}
+
+@media (max-width: 991px) {
+ .evaluationResultsPage {
+ margin-left: 180px;
+ }
+
+ .evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+ }
+}
+
+@media (max-width: 767px) {
+ .evaluationResultsPage {
+ margin-left: 240px;
+ }
+
+ .evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+ }
+}
+
+@media (max-width: 480px) {
+ .evaluationResultsPage {
+ margin-left: 220px;
+ }
+
+ .evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+ }
+}
+
+@media (max-width: 359px) {
+ .evaluationResultsPage {
+ margin-left: 200px;
+ }
+
+ .evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+ }
+}
+
+/* ============================================================================
+ HEADER SECTION - Clean Professional Header
+ ============================================================================ */
+
+.headerSection {
+ background-color: var(--bg-white);
+ border-bottom: 1px solid var(--border-color);
+ padding: 2rem 0;
+ margin-bottom: 1.5rem;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
+}
+
+.headerContent {
+ display: flex;
+ justify-content: flex-start;
+ align-items: flex-start;
+ gap: 2rem;
+ position: relative;
+}
+
+.headerLeft {
+ flex: 1;
+ max-width: 600px;
+}
+
+.pageTitle {
+ font-size: 2rem;
+ font-weight: 700;
+ color: var(--text-dark);
+ margin: 0 0 0.75rem 0;
+ letter-spacing: -0.025em;
+ text-align: left;
+}
+
+.pageSubtitle {
+ font-size: 0.9rem;
+ color: var(--text-muted);
+ margin: 0;
+ line-height: 1.5;
+ max-width: 500px;
+ text-align: left;
+}
+
+.headerRight {
+ position: absolute;
+ right: 0;
+ top: 0;
+ display: flex;
+ align-items: center;
+ gap: 1.5rem;
+}
+
+.userWelcome {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-size: 0.9rem;
+ color: var(--text-dark);
+ font-weight: 500;
+ padding: 0.5rem 1rem;
+ background-color: #f8f9fa;
+ border-radius: 1.5rem;
+ border: 1px solid var(--border-color);
+}
+
+.userIcon {
+ color: var(--text-muted);
+ font-size: 0.875rem;
+}
+
+.notificationIcon {
+ font-size: 1.25rem;
+ color: var(--text-muted);
+ cursor: pointer;
+ padding: 0.5rem;
+ border-radius: 50%;
+ transition: all 0.2s ease;
+}
+
+.notificationIcon:hover {
+ color: var(--text-dark);
+ background-color: #f8f9fa;
+}
+
+/* ============================================================================
+ MAIN CONTENT CONTAINER
+ ============================================================================ */
+
+.mainContent {
+ max-width: 1400px;
+ margin: 0 auto;
+ padding: 0 0.75rem;
+}
+
+/* ============================================================================
+ OVERALL PERFORMANCE SECTION
+ ============================================================================ */
+
+.overallSection {
+ background-color: var(--bg-white);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ padding: 1.5rem;
+ margin-bottom: 1.5rem;
+}
+
+.sectionHeader {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1rem;
+}
+
+.sectionHeader h3 {
+ font-size: 1.125rem;
+ font-weight: 600;
+ color: var(--text-dark);
+ margin: 0;
+}
+
+.overallScore {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.scoreText {
+ font-size: 1.5rem;
+ font-weight: 700;
+ color: var(--text-dark);
+}
+
+.scoreLabel {
+ font-size: 0.875rem;
+ color: var(--text-muted);
+}
+
+.progressSection {
+ margin-top: 1rem;
+}
+
+.progressBar {
+ width: 100%;
+ height: 2rem;
+ background-color: #e0e0e0;
+ border-radius: 0;
+ overflow: hidden;
+ margin-bottom: 0.5rem;
+}
+
+.progressFill {
+ height: 100%;
+ background-color: #000000;
+ transition: width 0.3s ease;
+}
+
+.scoreDetails {
+ font-size: 0.875rem;
+ color: var(--text-muted);
+}
+
+/* ============================================================================
+ SECTION TITLES
+ ============================================================================ */
+
+.sectionTitle {
+ font-size: 1.125rem;
+ font-weight: 600;
+ color: var(--text-dark);
+ margin: 0 0 1rem 0;
+}
+
+/* ============================================================================
+ CATEGORY SECTION & PERFORMANCE TABLE
+ ============================================================================ */
+
+.categorySection {
+ background-color: var(--bg-white);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ padding: 1.5rem;
+ margin-bottom: 1.5rem;
+}
+
+.tableContainer {
+ overflow-x: auto;
+ border-radius: var(--border-radius);
+ border: 1px solid var(--table-border);
+}
+
+.performanceTable {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 0.875rem;
+ background-color: var(--bg-white);
+}
+
+.performanceTable th {
+ background-color: #f8f9fa;
+ color: var(--text-dark);
+ font-weight: 600;
+ padding: 1rem 0.75rem;
+ text-align: left;
+ border-bottom: 2px solid var(--table-border);
+ font-size: 0.875rem;
+}
+
+.performanceTable td {
+ padding: 1rem 0.75rem;
+ border-bottom: 1px solid var(--table-border);
+ vertical-align: middle;
+ font-size: 0.875rem;
+}
+
+.assignmentTable {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 0.875rem;
+ background-color: var(--bg-white);
+ table-layout: fixed;
+}
+
+.assignmentTable th {
+ background-color: #f8f9fa;
+ color: var(--text-dark);
+ font-weight: 600;
+ padding: 1.25rem 0.75rem;
+ text-align: left;
+ border-bottom: 2px solid var(--table-border);
+ font-size: 0.875rem;
+}
+
+.assignmentTable th:nth-child(1) { width: 35%; } /* Assignment Name */
+.assignmentTable th:nth-child(2) { width: 12%; text-align: center; } /* Weightage */
+.assignmentTable th:nth-child(3) { width: 15%; text-align: center; } /* Your Marks */
+.assignmentTable th:nth-child(4) { width: 12%; text-align: center; } /* Percentage */
+.assignmentTable th:nth-child(5) { width: 15%; text-align: center; } /* Status */
+.assignmentTable th:nth-child(6) { width: 11%; text-align: center; } /* Feedback */
+
+.assignmentTable td {
+ padding: 1.25rem 0.75rem;
+ border-bottom: 1px solid var(--table-border);
+ vertical-align: middle;
+ font-size: 0.875rem;
+}
+
+.assignmentTable td:nth-child(2),
+.assignmentTable td:nth-child(3),
+.assignmentTable td:nth-child(4),
+.assignmentTable td:nth-child(5),
+.assignmentTable td:nth-child(6) {
+ text-align: center;
+}
+
+.categoryName {
+ font-weight: 500;
+ color: var(--text-dark);
+}
+
+.performanceBar {
+ width: 120px;
+ height: 0.75rem;
+ background-color: #e0e0e0;
+ border-radius: 0.375rem;
+ overflow: hidden;
+ position: relative;
+}
+
+.performanceFill {
+ height: 100%;
+ border-radius: 0.375rem;
+ transition: width 0.3s ease;
+}
+
+.performanceFill.excellent {
+ background-color: #28a745;
+}
+
+.performanceFill.good {
+ background-color: #28a745;
+}
+
+.performanceFill.fair {
+ background-color: #ffc107;
+}
+
+.performanceFill.poor {
+ background-color: #dc3545;
+}
+
+/* ============================================================================
+ PERFORMANCE INSIGHTS SECTION
+ ============================================================================ */
+
+.insightsSection {
+ margin-bottom: 1.5rem;
+}
+
+.insightsBox {
+ background-color: #e3f2fd;
+ border: 1px solid #90caf9;
+ border-radius: var(--border-radius);
+ padding: 1.5rem;
+}
+
+.insightsBox h4 {
+ font-size: 1rem;
+ font-weight: 600;
+ color: var(--text-dark);
+ margin: 0 0 0.75rem 0;
+}
+
+.insightsBox p {
+ font-size: 0.875rem;
+ color: var(--text-dark);
+ line-height: 1.5;
+ margin: 0 0 1rem 0;
+}
+
+.actionButtons {
+ display: flex;
+ gap: 0.75rem;
+ flex-wrap: wrap;
+}
+
+.actionButton {
+ background-color: var(--primary-color);
+ color: white;
+ border: none;
+ padding: 0.5rem 1rem;
+ border-radius: var(--border-radius);
+ font-size: 0.875rem;
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+}
+
+.actionButton:hover {
+ background-color: #0056b3;
+}
+
+/* ============================================================================
+ ASSIGNMENT SECTION & TABLE
+ ============================================================================ */
+
+.assignmentSection {
+ background-color: var(--bg-white);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ padding: 1.5rem;
+ margin-bottom: 1.5rem;
+}
+
+/* Mobile assignment cards (hidden by default; enabled on small screens) */
+.mobileAssignments {
+ display: none;
+}
+
+.assignmentCard {
+ background-color: var(--bg-white);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ padding: 1rem;
+ margin-bottom: 0.75rem;
+ box-shadow: var(--box-shadow);
+}
+
+.cardHeader {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ gap: 0.75rem;
+ margin-bottom: 0.5rem;
+}
+
+.cardMeta {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 0.5rem 0.75rem;
+ margin-bottom: 0.75rem;
+}
+
+.cardMetaItem {
+ font-size: 0.85rem;
+ color: var(--text-dark);
+}
+
+.cardActions {
+ display: flex;
+ justify-content: flex-end;
+}
+
+.assignmentInfo {
+ display: flex;
+ flex-direction: column;
+ gap: 0.375rem;
+}
+
+.assignmentName {
+ font-weight: 500;
+ color: var(--text-dark);
+ font-size: 0.9rem;
+ line-height: 1.3;
+ word-break: break-word;
+ overflow-wrap: anywhere;
+}
+
+.assignmentDate {
+ font-size: 0.75rem;
+ color: var(--text-muted);
+}
+
+.statusBadge {
+ display: inline-block;
+ padding: 0.375rem 0.75rem;
+ border-radius: 1rem;
+ font-size: 0.75rem;
+ font-weight: 500;
+ text-align: center;
+ min-width: 80px;
+}
+
+.statusBadge.onTime {
+ background-color: #d4edda;
+ color: #155724;
+ border: 1px solid #c3e6cb;
+}
+
+.statusBadge.late {
+ background-color: #f8d7da;
+ color: #721c24;
+ border: 1px solid #f5c6cb;
+}
+
+.feedbackButton {
+ background-color: #f8f9fa;
+ border: 1px solid #dee2e6;
+ color: #6c757d;
+ padding: 0.375rem 0.75rem;
+ border-radius: 1rem;
+ font-size: 0.75rem;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 0.375rem;
+ transition: all 0.2s ease;
+ min-width: 100px;
+ justify-content: center;
+}
+
+.feedbackButton:hover {
+ background-color: #e9ecef;
+ color: #495057;
+ border-color: #adb5bd;
+}
+
+.buttonIcon {
+ font-size: 0.875rem;
+}
+
+/* Performance percentage colors */
+.excellent {
+ color: var(--success-color);
+ font-weight: 600;
+}
+
+.good {
+ color: var(--warning-color);
+ font-weight: 600;
+}
+
+.fair {
+ color: #fd7e14;
+ font-weight: 600;
+}
+
+.poor {
+ color: var(--danger-color);
+ font-weight: 600;
+}
+
+/* ============================================================================
+ SUMMARY CARDS
+ ============================================================================ */
+
+.summaryCards {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 1rem;
+ margin-bottom: 2rem;
+}
+
+.summaryCard {
+ background-color: var(--bg-white);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ padding: 1.5rem;
+ text-align: center;
+ box-shadow: var(--box-shadow);
+}
+
+.cardNumber {
+ font-size: 2rem;
+ font-weight: 700;
+ margin-bottom: 0.5rem;
+}
+
+.cardNumber.total {
+ color: var(--text-dark);
+}
+
+.cardNumber.onTime {
+ color: #28a745;
+}
+
+.cardNumber.late {
+ color: #dc3545;
+}
+
+.cardNumber.average {
+ color: #007bff;
+}
+
+.cardLabel {
+ font-size: 0.875rem;
+ color: var(--text-muted);
+ margin: 0;
+}
+
+/* ============================================================================
+ LOADING STATES
+ ============================================================================ */
+
+.loadingContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 3rem;
+ text-align: center;
+}
+
+.loadingSpinner {
+ width: 40px;
+ height: 40px;
+ border: 4px solid var(--bg-light);
+ border-top: 4px solid var(--primary-color);
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin-bottom: 1rem;
+}
+
+.loadingIcon {
+ font-size: 3rem;
+ color: var(--primary-color);
+ margin-bottom: 1rem;
+ animation: pulse 2s infinite;
+}
+
+.loadingSpinner h3 {
+ color: var(--text-dark);
+ margin-bottom: 1rem;
+}
+
+.loadingBar {
+ width: 200px;
+ height: 4px;
+ background-color: var(--bg-light);
+ border-radius: 2px;
+ overflow: hidden;
+}
+
+.loadingProgress {
+ width: 30%;
+ height: 100%;
+ background-color: var(--primary-color);
+ animation: progress 2s ease-in-out infinite;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+@keyframes pulse {
+ 0%, 100% { opacity: 1; }
+ 50% { opacity: 0.5; }
+}
+
+@keyframes progress {
+ 0% { transform: translateX(-100%); }
+ 50% { transform: translateX(0%); }
+ 100% { transform: translateX(100%); }
+}
+
+/* ============================================================================
+ NO DATA STATES
+ ============================================================================ */
+
+.noDataAlert {
+ text-align: center;
+ margin: 2rem 0;
+}
+
+/* ============================================================================
+ RESPONSIVE DESIGN
+ ============================================================================ */
+
+@media (max-width: 768px) {
+ .evaluationResultsPage {
+ padding: 0.5rem;
+ }
+
+ .headerSection {
+ padding: 1.5rem 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .headerContent {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1.25rem;
+ max-width: 100%;
+ }
+
+ .headerRight {
+ position: static;
+ align-self: flex-start;
+ width: 100%;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ }
+
+ .pageTitle {
+ font-size: 1.75rem;
+ line-height: 1.2;
+ margin-bottom: 0.5rem;
+ }
+
+ .pageSubtitle {
+ font-size: 0.9rem;
+ max-width: 100%;
+ line-height: 1.4;
+ }
+
+ .mainContent {
+ padding: 0 0.75rem;
+ }
+
+ .overallSection,
+ .categorySection,
+ .assignmentSection,
+ .insightsSection {
+ margin: 0 0 1.25rem 0;
+ padding: 1.25rem 1rem;
+ border-radius: 0.5rem;
+ }
+
+ .sectionHeader {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .overallScore {
+ align-self: flex-start;
+ width: 100%;
+ font-size: 1.5rem;
+ padding: 0.75rem 1rem;
+ text-align: center;
+ }
+
+ .actionButtons {
+ flex-direction: column;
+ width: 100%;
+ gap: 0.75rem;
+ }
+
+ .actionButton {
+ width: 100%;
+ text-align: center;
+ padding: 0.875rem 1rem;
+ margin-bottom: 0;
+ font-size: 0.95rem;
+ border-radius: 0.5rem;
+ min-height: 44px; /* Better touch target */
+ }
+
+ .summaryCards {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1rem;
+ }
+
+ /* Make tables responsive by allowing horizontal scroll */
+ .tableContainer {
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ margin: 0 -1rem;
+ padding: 0 1rem;
+ }
+
+ /* Keep headers visible when scrolling horizontally */
+ .assignmentTable thead th {
+ position: sticky;
+ top: 0;
+ background: #f8f9fa;
+ z-index: 1;
+ }
+
+ .categoryTable,
+ .assignmentTable {
+ min-width: 600px;
+ font-size: 0.9rem;
+ }
+
+ .categoryTable th,
+ .categoryTable td,
+ .assignmentTable th,
+ .assignmentTable td {
+ padding: 0.75rem 0.5rem;
+ white-space: nowrap;
+ }
+
+ .teacherFeedbackSection {
+ padding: 1.25rem;
+ margin: 0 0 1.25rem 0;
+ }
+
+ .feedbackColumns {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ margin-top: 1rem;
+ align-items: start;
+ }
+
+ .overallFeedback {
+ padding: 1.25rem;
+ margin-bottom: 1.5rem;
+ border-radius: 0.5rem;
+ }
+
+ .teacherInfo {
+ align-items: flex-start;
+ margin-bottom: 1rem;
+ padding: 1rem;
+ background: var(--bg-light);
+ border-radius: 0.5rem;
+ border: 1px solid var(--border-color);
+ }
+
+ .teacherName {
+ font-size: 1rem;
+ margin-bottom: 0.25rem;
+ }
+
+ .teacherTitle {
+ font-size: 0.875rem;
+ }
+
+ .feedbackColumns {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ margin-top: 1rem;
+ align-items: stretch; /* Make cards same height */
+ }
+
+ .strengthsSection,
+ .improvementsSection {
+ padding: 1rem;
+ border-radius: 0.5rem;
+ margin-bottom: 0;
+ min-width: 0;
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ height: fit-content;
+ display: flex;
+ flex-direction: column;
+ }
+
+ /* Modal mobile styles */
+ .feedbackModal .modal-dialog {
+ margin: 0.25rem;
+ max-width: calc(100% - 0.5rem);
+ }
+
+ .modalBody {
+ padding: 1.25rem;
+ max-height: 65vh;
+ }
+
+ .modalHeader {
+ padding: 1.25rem;
+ text-align: center;
+ }
+
+ .modalHeader h4 {
+ font-size: 1.1rem;
+ line-height: 1.3;
+ }
+
+ .modalFooter {
+ padding: 1rem;
+ flex-direction: column;
+ }
+
+ .modalFooter button {
+ width: 100%;
+ margin: 0;
+ }
+
+ .assignmentHeader,
+ .performanceSummary,
+ .teacherFeedbackDetail,
+ .additionalDetails {
+ padding: 1.25rem;
+ }
+
+ .assignmentMeta {
+ flex-direction: column;
+ gap: 0.75rem;
+ align-items: flex-start;
+ }
+
+ .performanceSummary {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 0.75rem;
+ }
+
+ .performanceItem {
+ padding: 0.75rem;
+ min-height: 70px;
+ }
+
+ .performanceValue {
+ font-size: 1.1rem;
+ }
+
+ .detailItem {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 0.5rem;
+ padding: 0.5rem 0;
+ }
+}
+
+@media (max-width: 480px) {
+ .evaluationResultsPage {
+ padding: 0.25rem;
+ }
+
+ /* Hide table, show cards */
+ .assignmentSection .tableContainer { display: none; }
+ .mobileAssignments { display: block; }
+
+ .summaryCards {
+ grid-template-columns: 1fr;
+ gap: 0.875rem;
+ }
+
+ .mainContent {
+ padding: 0 0.5rem;
+ }
+
+ .overallSection,
+ .categorySection,
+ .assignmentSection,
+ .insightsSection {
+ padding: 1rem;
+ margin: 0 0 1rem 0;
+ border-radius: 0.5rem;
+ }
+
+ .pageTitle {
+ font-size: 1.5rem;
+ text-align: left;
+ line-height: 1.2;
+ margin-bottom: 0.75rem;
+ }
+
+ .pageSubtitle {
+ font-size: 0.85rem;
+ text-align: left;
+ line-height: 1.4;
+ }
+
+ .headerSection {
+ padding: 1.25rem 0.75rem;
+ }
+
+ .userWelcome {
+ padding: 0.5rem 0.75rem;
+ font-size: 0.85rem;
+ border-radius: 1.25rem;
+ }
+
+ .notificationIcon {
+ font-size: 1rem;
+ min-height: 44px;
+ min-width: 44px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .categoryTable,
+ .assignmentTable {
+ min-width: 500px;
+ font-size: 0.8rem;
+ }
+
+ .categoryTable th,
+ .categoryTable td,
+ .assignmentTable th,
+ .assignmentTable td {
+ padding: 0.6rem 0.4rem;
+ }
+
+ .actionButton {
+ padding: 0.875rem 1rem;
+ font-size: 0.9rem;
+ min-height: 48px;
+ border-radius: 0.5rem;
+ font-weight: 500;
+ }
+
+ .feedbackButton {
+ width: 100%;
+ font-size: 0.875rem;
+ min-height: 44px;
+ padding: 0.75rem 1rem;
+ border-radius: 0.375rem;
+ }
+
+ .statusBadge {
+ min-width: auto;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.75rem;
+ border-radius: 0.375rem;
+ font-weight: 500;
+ }
+
+ .categoryTable,
+ .assignmentTable {
+ min-width: 500px;
+ font-size: 0.85rem;
+ }
+
+ .categoryTable th,
+ .categoryTable td,
+ /* Teacher Feedback mobile styles */
+ .teacherFeedbackSection {
+ padding: 1rem;
+ margin: 0 0 1rem 0;
+ border-radius: 0.5rem;
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ .feedbackColumns {
+ grid-template-columns: 1fr;
+ gap: 1rem;
+ margin-top: 1rem;
+ }
+
+ .teacherInfo {
+ padding: 0.875rem;
+ margin-bottom: 1rem;
+ background: var(--bg-light);
+ border-radius: 0.5rem;
+ align-items: flex-start;
+ }
+
+ .teacherName {
+ font-size: 1rem;
+ margin-bottom: 0.25rem;
+ }
+
+ .teacherTitle {
+ font-size: 0.875rem;
+ }
+
+ .overallFeedback {
+ padding: 1rem;
+ margin-bottom: 1.25rem;
+ border-radius: 0.5rem;
+ }
+
+ .feedbackColumns {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 1rem;
+ margin-top: 1rem;
+ align-items: stretch;
+ }
+
+ .strengthsSection,
+ .improvementsSection {
+ padding: 1rem;
+ margin: 0;
+ border-radius: 0.5rem;
+ min-width: 0;
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ .feedbackSubtitle {
+ font-size: 0.95rem;
+ margin-bottom: 0.75rem;
+ line-height: 1.3;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ flex-wrap: wrap;
+ }
+
+ .feedbackText {
+ font-size: 0.9rem;
+ line-height: 1.5;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ }
+
+ .feedbackIcon {
+ font-size: 0.9rem;
+ flex-shrink: 0;
+ }
+ .overallScore {
+ font-size: 1.375rem;
+ padding: 0.75rem;
+ text-align: center;
+ }
+}
+
+/* ============================================================================
+ TEACHER FEEDBACK SECTION - Structured feedback display
+ ============================================================================ */
+
+.teacherFeedbackSection {
+ background: var(--bg-white);
+ border-radius: var(--border-radius);
+ box-shadow: var(--box-shadow);
+ padding: 2rem;
+ margin-bottom: 1.5rem;
+ border: 1px solid var(--border-color);
+}
+
+.teacherInfo {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ gap: 0.25rem;
+}
+
+.teacherName {
+ font-weight: 600;
+ color: var(--primary-color);
+ font-size: 1rem;
+}
+
+.teacherTitle {
+ font-size: 0.875rem;
+ color: var(--text-muted);
+}
+
+.feedbackContent {
+ margin-top: 1.5rem;
+}
+
+.overallFeedback {
+ margin-bottom: 2rem;
+ padding: 1.25rem;
+ background: var(--bg-light);
+ border-radius: var(--border-radius);
+ border-left: 4px solid var(--primary-color);
+}
+
+.feedbackSubtitle {
+ font-size: 1.1rem;
+ font-weight: 600;
+ color: var(--text-dark);
+ margin-bottom: 0.75rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ line-height: 1.3;
+ flex-wrap: wrap;
+}
+
+.feedbackIcon {
+ font-size: 1rem;
+}
+
+.feedbackText {
+ color: var(--text-dark);
+ line-height: 1.6;
+ margin: 0;
+}
+
+.feedbackColumns {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 2rem;
+ margin-top: 1.5rem;
+ align-items: start;
+}
+
+.strengthsSection,
+.improvementsSection {
+ padding: 1.25rem;
+ border-radius: var(--border-radius);
+ border: 1px solid var(--border-color);
+}
+
+.strengthsSection {
+ background: linear-gradient(135deg, #f8fffe 0%, #e8f7f5 100%);
+ border-left: 4px solid var(--success-color);
+}
+
+.improvementsSection {
+ background: linear-gradient(135deg, #fffcf8 0%, #fef5e7 100%);
+ border-left: 4px solid var(--warning-color);
+}
+
+.feedbackList {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.feedbackItem {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ padding: 0.5rem 0;
+ color: var(--text-dark);
+ line-height: 1.5;
+ width: 100%;
+ flex-wrap: wrap;
+}
+
+.checkmark {
+ color: var(--success-color);
+ font-weight: bold;
+ font-size: 1.1rem;
+ margin-top: 0.1rem;
+ flex-shrink: 0;
+}
+
+.arrow {
+ color: var(--warning-color);
+ font-weight: bold;
+ font-size: 1.1rem;
+ margin-top: 0.1rem;
+ flex-shrink: 0;
+}
+
+/* Ensure list text wraps within card and doesn't overflow */
+.feedbackTextItem {
+ flex: 1 1 auto;
+ min-width: 0;
+ overflow-wrap: break-word;
+ word-break: break-word;
+}
+
+/* ============================================================================
+ FEEDBACK MODAL - Detailed assignment feedback display
+ ============================================================================ */
+
+.feedbackModal {
+ font-family: inherit;
+}
+
+.feedbackModal .modal-dialog {
+ margin: 0.5rem;
+ max-width: calc(100% - 1rem);
+}
+
+.modalHeader {
+ background: linear-gradient(135deg, var(--primary-color) 0%, #0056b3 100%);
+ color: white;
+ border-bottom: none;
+ padding: 1.5rem 2rem;
+ position: relative;
+}
+
+.modalHeader .btn-close {
+ color: white;
+ opacity: 0.8;
+ font-size: 1.2rem;
+}
+
+.modalHeader .btn-close:hover {
+ opacity: 1;
+}
+
+.modalIcon {
+ margin-right: 0.75rem;
+ font-size: 1.2rem;
+}
+
+.modalTitle {
+ font-weight: 600;
+ font-size: 1.25rem;
+}
+
+.modalBody {
+ padding: 2rem;
+ background: var(--bg-light);
+ max-height: 70vh;
+ overflow-y: auto;
+}
+
+.modalFooter {
+ border-top: 1px solid var(--border-color);
+ background: var(--bg-white);
+ padding: 1rem 2rem;
+ justify-content: center;
+}
+
+.modalFooter button {
+ min-width: 120px;
+ padding: 0.75rem 1.5rem;
+ font-weight: 500;
+}
+
+.feedbackModalContent {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+/* Assignment Header */
+.assignmentHeader {
+ background: var(--bg-white);
+ padding: 1.5rem;
+ border-radius: var(--border-radius);
+ border: 1px solid var(--border-color);
+ box-shadow: var(--box-shadow);
+}
+
+.assignmentTitle {
+ font-size: 1.4rem;
+ font-weight: 600;
+ color: var(--text-dark);
+ margin-bottom: 1rem;
+}
+
+.assignmentMeta {
+ display: flex;
+ gap: 2rem;
+ flex-wrap: wrap;
+}
+
+.assignmentType,
+.assignmentDate {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ color: var(--text-muted);
+ font-size: 0.9rem;
+}
+
+.assignmentType svg,
+.assignmentDate svg {
+ color: var(--primary-color);
+}
+
+/* Performance Summary */
+.performanceSummary {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
+ gap: 1rem;
+ background: var(--bg-white);
+ padding: 1.5rem;
+ border-radius: var(--border-radius);
+ border: 1px solid var(--border-color);
+ box-shadow: var(--box-shadow);
+}
+
+.performanceItem {
+ text-align: center;
+ padding: 1rem;
+ border-radius: var(--border-radius);
+ background: var(--bg-light);
+ min-height: 80px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ transition: transform 0.2s ease;
+}
+
+.performanceItem:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+}
+
+.performanceLabel {
+ font-size: 0.875rem;
+ color: var(--text-muted);
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+}
+
+.performanceValue {
+ font-size: 1.25rem;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+}
+
+.percentage {
+ font-size: 1rem;
+ font-weight: 400;
+}
+
+.statusValue {
+ padding: 0.25rem 0.75rem;
+ border-radius: 20px;
+ font-size: 0.875rem;
+ font-weight: 500;
+}
+
+/* Teacher Feedback Detail */
+.teacherFeedbackDetail {
+ background: var(--bg-white);
+ padding: 1.5rem;
+ border-radius: var(--border-radius);
+ border: 1px solid var(--border-color);
+ box-shadow: var(--box-shadow);
+}
+
+.feedbackTitle {
+ font-size: 1.1rem;
+ font-weight: 600;
+ color: var(--text-dark);
+ margin-bottom: 1rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.feedbackTitle svg {
+ color: var(--primary-color);
+}
+
+.feedbackText {
+ color: var(--text-dark);
+ line-height: 1.6;
+ padding: 1rem;
+ background: var(--bg-light);
+ border-radius: var(--border-radius);
+ border-left: 4px solid var(--primary-color);
+}
+
+/* Additional Details */
+.additionalDetails {
+ background: var(--bg-white);
+ padding: 1.5rem;
+ border-radius: var(--border-radius);
+ border: 1px solid var(--border-color);
+ box-shadow: var(--box-shadow);
+}
+
+.detailItem {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.75rem 0;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.detailItem:last-child {
+ border-bottom: none;
+}
+
+.detailLabel {
+ font-weight: 500;
+ color: var(--text-muted);
+}
+
+.detailValue {
+ color: var(--text-dark);
+ font-weight: 400;
+}
+
+/* ============================================================================
+ MOBILE RESPONSIVE BREAKPOINTS
+ ============================================================================ */
+
+/* Tablets (768px and below) */
+@media (max-width: 991px) and (min-width: 768px) {
+ .evaluationResultsPage {
+ margin-left: 180px;
+ }
+}
+
+/* Mobile phones (767px and below) */
+@media (max-width: 767px) {
+ .evaluationResultsPage {
+ margin-left: 240px;
+ }
+
+ .headerSection {
+ padding: 1.5rem 0;
+ margin-bottom: 1rem;
+ }
+
+ .headerContent {
+ flex-direction: column;
+ gap: 1rem;
+ }
+
+ .headerRight {
+ position: relative;
+ right: auto;
+ top: auto;
+ margin-top: 1rem;
+ }
+
+ .pageTitle {
+ font-size: 1.5rem;
+ }
+
+ .pageSubtitle {
+ font-size: 0.85rem;
+ }
+
+ .mainContent {
+ padding: 0 1rem;
+ }
+
+ .overallSection {
+ padding: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .sectionHeader {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 0.75rem;
+ }
+
+ .overallScore {
+ width: 100%;
+ }
+
+ .categorySection,
+ .assignmentSection,
+ .insightsSection,
+ .teacherFeedbackSection {
+ margin-bottom: 1rem;
+ }
+
+ .tableContainer {
+ overflow-x: auto;
+ border-radius: 0;
+ }
+
+ .performanceTable {
+ font-size: 0.75rem;
+ }
+
+ .performanceTable th,
+ .performanceTable td {
+ padding: 0.5rem;
+ }
+
+ .mobileAssignments {
+ display: block;
+ }
+
+ .assignmentTable {
+ display: none;
+ }
+
+ .assignmentCard {
+ margin-bottom: 1rem;
+ padding: 1rem;
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ }
+
+ .feedbackColumns {
+ flex-direction: column;
+ gap: 1rem;
+ }
+
+ .summaryCards {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 0.75rem;
+ }
+
+ .summaryCard {
+ padding: 0.75rem;
+ }
+
+ .cardNumber {
+ font-size: 1.5rem;
+ }
+
+ .cardLabel {
+ font-size: 0.75rem;
+ }
+}
+
+/* Mobile phones (480px and below) */
+@media (max-width: 480px) {
+ .evaluationResultsPage {
+ margin-left: 220px;
+ }
+
+ .headerSection {
+ padding: 1rem 0;
+ margin-bottom: 0.75rem;
+ }
+
+ .pageTitle {
+ font-size: 1.25rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .pageSubtitle {
+ font-size: 0.8rem;
+ }
+
+ .mainContent {
+ padding: 0 0.75rem;
+ }
+
+ .overallSection {
+ padding: 0.75rem;
+ }
+
+ .userWelcome {
+ flex-wrap: wrap;
+ font-size: 0.75rem;
+ padding: 0.35rem 0.75rem;
+ }
+
+ .performanceTable {
+ font-size: 0.65rem;
+ }
+
+ .performanceTable th,
+ .performanceTable td {
+ padding: 0.35rem;
+ }
+
+ .sectionTitle {
+ font-size: 1rem;
+ }
+
+ .feedbackColumns {
+ gap: 0.75rem;
+ }
+
+ .strengthsSection,
+ .improvementsSection {
+ padding: 0.75rem;
+ }
+
+ .feedbackList {
+ padding-left: 1rem;
+ }
+
+ .feedbackItem {
+ padding: 0.5rem 0;
+ font-size: 0.8rem;
+ }
+
+ .summaryCards {
+ grid-template-columns: 1fr;
+ gap: 0.5rem;
+ }
+
+ .summaryCard {
+ padding: 0.5rem;
+ }
+
+ .cardNumber {
+ font-size: 1.25rem;
+ }
+
+ .cardLabel {
+ font-size: 0.7rem;
+ }
+
+ .actionButtons {
+ flex-direction: column;
+ }
+
+ .actionButton {
+ width: 100%;
+ padding: 0.5rem;
+ font-size: 0.75rem;
+ }
+
+ .feedbackButton {
+ padding: 0.5rem 1rem;
+ font-size: 0.75rem;
+ }
+}
+
+/* Small phones (below 360px) */
+@media (max-width: 359px) {
+ .evaluationResultsPage {
+ margin-left: 200px;
+ }
+
+ .pageTitle {
+ font-size: 1rem;
+ }
+
+ .mainContent {
+ padding: 0 0.5rem;
+ }
+
+ .overallScore .scoreText {
+ font-size: 1.5rem;
+ }
+
+ .performanceTable {
+ font-size: 0.6rem;
+ }
+
+ .performanceTable th,
+ .performanceTable td {
+ padding: 0.25rem;
+ }
+}
\ No newline at end of file
diff --git a/src/components/EductionPortal/EvaluationResults/OverallPerformance.jsx b/src/components/EductionPortal/EvaluationResults/OverallPerformance.jsx
new file mode 100644
index 0000000000..c087e697d5
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/OverallPerformance.jsx
@@ -0,0 +1,293 @@
+import React from 'react';
+import { Card, CardBody, CardHeader, Progress, Badge, Row, Col } from 'reactstrap';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {
+ faChartLine,
+ faTrophy,
+ faBullseye,
+ faArrowTrendUp,
+ faUsers,
+ faCalendar,
+ faClock,
+ faCheckCircle,
+} from '@fortawesome/free-solid-svg-icons';
+import styles from './OverallPerformance.module.css';
+
+const OverallPerformance = ({ data, analytics, isLoading }) => {
+ if (isLoading) {
+ return (
+
+
+
+
+
Loading performance data...
+
+
+
+ );
+ }
+
+ if (!data || !analytics) {
+ return (
+
+
+
+
+
No performance data available yet.
+
+
+
+ );
+ }
+
+ const getPerformanceLevel = score => {
+ if (score >= 90) return { level: 'excellent', color: 'success', icon: faTrophy };
+ if (score >= 80) return { level: 'good', color: 'primary', icon: faBullseye };
+ if (score >= 70) return { level: 'fair', color: 'warning', icon: faArrowTrendUp };
+ return { level: 'poor', color: 'danger', icon: faBullseye };
+ };
+
+ const performanceLevel = getPerformanceLevel(data.overallScore);
+ const percentile = analytics.percentile;
+ const improvementTrend = data.summary?.improvementTrend || '+0%';
+ const isImproving = improvementTrend.startsWith('+');
+
+ return (
+
+
+
+
+
+
+
Overall Performance
+
Academic Progress Overview
+
+
+
+
+
+ {performanceLevel.level.toUpperCase()}
+
+
+
+
+
+
+ {/* Main Performance Score */}
+
+
+
+
{data.overallScore.toFixed(1)}
+
Overall Score
+
+
+
+ Class Rank
+
+ #{analytics.classRank} of {analytics.totalStudents}
+
+
+
+ Percentile
+ {percentile}th
+
+
+ GPA
+ {analytics.gpa}
+
+
+ Trend
+
+
+ {improvementTrend}
+
+
+
+
+
+
+ {/* Performance Metrics Grid */}
+
+
+
+
+
+ Completion Rate
+
+
+
+ {Math.round(
+ (data.summary.completedAssignments / data.summary.totalAssignments) * 100,
+ )}
+ %
+
+
+ {data.summary.completedAssignments} of {data.summary.totalAssignments} assignments
+
+
+
+
+
+
+
+
+
+
+ On-Time Rate
+
+
+
+ {Math.round(
+ (data.summary.onTimeSubmissions /
+ (data.summary.onTimeSubmissions +
+ data.summary.lateSubmissions +
+ data.summary.missingSubmissions)) *
+ 100,
+ )}
+ %
+
+
+ {data.summary.onTimeSubmissions} on-time submissions
+
+
+
+
+
+
+
+
+
+
+ Attendance
+
+
+
{analytics.attendanceRate}%
+
Class attendance rate
+
= 90
+ ? 'success'
+ : analytics.attendanceRate >= 80
+ ? 'warning'
+ : 'danger'
+ }
+ className={styles.metricProgress}
+ />
+
+
+
+
+
+
+
+
+ Participation
+
+
+
{analytics.participationScore}%
+
Class participation score
+
= 90
+ ? 'success'
+ : analytics.participationScore >= 80
+ ? 'primary'
+ : 'warning'
+ }
+ className={styles.metricProgress}
+ />
+
+
+
+
+
+ {/* Performance Summary */}
+
+
Performance Summary
+
+
+
+
Academic Achievements
+
+
+
+ Highest Score: {data.summary.highestScore}%
+
+
+
+ Average Score: {data.summary.averageScore}%
+
+
+
+
+ Time Management:{' '}
+ {data.summary.timeManagement?.excellent >
+ data.summary.timeManagement?.needsImprovement
+ ? 'Excellent'
+ : 'Needs Improvement'}
+
+
+
+
+
+
+
+
Key Insights
+
+ {data.summary.strengths?.slice(0, 3).map((strength, index) => (
+
+ ))}
+
+
+
+
+
+
+ {/* Last Updated */}
+
+
+
+ Last updated:{' '}
+ {new Date(data.student.lastUpdated).toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ })}
+
+
+
+
+ );
+};
+
+export default OverallPerformance;
diff --git a/src/components/EductionPortal/EvaluationResults/OverallPerformance.module.css b/src/components/EductionPortal/EvaluationResults/OverallPerformance.module.css
new file mode 100644
index 0000000000..f0533641ca
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/OverallPerformance.module.css
@@ -0,0 +1,533 @@
+/* ============================================================================
+ OVERALL PERFORMANCE COMPONENT STYLES - Premium Dashboard Design
+ ============================================================================ */
+
+.performanceCard {
+ border: none;
+ border-radius: var(--border-radius-lg);
+ box-shadow: var(--shadow-elegant);
+ background: linear-gradient(135deg, var(--gradient-start) 0%, var(--gradient-end) 100%);
+ overflow: hidden;
+ transition: all 0.3s ease;
+}
+
+.performanceCard:hover {
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-floating);
+}
+
+/* Header Styles */
+.performanceHeader {
+ background: var(--primary-gradient);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ padding: 1.5rem;
+}
+
+.headerContent {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 1rem;
+}
+
+.headerLeft {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.headerIcon {
+ font-size: 2.5rem;
+ color: var(--accent-light);
+ background: rgba(255, 255, 255, 0.1);
+ padding: 0.75rem;
+ border-radius: var(--border-radius-full);
+ backdrop-filter: blur(10px);
+}
+
+.headerTitle {
+ color: var(--text-light);
+ margin: 0;
+ font-size: 1.5rem;
+ font-weight: 600;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.headerSubtitle {
+ color: var(--accent-light);
+ margin: 0.25rem 0 0 0;
+ font-size: 0.9rem;
+ font-weight: 400;
+ opacity: 0.9;
+}
+
+.headerRight {
+ display: flex;
+ align-items: center;
+}
+
+.performanceBadge {
+ font-size: 0.85rem;
+ font-weight: 600;
+ padding: 0.6rem 1.2rem;
+ border-radius: var(--border-radius-full);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.badgeIcon {
+ font-size: 1rem;
+}
+
+/* Body Styles */
+.performanceBody {
+ padding: 2rem;
+ background: var(--surface-light);
+}
+
+/* Main Score Section */
+.mainScoreSection {
+ margin-bottom: 2.5rem;
+}
+
+.scoreDisplay {
+ display: flex;
+ align-items: center;
+ gap: 2rem;
+ padding: 2rem;
+ background: linear-gradient(135deg, #f8faff 0%, #e8f2ff 100%);
+ border: 1px solid rgba(59, 130, 246, 0.2);
+ border-radius: var(--border-radius-lg);
+ position: relative;
+ overflow: hidden;
+}
+
+.scoreDisplay::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100%;
+ width: 6px;
+ background: var(--primary-gradient);
+}
+
+.scoreCircle {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 120px;
+ height: 120px;
+ background: var(--primary-gradient);
+ border-radius: var(--border-radius-full);
+ color: white;
+ text-align: center;
+ box-shadow: 0 8px 25px rgba(59, 130, 246, 0.3);
+ flex-shrink: 0;
+}
+
+.scoreNumber {
+ font-size: 2rem;
+ font-weight: 700;
+ line-height: 1;
+ margin-bottom: 0.25rem;
+}
+
+.scoreLabel {
+ font-size: 0.8rem;
+ font-weight: 500;
+ opacity: 0.9;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.scoreDetails {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
+ gap: 1.5rem;
+ flex: 1;
+}
+
+.scoreMetric {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.metricLabel {
+ font-size: 0.85rem;
+ color: var(--text-muted);
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.metricValue {
+ font-size: 1.5rem;
+ font-weight: 600;
+ color: var(--text-primary);
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.trendPositive {
+ color: var(--success-color);
+}
+
+.trendNegative {
+ color: var(--error-color);
+}
+
+.trendIcon {
+ font-size: 1rem;
+}
+
+.trendUp {
+ transform: rotate(0deg);
+}
+
+.trendDown {
+ transform: rotate(180deg);
+}
+
+/* Metrics Grid */
+.metricsGrid {
+ margin: 0 -0.75rem;
+}
+
+.metricCol {
+ padding: 0 0.75rem;
+ margin-bottom: 1.5rem;
+}
+
+.metricCard {
+ background: white;
+ border: 1px solid var(--border-light);
+ border-radius: var(--border-radius-md);
+ padding: 1.5rem;
+ height: 100%;
+ transition: all 0.2s ease;
+ position: relative;
+ overflow: hidden;
+}
+
+.metricCard:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
+}
+
+.metricCard::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100%;
+ width: 3px;
+ background: var(--primary-color);
+ opacity: 0.7;
+}
+
+.metricHeader {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ margin-bottom: 1rem;
+}
+
+.metricIcon {
+ font-size: 1.25rem;
+ color: var(--primary-color);
+ background: rgba(59, 130, 246, 0.1);
+ padding: 0.5rem;
+ border-radius: var(--border-radius-sm);
+}
+
+.metricTitle {
+ font-size: 0.9rem;
+ font-weight: 600;
+ color: var(--text-secondary);
+ margin: 0;
+ text-transform: uppercase;
+ letter-spacing: 0.3px;
+}
+
+.metricContent {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.metricNumber {
+ font-size: 2rem;
+ font-weight: 700;
+ color: var(--text-primary);
+ line-height: 1;
+}
+
+.metricDescription {
+ font-size: 0.85rem;
+ color: var(--text-muted);
+ line-height: 1.4;
+}
+
+.metricProgress {
+ height: 8px;
+ border-radius: var(--border-radius-full);
+}
+
+/* Summary Section */
+.summarySection {
+ margin-top: 2.5rem;
+ padding-top: 2rem;
+ border-top: 2px solid var(--accent-light);
+}
+
+.summaryTitle {
+ font-size: 1.3rem;
+ font-weight: 600;
+ color: var(--text-primary);
+ margin-bottom: 1.5rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.summaryCard {
+ background: white;
+ border: 1px solid var(--border-light);
+ border-radius: var(--border-radius-md);
+ padding: 1.5rem;
+ height: 100%;
+}
+
+.summaryCardTitle {
+ font-size: 1rem;
+ font-weight: 600;
+ color: var(--text-primary);
+ margin-bottom: 1rem;
+ padding-bottom: 0.5rem;
+ border-bottom: 2px solid var(--accent-light);
+}
+
+.achievementsList,
+.insightsList {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.achievementItem,
+.insightItem {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ padding: 0.5rem;
+ border-radius: var(--border-radius-sm);
+ transition: all 0.2s ease;
+}
+
+.achievementItem:hover,
+.insightItem:hover {
+ background: var(--surface-light);
+}
+
+.achievementIcon {
+ color: var(--primary-color);
+ font-size: 1rem;
+ flex-shrink: 0;
+}
+
+.insightBullet {
+ width: 6px;
+ height: 6px;
+ background: var(--primary-color);
+ border-radius: var(--border-radius-full);
+ flex-shrink: 0;
+}
+
+.insightText {
+ font-size: 0.9rem;
+ color: var(--text-secondary);
+ line-height: 1.4;
+}
+
+/* Last Updated */
+.lastUpdated {
+ margin-top: 2rem;
+ padding-top: 1rem;
+ border-top: 1px solid var(--border-light);
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ color: var(--text-muted);
+ font-size: 0.85rem;
+}
+
+.updateIcon {
+ font-size: 0.9rem;
+}
+
+.updateText {
+ font-style: italic;
+}
+
+/* Loading States */
+.loadingContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 4rem;
+ gap: 1rem;
+}
+
+.loadingSpinner {
+ width: 50px;
+ height: 50px;
+ border: 4px solid var(--accent-light);
+ border-top: 4px solid var(--primary-color);
+ border-radius: var(--border-radius-full);
+ animation: spin 1s linear infinite;
+}
+
+.loadingText {
+ color: var(--text-muted);
+ font-size: 1rem;
+ text-align: center;
+ margin: 0;
+}
+
+/* No Data State */
+.noDataContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 4rem;
+ gap: 1rem;
+}
+
+.noDataIcon {
+ font-size: 4rem;
+ color: var(--accent-light);
+ opacity: 0.6;
+}
+
+.noDataText {
+ color: var(--text-muted);
+ font-size: 1.1rem;
+ text-align: center;
+ margin: 0;
+}
+
+/* Responsive Design */
+@media (max-width: 992px) {
+ .scoreDisplay {
+ flex-direction: column;
+ text-align: center;
+ gap: 1.5rem;
+ }
+
+ .scoreDetails {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .metricCol {
+ margin-bottom: 1rem;
+ }
+}
+
+@media (max-width: 768px) {
+ .performanceBody {
+ padding: 1.5rem;
+ }
+
+ .scoreDisplay {
+ padding: 1.5rem;
+ }
+
+ .scoreCircle {
+ width: 100px;
+ height: 100px;
+ }
+
+ .scoreNumber {
+ font-size: 1.75rem;
+ }
+
+ .scoreDetails {
+ grid-template-columns: 1fr;
+ gap: 1rem;
+ }
+
+ .metricNumber {
+ font-size: 1.75rem;
+ }
+
+ .metricCard {
+ padding: 1rem;
+ }
+}
+
+@media (max-width: 480px) {
+ .performanceHeader {
+ padding: 1rem;
+ }
+
+ .performanceBody {
+ padding: 1rem;
+ }
+
+ .headerContent {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ .scoreDisplay {
+ padding: 1rem;
+ }
+
+ .summarySection {
+ margin-top: 1.5rem;
+ padding-top: 1.5rem;
+ }
+}
+
+/* Animations */
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* Accessibility */
+@media (prefers-reduced-motion: reduce) {
+ .performanceCard,
+ .metricCard,
+ .achievementItem,
+ .insightItem {
+ transition: none;
+ }
+
+ .loadingSpinner {
+ animation: none;
+ }
+}
+
+/* High contrast mode support */
+@media (prefers-contrast: high) {
+ .performanceCard,
+ .metricCard,
+ .summaryCard {
+ border-width: 2px;
+ }
+
+ .scoreCircle {
+ border: 2px solid var(--text-primary);
+ }
+}
\ No newline at end of file
diff --git a/src/components/EductionPortal/EvaluationResults/SummaryStats.jsx b/src/components/EductionPortal/EvaluationResults/SummaryStats.jsx
new file mode 100644
index 0000000000..d376a0e275
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/SummaryStats.jsx
@@ -0,0 +1,381 @@
+import React from 'react';
+import { Card, CardBody, CardHeader, Progress, Badge, Row, Col } from 'reactstrap';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {
+ faChartBar,
+ faTrophy,
+ faCalendar,
+ faCheckCircle,
+ faClock,
+ faExclamationTriangle,
+ faArrowTrendUp,
+ faBullseye,
+ faUsers,
+ faPercentage,
+ faAward,
+ faLightbulb,
+} from '@fortawesome/free-solid-svg-icons';
+import styles from './SummaryStats.module.css';
+
+const SummaryStats = ({ summary, analytics, trends, isLoading }) => {
+ if (isLoading) {
+ return (
+
+
+
+
+
Loading summary statistics...
+
+
+
+ );
+ }
+
+ if (!summary || !analytics) {
+ return (
+
+
+
+
+
No summary data available yet.
+
+
+
+ );
+ }
+
+ const improvementTrend = summary.improvementTrend || '+0%';
+ const isImproving = improvementTrend.startsWith('+');
+
+ const completionRate = Math.round(
+ (summary.completedAssignments / summary.totalAssignments) * 100,
+ );
+ const onTimeRate = Math.round(
+ (summary.onTimeSubmissions /
+ (summary.onTimeSubmissions + summary.lateSubmissions + summary.missingSubmissions)) *
+ 100,
+ );
+
+ return (
+
+
+
+
+
+
Summary Statistics
+
Comprehensive performance overview
+
+
+
+
+
+ {/* Key Performance Indicators */}
+
+
Key Performance Indicators
+
+
+
+
+
+
+
+
{summary.averageScore}%
+
Average Score
+
+
+
+ {improvementTrend}
+
+
+
+
+
+
+
+
+
+
+
+
+
#{analytics.classRank}
+
Class Rank
+
+ {analytics.percentile}th percentile of {analytics.totalStudents}
+
+
+
+
+
+
+
+
+
+
+
+
{completionRate}%
+
Completion Rate
+
+ {summary.completedAssignments}/{summary.totalAssignments} completed
+
+
+
+
+
+
+
+
+
+
+
+
{onTimeRate}%
+
On-Time Rate
+
+ {summary.onTimeSubmissions} on-time submissions
+
+
+
+
+
+
+
+ {/* Performance Breakdown */}
+
+
Performance Breakdown
+
+
+
+
Submission Status
+
+
+
+
On Time
+
+
{summary.onTimeSubmissions}
+
+
+
+
+
Late
+
+
{summary.lateSubmissions}
+
+
+
+
+
Missing
+
+
{summary.missingSubmissions}
+
+
+
+
+
+
+
+
+
Score Distribution
+
+
+
+ Highest Score:
+ {summary.highestScore}%
+
+
+
+ Average Score:
+ {summary.averageScore}%
+
+
+
+ Lowest Score:
+ {summary.lowestScore}%
+
+
+
+
+
+
+
+ {/* Academic Insights */}
+
+
Academic Insights
+
+
+
+
+
+
Strengths
+
+ {summary.strengths?.length || 0}
+
+
+
+ {summary.strengths?.slice(0, 4).map((strength, index) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
Areas for Improvement
+
+ {summary.areasForImprovement?.length || 0}
+
+
+
+ {summary.areasForImprovement?.slice(0, 4).map((area, index) => (
+
+ ))}
+
+
+
+
+
+
+ {/* Performance Trends */}
+ {trends && (
+
+
Performance Trends
+
+
+ {trends.monthly?.map((month, index) => (
+
+
{month.month}
+
{month.score}%
+
Rank #{month.rank}
+ {index > 0 && (
+
+ trends.monthly[index - 1].score
+ ? styles.trendUp
+ : styles.trendDown
+ }`}
+ />
+ trends.monthly[index - 1].score
+ ? styles.trendPositive
+ : styles.trendNegative
+ }`}
+ >
+ {month.score > trends.monthly[index - 1].score ? '+' : ''}
+ {(month.score - trends.monthly[index - 1].score).toFixed(1)}%
+
+
+ )}
+
+ ))}
+
+
+
+ )}
+
+ {/* Additional Metrics */}
+
+
Additional Metrics
+
+
+
+
+
{analytics.attendanceRate}%
+
Attendance
+
+
+
+
+
+
{analytics.participationScore}%
+
Participation
+
+
+
+
+
+
{analytics.gpa}
+
Current GPA
+
+
+
+
+
+
{analytics.creditHours}
+
Credit Hours
+
+
+
+
+
+
+ );
+};
+
+export default SummaryStats;
diff --git a/src/components/EductionPortal/EvaluationResults/SummaryStats.module.css b/src/components/EductionPortal/EvaluationResults/SummaryStats.module.css
new file mode 100644
index 0000000000..81e848f85a
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/SummaryStats.module.css
@@ -0,0 +1,317 @@
+/* SummaryStats Component Styles */
+
+.summaryContainer {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 1.5rem;
+ margin-bottom: 2rem;
+}
+
+.statCard {
+ background: #ffffff;
+ border: none;
+ border-radius: 12px;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
+ overflow: hidden;
+ transition: all 0.3s ease;
+ position: relative;
+}
+
+.statCard:hover {
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
+ transform: translateY(-4px);
+}
+
+.statCard::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 4px;
+ background: var(--accent-color);
+}
+
+.statCard.totalAssignments::before {
+ --accent-color: linear-gradient(90deg, #3b82f6, #1d4ed8);
+}
+
+.statCard.onTime::before {
+ --accent-color: linear-gradient(90deg, #10b981, #059669);
+}
+
+.statCard.late::before {
+ --accent-color: linear-gradient(90deg, #f59e0b, #d97706);
+}
+
+.statCard.average::before {
+ --accent-color: linear-gradient(90deg, #8b5cf6, #7c3aed);
+}
+
+.statCardBody {
+ padding: 1.5rem;
+}
+
+.statHeader {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 1rem;
+}
+
+.statIcon {
+ width: 48px;
+ height: 48px;
+ border-radius: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1.25rem;
+ color: white;
+ background: var(--icon-bg);
+}
+
+.statCard.totalAssignments .statIcon {
+ --icon-bg: linear-gradient(135deg, #3b82f6, #1d4ed8);
+}
+
+.statCard.onTime .statIcon {
+ --icon-bg: linear-gradient(135deg, #10b981, #059669);
+}
+
+.statCard.late .statIcon {
+ --icon-bg: linear-gradient(135deg, #f59e0b, #d97706);
+}
+
+.statCard.average .statIcon {
+ --icon-bg: linear-gradient(135deg, #8b5cf6, #7c3aed);
+}
+
+.statTrend {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ font-size: 0.75rem;
+ font-weight: 600;
+ padding: 0.25rem 0.5rem;
+ border-radius: 12px;
+}
+
+.statTrend.positive {
+ color: #065f46;
+ background: #d1fae5;
+}
+
+.statTrend.negative {
+ color: #991b1b;
+ background: #fee2e2;
+}
+
+.statTrend.neutral {
+ color: #374151;
+ background: #f3f4f6;
+}
+
+.trendIcon {
+ font-size: 0.625rem;
+}
+
+.statContent {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.statValue {
+ font-size: 2.25rem;
+ font-weight: 800;
+ line-height: 1;
+ color: #1f2937;
+ margin: 0;
+}
+
+.statLabel {
+ font-size: 0.875rem;
+ font-weight: 600;
+ color: #6b7280;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ margin: 0;
+}
+
+.statDescription {
+ font-size: 0.8125rem;
+ color: #9ca3af;
+ line-height: 1.4;
+ margin: 0;
+}
+
+.statProgress {
+ margin-top: 1rem;
+}
+
+.progressLabel {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-size: 0.75rem;
+ color: #6b7280;
+ margin-bottom: 0.5rem;
+}
+
+.progressBar {
+ width: 100%;
+ height: 6px;
+ background: #f3f4f6;
+ border-radius: 3px;
+ overflow: hidden;
+}
+
+.progressFill {
+ height: 100%;
+ border-radius: 3px;
+ transition: width 0.8s ease;
+}
+
+.statCard.totalAssignments .progressFill {
+ background: linear-gradient(90deg, #3b82f6, #1d4ed8);
+}
+
+.statCard.onTime .progressFill {
+ background: linear-gradient(90deg, #10b981, #059669);
+}
+
+.statCard.late .progressFill {
+ background: linear-gradient(90deg, #f59e0b, #d97706);
+}
+
+.statCard.average .progressFill {
+ background: linear-gradient(90deg, #8b5cf6, #7c3aed);
+}
+
+.loadingContainer {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 3rem;
+ text-align: center;
+}
+
+.loadingSpinner {
+ width: 40px;
+ height: 40px;
+ border: 3px solid #e5e7eb;
+ border-top: 3px solid #3b82f6;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin-bottom: 1rem;
+}
+
+.loadingText {
+ color: #6b7280;
+ font-size: 0.875rem;
+ margin: 0;
+}
+
+.noDataContainer {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 3rem;
+ text-align: center;
+}
+
+.noDataIcon {
+ font-size: 3rem;
+ color: #d1d5db;
+ margin-bottom: 1rem;
+}
+
+.noDataText {
+ color: #6b7280;
+ font-size: 1rem;
+ margin: 0;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* Animation for counting effect */
+@keyframes countUp {
+ from {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.statValue {
+ animation: countUp 0.6s ease-out;
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .summaryContainer {
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 1rem;
+ }
+
+ .statCardBody {
+ padding: 1.25rem;
+ }
+
+ .statIcon {
+ width: 40px;
+ height: 40px;
+ font-size: 1rem;
+ }
+
+ .statValue {
+ font-size: 1.875rem;
+ }
+
+ .statLabel {
+ font-size: 0.8125rem;
+ }
+
+ .statDescription {
+ font-size: 0.75rem;
+ }
+}
+
+@media (max-width: 480px) {
+ .summaryContainer {
+ grid-template-columns: 1fr;
+ gap: 0.75rem;
+ }
+
+ .statCardBody {
+ padding: 1rem;
+ }
+
+ .statHeader {
+ margin-bottom: 0.75rem;
+ }
+
+ .statIcon {
+ width: 36px;
+ height: 36px;
+ font-size: 0.875rem;
+ }
+
+ .statValue {
+ font-size: 1.75rem;
+ }
+
+ .statTrend {
+ font-size: 0.6875rem;
+ padding: 0.2rem 0.4rem;
+ }
+}
\ No newline at end of file
diff --git a/src/components/EductionPortal/EvaluationResults/TaskDetailsList.jsx b/src/components/EductionPortal/EvaluationResults/TaskDetailsList.jsx
new file mode 100644
index 0000000000..43bc8f64c2
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/TaskDetailsList.jsx
@@ -0,0 +1,440 @@
+import React, { useState } from 'react';
+import { Card, CardBody, CardHeader, Badge, Collapse, Row, Col, Progress } from 'reactstrap';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {
+ faList,
+ faChevronDown,
+ faChevronUp,
+ faCheckCircle,
+ faClock,
+ faExclamationTriangle,
+ faFileAlt,
+ faCalendar,
+ faWeight,
+ faComments,
+ faDownload,
+ faEye,
+} from '@fortawesome/free-solid-svg-icons';
+import { getStatusInfo } from './mockData_new';
+import styles from './TaskDetailsList.module.css';
+
+const TaskDetailsList = ({ tasks, selectedCategory = 'all', categories, isLoading }) => {
+ const [expandedTasks, setExpandedTasks] = useState(new Set());
+ const [filterCategory, setFilterCategory] = useState(selectedCategory);
+ const [sortBy, setSortBy] = useState('dueDate');
+
+ // Update local filter when parent category changes
+ React.useEffect(() => {
+ setFilterCategory(selectedCategory);
+ }, [selectedCategory]);
+
+ if (isLoading) {
+ return (
+
+
+
+
+
Loading task details...
+
+
+
+ );
+ }
+
+ if (!tasks || tasks.length === 0) {
+ return (
+
+
+
+
+
No task details available yet.
+
+
+
+ );
+ }
+
+ const toggleTaskExpansion = taskId => {
+ const newExpanded = new Set(expandedTasks);
+ if (newExpanded.has(taskId)) {
+ newExpanded.delete(taskId);
+ } else {
+ newExpanded.add(taskId);
+ }
+ setExpandedTasks(newExpanded);
+ };
+
+ // Filter and sort tasks
+ const filteredTasks = tasks
+ .filter(task => {
+ if (filterCategory === 'all') return true;
+ // Handle both category name and category id formats
+ return task.category === filterCategory || task.category === filterCategory.toLowerCase();
+ })
+ .sort((a, b) => {
+ if (sortBy === 'dueDate') {
+ return new Date(a.dueDate) - new Date(b.dueDate);
+ }
+ if (sortBy === 'score') {
+ return b.percentage - a.percentage;
+ }
+ if (sortBy === 'name') {
+ return a.name.localeCompare(b.name);
+ }
+ return 0;
+ });
+
+ const getTaskTypeIcon = type => {
+ if (type?.toLowerCase().includes('exam')) return faFileAlt;
+ if (type?.toLowerCase().includes('quiz')) return faCheckCircle;
+ if (type?.toLowerCase().includes('project')) return faEye;
+ return faFileAlt;
+ };
+
+ const getCategoryColor = category => {
+ const colors = {
+ assignments: '#3b82f6',
+ quizzes: '#10b981',
+ exams: '#f59e0b',
+ projects: '#8b5cf6',
+ };
+ return colors[category] || '#6b7280';
+ };
+
+ // Create dropdown options from parent categories or fallback to task categories
+ const categoryOptions = categories
+ ? ['all', ...categories.map(cat => cat.name.toLowerCase())]
+ : ['all', ...new Set(tasks.map(task => task.category))];
+
+ return (
+
+
+
+
+
+
+
+ {filterCategory === 'all'
+ ? 'Task Details'
+ : `${filterCategory.charAt(0).toUpperCase() + filterCategory.slice(1)} Tasks`}
+
+
+ {filterCategory === 'all'
+ ? 'Detailed breakdown of all assignments and assessments'
+ : `Showing ${filteredTasks.length} ${filterCategory} task${
+ filteredTasks.length !== 1 ? 's' : ''
+ }`}
+
+
+
+
+
+ {filteredTasks.length} tasks
+
+ {filterCategory !== 'all' && (
+
+ Filtered
+
+ )}
+
+
+
+ {/* Filters and Controls */}
+
+
+
+
+ Category:
+
+ setFilterCategory(e.target.value)}
+ className={styles.filterSelect}
+ >
+ {categoryOptions.map(category => (
+
+ {category === 'all'
+ ? 'All Categories'
+ : category.charAt(0).toUpperCase() + category.slice(1)}
+
+ ))}
+
+
+
+
+ Sort by:
+
+ setSortBy(e.target.value)}
+ className={styles.filterSelect}
+ >
+ Due Date
+ Score
+ Name
+
+
+
+
+
+
+
+
+ {filteredTasks.map(task => {
+ const isExpanded = expandedTasks.has(task.id);
+ const statusInfo = getStatusInfo(task.status);
+ const categoryColor = getCategoryColor(task.category);
+ const isOverdue = new Date(task.dueDate) < new Date() && task.status === 'Missing';
+
+ return (
+
+ {/* Task Header */}
+
toggleTaskExpansion(task.id)}
+ role="button"
+ tabIndex={0}
+ onKeyDown={e => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ toggleTaskExpansion(task.id);
+ }
+ }}
+ >
+
+
+
+
+
+
{task.name}
+
+
+ {task.category}
+
+
+ {task.type}
+
+
+
+ {task.weightage}%
+
+
+
+
+
+
+
+
+ {task.percentage}%
+
+
+ {task.earnedMarks}/{task.totalMarks}
+
+
+
+
+
+ {statusInfo.label}
+
+
+
+
+ {new Date(task.dueDate).toLocaleDateString('en-US', {
+ month: 'short',
+ day: 'numeric',
+ })}
+
+
+
+
+
+
+
+
+
+ {/* Expandable Details */}
+
+
+ {/* Progress Bar */}
+
+
= 90
+ ? 'success'
+ : task.percentage >= 80
+ ? 'primary'
+ : task.percentage >= 70
+ ? 'warning'
+ : 'danger'
+ }
+ className={styles.taskProgress}
+ />
+
+ Score: {task.percentage}% ({task.earnedMarks}/{task.totalMarks} points)
+
+
+
+ {/* Submission Info */}
+
+
+
+
Submission Details
+
+ Submitted: {' '}
+ {task.submittedDate
+ ? new Date(task.submittedDate).toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ })
+ : 'Not submitted'}
+
+
+ Due Date: {' '}
+ {new Date(task.dueDate).toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ })}
+
+ {task.timeSpent && (
+
+ Time Spent: {task.timeSpent}
+
+ )}
+ {task.attempts && (
+
+ Attempts: {task.attempts}
+ {task.maxAttempts && ` / ${task.maxAttempts}`}
+
+ )}
+
+
+
+
+
+
Additional Info
+ {task.rubricScores && (
+
+
Rubric Breakdown:
+
+ {Object.entries(task.rubricScores).map(([criteria, score]) => (
+
+
{criteria}:
+
+ {score.earned}/{score.total}
+
+
+
+ ))}
+
+
+ )}
+
+ {task.sections && (
+
+
Exam Sections:
+
+ {Object.entries(task.sections).map(([section, score]) => (
+
+ {section}:
+
+ {score.earned}/{score.total}
+
+
+ ))}
+
+
+ )}
+
+ {task.technologies && (
+
+
Technologies:
+
+ {task.technologies.map(tech => (
+
+ {tech}
+
+ ))}
+
+
+ )}
+
+
+
+
+ {/* Teacher Feedback */}
+ {task.teacherFeedback && (
+
+
+
+ Teacher Feedback
+
+
+
{task.teacherFeedback}
+
+
+ )}
+
+ {/* Attachments */}
+ {task.attachments && task.attachments.length > 0 && (
+
+
+
+ Attachments
+
+
+ {task.attachments.map(attachment => (
+
+
+ {attachment}
+
+ ))}
+
+
+ )}
+
+
+
+ );
+ })}
+
+
+
+ );
+};
+
+export default TaskDetailsList;
diff --git a/src/components/EductionPortal/EvaluationResults/TaskDetailsList.module.css b/src/components/EductionPortal/EvaluationResults/TaskDetailsList.module.css
new file mode 100644
index 0000000000..7caa8af55f
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/TaskDetailsList.module.css
@@ -0,0 +1,617 @@
+/* TaskDetailsList Component Styles */
+
+.tasksCard {
+ background: #ffffff;
+ border: none;
+ border-radius: 12px;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
+ margin-bottom: 2rem;
+ overflow: hidden;
+ transition: all 0.3s ease;
+}
+
+.tasksCard:hover {
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
+ transform: translateY(-2px);
+}
+
+.tasksHeader {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ padding: 1.5rem;
+ border-bottom: none;
+}
+
+.headerContent {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 1rem;
+}
+
+.headerLeft {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.headerIcon {
+ font-size: 1.5rem;
+ color: rgba(255, 255, 255, 0.9);
+}
+
+.headerTitle {
+ margin: 0;
+ font-size: 1.5rem;
+ font-weight: 600;
+ color: white;
+}
+
+.headerSubtitle {
+ margin: 0.25rem 0 0 0;
+ font-size: 0.875rem;
+ color: rgba(255, 255, 255, 0.8);
+ font-weight: 400;
+}
+
+.headerRight {
+ display: flex;
+ align-items: center;
+}
+
+.countBadge {
+ background: rgba(255, 255, 255, 0.2);
+ color: white;
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ font-weight: 500;
+}
+
+.filterBadge {
+ background: rgba(255, 255, 255, 0.9);
+ color: #667eea;
+ border: 1px solid rgba(255, 255, 255, 0.5);
+ font-weight: 600;
+ font-size: 0.7rem;
+ margin-left: 0.5rem;
+ text-transform: uppercase;
+ letter-spacing: 0.025em;
+}
+
+.controlsSection {
+ padding-top: 1rem;
+ border-top: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+.filterControls {
+ display: flex;
+ gap: 1.5rem;
+ align-items: center;
+ flex-wrap: wrap;
+}
+
+.filterGroup {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.filterLabel {
+ font-size: 0.875rem;
+ font-weight: 500;
+ color: rgba(255, 255, 255, 0.9);
+ margin: 0;
+}
+
+.filterSelect {
+ background: rgba(255, 255, 255, 0.15);
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ border-radius: 6px;
+ color: white;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.875rem;
+ min-width: 140px;
+ transition: all 0.2s ease;
+}
+
+.filterSelect:focus {
+ background: rgba(255, 255, 255, 0.25);
+ border-color: rgba(255, 255, 255, 0.5);
+ outline: none;
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.2);
+}
+
+.filterSelect option {
+ background: #333;
+ color: white;
+}
+
+.tasksBody {
+ padding: 0;
+}
+
+.tasksList {
+ display: flex;
+ flex-direction: column;
+}
+
+.taskCard {
+ border-bottom: 1px solid #e9ecef;
+ transition: all 0.2s ease;
+}
+
+.taskCard:hover {
+ background: #f8f9fa;
+}
+
+.taskCard:last-child {
+ border-bottom: none;
+}
+
+.taskCard.overdue {
+ border-left: 4px solid #dc3545;
+ background: #fff5f5;
+}
+
+.taskHeader {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 1.25rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.taskHeader:hover {
+ background: rgba(102, 126, 234, 0.05);
+}
+
+.taskInfo {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ flex: 1;
+}
+
+.taskIcon {
+ width: 40px;
+ height: 40px;
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: #f8f9fa;
+ font-size: 1.1rem;
+}
+
+.taskMain {
+ flex: 1;
+}
+
+.taskName {
+ margin: 0 0 0.5rem 0;
+ font-size: 1.1rem;
+ font-weight: 600;
+ color: #2d3748;
+ line-height: 1.3;
+}
+
+.taskMeta {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ flex-wrap: wrap;
+}
+
+.categoryBadge {
+ font-size: 0.75rem;
+ font-weight: 500;
+ padding: 0.25rem 0.5rem;
+ border-radius: 4px;
+ background: transparent;
+ border: 1px solid;
+}
+
+.typeBadge {
+ font-size: 0.75rem;
+ font-weight: 500;
+ padding: 0.25rem 0.5rem;
+ border-radius: 4px;
+}
+
+.weightInfo {
+ font-size: 0.75rem;
+ color: #6b7280;
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.weightIcon {
+ font-size: 0.7rem;
+}
+
+.taskSummary {
+ display: flex;
+ align-items: center;
+ gap: 1.5rem;
+}
+
+.scoreDisplay {
+ text-align: center;
+ min-width: 80px;
+}
+
+.scoreNumber {
+ font-size: 1.5rem;
+ font-weight: 700;
+ line-height: 1;
+ margin-bottom: 0.25rem;
+}
+
+.scoreBreakdown {
+ font-size: 0.75rem;
+ color: #6b7280;
+ font-weight: 500;
+}
+
+.statusSection {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.5rem;
+ min-width: 100px;
+}
+
+.statusBadge {
+ font-size: 0.75rem;
+ font-weight: 500;
+ padding: 0.25rem 0.5rem;
+ border-radius: 4px;
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.statusIcon {
+ font-size: 0.7rem;
+}
+
+.dueDateInfo {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ font-size: 0.75rem;
+ color: #6b7280;
+}
+
+.dueDateIcon {
+ font-size: 0.7rem;
+}
+
+.dueDateText {
+ font-weight: 500;
+}
+
+.expandToggle {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ background: #f3f4f6;
+ color: #6b7280;
+ transition: all 0.2s ease;
+}
+
+.expandToggle:hover {
+ background: #e5e7eb;
+ color: #374151;
+}
+
+.expandIcon {
+ font-size: 0.875rem;
+}
+
+.taskDetails {
+ padding: 1.5rem;
+ background: #f8f9fa;
+ border-top: 1px solid #e9ecef;
+}
+
+.progressSection {
+ margin-bottom: 1.5rem;
+}
+
+.taskProgress {
+ margin-bottom: 0.5rem;
+}
+
+.progressLabel {
+ font-size: 0.875rem;
+ color: #6b7280;
+ font-weight: 500;
+ text-align: center;
+}
+
+.detailsRow {
+ margin-bottom: 1.5rem;
+}
+
+.detailSection {
+ background: white;
+ border-radius: 8px;
+ padding: 1rem;
+ height: 100%;
+}
+
+.detailTitle {
+ font-size: 0.875rem;
+ font-weight: 600;
+ color: #374151;
+ margin-bottom: 0.75rem;
+ padding-bottom: 0.5rem;
+ border-bottom: 1px solid #e5e7eb;
+}
+
+.detailItem {
+ margin-bottom: 0.5rem;
+ font-size: 0.875rem;
+ line-height: 1.4;
+}
+
+.detailItem strong {
+ color: #374151;
+ font-weight: 600;
+}
+
+.rubricSection {
+ margin-top: 0.75rem;
+}
+
+.rubricScores {
+ margin-top: 0.5rem;
+}
+
+.rubricItem {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ margin-bottom: 0.5rem;
+}
+
+.rubricCriteria {
+ font-size: 0.75rem;
+ color: #6b7280;
+ min-width: 80px;
+ font-weight: 500;
+}
+
+.rubricScore {
+ font-size: 0.75rem;
+ font-weight: 600;
+ color: #374151;
+ min-width: 40px;
+}
+
+.rubricProgress {
+ flex: 1;
+ height: 4px;
+}
+
+.sectionsInfo {
+ margin-top: 0.75rem;
+}
+
+.sectionScores {
+ margin-top: 0.5rem;
+}
+
+.sectionItem {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.25rem 0;
+ font-size: 0.75rem;
+}
+
+.sectionName {
+ color: #6b7280;
+ font-weight: 500;
+}
+
+.sectionScore {
+ font-weight: 600;
+ color: #374151;
+}
+
+.technologiesInfo {
+ margin-top: 0.75rem;
+}
+
+.techTags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.25rem;
+ margin-top: 0.5rem;
+}
+
+.techTag {
+ font-size: 0.7rem;
+ padding: 0.125rem 0.375rem;
+ border-radius: 3px;
+}
+
+.feedbackSection {
+ background: white;
+ border-radius: 8px;
+ padding: 1rem;
+ margin-bottom: 1rem;
+ border-left: 4px solid #3b82f6;
+}
+
+.feedbackIcon {
+ margin-right: 0.5rem;
+ color: #3b82f6;
+}
+
+.feedbackContent {
+ margin-top: 0.5rem;
+}
+
+.feedbackText {
+ font-size: 0.875rem;
+ line-height: 1.5;
+ color: #4b5563;
+ margin: 0;
+}
+
+.attachmentsSection {
+ background: white;
+ border-radius: 8px;
+ padding: 1rem;
+ border-left: 4px solid #10b981;
+}
+
+.attachmentIcon {
+ margin-right: 0.5rem;
+ color: #10b981;
+}
+
+.attachmentsList {
+ margin-top: 0.5rem;
+}
+
+.attachmentItem {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.25rem 0;
+ font-size: 0.875rem;
+}
+
+.fileIcon {
+ color: #6b7280;
+ font-size: 0.75rem;
+}
+
+.fileName {
+ color: #374151;
+ font-weight: 500;
+}
+
+.loadingContainer {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 3rem;
+ text-align: center;
+}
+
+.loadingSpinner {
+ width: 40px;
+ height: 40px;
+ border: 3px solid #e5e7eb;
+ border-top: 3px solid #667eea;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin-bottom: 1rem;
+}
+
+.loadingText {
+ color: #6b7280;
+ font-size: 0.875rem;
+ margin: 0;
+}
+
+.noDataContainer {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 3rem;
+ text-align: center;
+}
+
+.noDataIcon {
+ font-size: 3rem;
+ color: #d1d5db;
+ margin-bottom: 1rem;
+}
+
+.noDataText {
+ color: #6b7280;
+ font-size: 1rem;
+ margin: 0;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .tasksHeader {
+ padding: 1rem;
+ }
+
+ .headerContent {
+ flex-direction: column;
+ gap: 1rem;
+ align-items: flex-start;
+ }
+
+ .filterControls {
+ flex-direction: column;
+ gap: 0.75rem;
+ align-items: stretch;
+ }
+
+ .taskHeader {
+ flex-direction: column;
+ gap: 1rem;
+ align-items: stretch;
+ }
+
+ .taskInfo {
+ gap: 0.75rem;
+ }
+
+ .taskSummary {
+ justify-content: space-between;
+ gap: 1rem;
+ }
+
+ .taskDetails {
+ padding: 1rem;
+ }
+
+ .rubricItem {
+ flex-direction: column;
+ align-items: stretch;
+ gap: 0.25rem;
+ }
+
+ .rubricCriteria {
+ min-width: auto;
+ }
+}
+
+@media (max-width: 480px) {
+ .taskMeta {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 0.5rem;
+ }
+
+ .scoreDisplay {
+ min-width: auto;
+ }
+
+ .statusSection {
+ min-width: auto;
+ align-items: flex-start;
+ }
+}
\ No newline at end of file
diff --git a/src/components/EductionPortal/EvaluationResults/TeacherFeedback.jsx b/src/components/EductionPortal/EvaluationResults/TeacherFeedback.jsx
new file mode 100644
index 0000000000..56f4950cbe
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/TeacherFeedback.jsx
@@ -0,0 +1,155 @@
+import React from 'react';
+import { Card, CardBody, CardHeader, Badge } from 'reactstrap';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faUser, faCalendar, faStar, faComments } from '@fortawesome/free-solid-svg-icons';
+import styles from './TeacherFeedback.module.css';
+
+const TeacherFeedback = ({ feedback, isLoading }) => {
+ if (isLoading) {
+ return (
+
+
+
+
+
Loading teacher feedback...
+
+
+
+ );
+ }
+
+ if (!feedback) {
+ return (
+
+
+
+
+
No teacher feedback available yet.
+
+
+
+ );
+ }
+
+ const getRatingStars = rating => {
+ const stars = [];
+ const fullStars = Math.floor(rating / 20); // Convert 100-point scale to 5-star
+ const hasHalfStar = rating % 20 >= 10;
+
+ for (let i = 0; i < 5; i++) {
+ if (i < fullStars) {
+ stars.push( );
+ } else if (i === fullStars && hasHalfStar) {
+ stars.push( );
+ } else {
+ stars.push( );
+ }
+ }
+ return stars;
+ };
+
+ return (
+
+
+
+
+
+
+
{feedback.teacherName}
+
{feedback.teacherTitle}
+
+
+
+
+
+ {getRatingStars(feedback.overallRating === 'Excellent' ? 95 : 85)}
+
+
+ {feedback.overallRating}
+
+
+
+
+
+ {new Date(feedback.lastUpdated).toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ })}
+
+
+
+
+
+
+
+ {/* Overall Feedback */}
+
+
+ {/* Strengths */}
+
+
+ Strengths
+
+ {feedback.strengths?.length || 0}
+
+
+
+ {feedback.strengths?.map((strength, index) => (
+
+ ))}
+
+
+
+ {/* Recommendations */}
+
+
+ Areas for Improvement
+
+ {feedback.recommendations?.length || 0}
+
+
+
+ {feedback.recommendations?.map((recommendation, index) => (
+
+ ))}
+
+
+
+ {/* Next Steps */}
+
+
+ Suggested Next Steps
+
+ {feedback.nextSteps?.length || 0}
+
+
+
+ {feedback.nextSteps?.map((step, index) => (
+
+ ))}
+
+
+
+
+ );
+};
+
+export default TeacherFeedback;
diff --git a/src/components/EductionPortal/EvaluationResults/TeacherFeedback.module.css b/src/components/EductionPortal/EvaluationResults/TeacherFeedback.module.css
new file mode 100644
index 0000000000..3461176ece
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/TeacherFeedback.module.css
@@ -0,0 +1,458 @@
+/* ============================================================================
+ TEACHER FEEDBACK COMPONENT STYLES - Premium UI Design
+ ============================================================================ */
+
+.feedbackCard {
+ border: none;
+ border-radius: var(--border-radius-lg);
+ box-shadow: var(--shadow-elegant);
+ background: linear-gradient(135deg, var(--gradient-start) 0%, var(--gradient-end) 100%);
+ overflow: hidden;
+ transition: all 0.3s ease;
+}
+
+.feedbackCard:hover {
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-floating);
+}
+
+/* Header Styles */
+.feedbackHeader {
+ background: var(--primary-gradient);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ padding: 1.5rem;
+}
+
+.headerContent {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 1rem;
+}
+
+.headerLeft {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.teacherIcon {
+ font-size: 2.5rem;
+ color: var(--accent-light);
+ background: rgba(255, 255, 255, 0.1);
+ padding: 0.75rem;
+ border-radius: var(--border-radius-full);
+ backdrop-filter: blur(10px);
+}
+
+.teacherInfo h4.teacherName {
+ color: var(--text-light);
+ margin: 0;
+ font-size: 1.4rem;
+ font-weight: 600;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.teacherInfo p.teacherTitle {
+ color: var(--accent-light);
+ margin: 0.25rem 0 0 0;
+ font-size: 0.9rem;
+ font-weight: 400;
+ opacity: 0.9;
+}
+
+.headerRight {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ gap: 0.5rem;
+}
+
+.ratingContainer {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+}
+
+.stars {
+ display: flex;
+ gap: 0.25rem;
+}
+
+.stars .starFilled {
+ color: #fbbf24;
+ font-size: 1.1rem;
+ filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.2));
+}
+
+.stars .starHalf {
+ color: #fbbf24;
+ font-size: 1.1rem;
+ opacity: 0.7;
+ filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.2));
+}
+
+.stars .starEmpty {
+ color: rgba(255, 255, 255, 0.3);
+ font-size: 1.1rem;
+}
+
+.ratingBadge {
+ font-size: 0.8rem;
+ font-weight: 600;
+ padding: 0.4rem 0.8rem;
+ border-radius: var(--border-radius-full);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.dateContainer {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ color: var(--accent-light);
+ font-size: 0.85rem;
+ opacity: 0.9;
+}
+
+.dateIcon {
+ font-size: 0.9rem;
+}
+
+/* Body Styles */
+.feedbackBody {
+ padding: 2rem;
+ background: var(--surface-light);
+}
+
+.feedbackSection {
+ margin-bottom: 2rem;
+}
+
+.feedbackSection:last-child {
+ margin-bottom: 0;
+}
+
+.sectionTitle {
+ font-size: 1.2rem;
+ font-weight: 600;
+ color: var(--text-primary);
+ margin-bottom: 1rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ border-bottom: 2px solid var(--accent-light);
+ padding-bottom: 0.5rem;
+}
+
+.countBadge {
+ font-size: 0.7rem;
+ padding: 0.25rem 0.5rem;
+ border-radius: var(--border-radius-full);
+ font-weight: 600;
+}
+
+.overallFeedback {
+ background: linear-gradient(135deg, #f8faff 0%, #e8f2ff 100%);
+ border: 1px solid rgba(59, 130, 246, 0.2);
+ border-radius: var(--border-radius-md);
+ padding: 1.5rem;
+ position: relative;
+ overflow: hidden;
+}
+
+.overallFeedback::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100%;
+ width: 4px;
+ background: var(--primary-gradient);
+}
+
+.feedbackText {
+ color: var(--text-secondary);
+ line-height: 1.7;
+ margin: 0;
+ font-size: 1rem;
+ font-style: italic;
+}
+
+/* Strengths Styles */
+.strengthsTitle {
+ color: var(--success-color);
+ font-weight: 600;
+}
+
+.strengthsList {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.strengthItem {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ padding: 0.75rem;
+ background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
+ border: 1px solid rgba(34, 197, 94, 0.2);
+ border-radius: var(--border-radius-md);
+ transition: all 0.2s ease;
+}
+
+.strengthItem:hover {
+ transform: translateX(4px);
+ box-shadow: 0 2px 8px rgba(34, 197, 94, 0.15);
+}
+
+.strengthBullet {
+ width: 8px;
+ height: 8px;
+ background: var(--success-color);
+ border-radius: var(--border-radius-full);
+ margin-top: 0.5rem;
+ flex-shrink: 0;
+}
+
+.strengthText {
+ color: var(--text-secondary);
+ line-height: 1.6;
+ font-size: 0.95rem;
+}
+
+/* Recommendations Styles */
+.recommendationsTitle {
+ color: var(--warning-color);
+ font-weight: 600;
+}
+
+.recommendationsList {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.recommendationItem {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ padding: 0.75rem;
+ background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);
+ border: 1px solid rgba(245, 158, 11, 0.2);
+ border-radius: var(--border-radius-md);
+ transition: all 0.2s ease;
+}
+
+.recommendationItem:hover {
+ transform: translateX(4px);
+ box-shadow: 0 2px 8px rgba(245, 158, 11, 0.15);
+}
+
+.recommendationBullet {
+ width: 8px;
+ height: 8px;
+ background: var(--warning-color);
+ border-radius: var(--border-radius-full);
+ margin-top: 0.5rem;
+ flex-shrink: 0;
+}
+
+.recommendationText {
+ color: var(--text-secondary);
+ line-height: 1.6;
+ font-size: 0.95rem;
+}
+
+/* Next Steps Styles */
+.nextStepsTitle {
+ color: var(--info-color);
+ font-weight: 600;
+}
+
+.nextStepsList {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.nextStepItem {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ padding: 0.75rem;
+ background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
+ border: 1px solid rgba(59, 130, 246, 0.2);
+ border-radius: var(--border-radius-md);
+ transition: all 0.2s ease;
+}
+
+.nextStepItem:hover {
+ transform: translateX(4px);
+ box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);
+}
+
+.nextStepNumber {
+ background: var(--info-color);
+ color: white;
+ width: 24px;
+ height: 24px;
+ border-radius: var(--border-radius-full);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.8rem;
+ font-weight: 600;
+ flex-shrink: 0;
+ margin-top: 0.1rem;
+}
+
+.nextStepText {
+ color: var(--text-secondary);
+ line-height: 1.6;
+ font-size: 0.95rem;
+}
+
+/* Loading States */
+.loadingContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 3rem;
+ gap: 1rem;
+}
+
+.loadingSpinner {
+ width: 40px;
+ height: 40px;
+ border: 3px solid var(--accent-light);
+ border-top: 3px solid var(--primary-color);
+ border-radius: var(--border-radius-full);
+ animation: spin 1s linear infinite;
+}
+
+.loadingText {
+ color: var(--text-muted);
+ font-size: 0.9rem;
+ text-align: center;
+ margin: 0;
+}
+
+/* No Feedback State */
+.noFeedbackContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 3rem;
+ gap: 1rem;
+}
+
+.noFeedbackIcon {
+ font-size: 3rem;
+ color: var(--accent-light);
+ opacity: 0.6;
+}
+
+.noFeedbackText {
+ color: var(--text-muted);
+ font-size: 1rem;
+ text-align: center;
+ margin: 0;
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .headerContent {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ }
+
+ .headerRight {
+ align-self: stretch;
+ align-items: flex-start;
+ }
+
+ .ratingContainer {
+ justify-content: space-between;
+ width: 100%;
+ }
+
+ .feedbackBody {
+ padding: 1.5rem;
+ }
+
+ .strengthItem,
+ .recommendationItem,
+ .nextStepItem {
+ padding: 1rem;
+ }
+
+ .teacherIcon {
+ font-size: 2rem;
+ padding: 0.6rem;
+ }
+
+ .teacherInfo h4.teacherName {
+ font-size: 1.2rem;
+ }
+
+ .teacherInfo p.teacherTitle {
+ font-size: 0.85rem;
+ }
+}
+
+@media (max-width: 480px) {
+ .feedbackHeader {
+ padding: 1rem;
+ }
+
+ .feedbackBody {
+ padding: 1rem;
+ }
+
+ .sectionTitle {
+ font-size: 1.1rem;
+ }
+
+ .overallFeedback {
+ padding: 1rem;
+ }
+}
+
+/* Animations */
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* Accessibility */
+@media (prefers-reduced-motion: reduce) {
+ .feedbackCard,
+ .strengthItem,
+ .recommendationItem,
+ .nextStepItem {
+ transition: none;
+ }
+
+ .loadingSpinner {
+ animation: none;
+ }
+}
+
+/* High contrast mode support */
+@media (prefers-contrast: high) {
+ .feedbackCard {
+ border: 2px solid var(--text-primary);
+ }
+
+ .strengthItem,
+ .recommendationItem,
+ .nextStepItem {
+ border-width: 2px;
+ }
+}
\ No newline at end of file
diff --git a/src/components/EductionPortal/EvaluationResults/evaluationApiService.js b/src/components/EductionPortal/EvaluationResults/evaluationApiService.js
new file mode 100644
index 0000000000..acc05232fa
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/evaluationApiService.js
@@ -0,0 +1,87 @@
+import httpService from '../../../services/httpService';
+import { ENDPOINTS } from '../../../utils/URL';
+
+/**
+ * API service for evaluation results
+ * Handles all backend communication for student evaluation data
+ */
+class EvaluationApiService {
+ /**
+ * Fetch evaluation results for the current student
+ */
+ static async getEvaluationResults() {
+ try {
+ const response = await httpService.get(
+ `${ENDPOINTS.APIEndpoint()}/student/evaluation-results`,
+ );
+ return response.data;
+ } catch (error) {
+ if (error.response?.status === 404) {
+ throw new Error('No evaluation results found');
+ }
+ if (error.response?.status === 403) {
+ throw new Error('Access denied to evaluation results');
+ }
+ throw new Error('Failed to fetch evaluation results');
+ }
+ }
+
+ /**
+ * Check for new evaluation notifications
+ */
+ static async checkNewNotifications(lastChecked = null) {
+ try {
+ const queryParams = lastChecked ? `?since=${lastChecked}` : '';
+ const response = await httpService.get(
+ `${ENDPOINTS.APIEndpoint()}/student/evaluation-results/notifications${queryParams}`,
+ );
+ return response.data;
+ } catch (error) {
+ throw new Error('Failed to check for new notifications');
+ }
+ }
+
+ /**
+ * Mark evaluation results as viewed
+ */
+ static async markAsViewed(evaluationId) {
+ try {
+ const response = await httpService.post(
+ `${ENDPOINTS.APIEndpoint()}/student/evaluation-results/${evaluationId}/mark-viewed`,
+ );
+ return response.data;
+ } catch (error) {
+ throw new Error('Failed to mark results as viewed');
+ }
+ }
+
+ /**
+ * Get evaluation details by category
+ */
+ static async getEvaluationByCategory(category) {
+ try {
+ const response = await httpService.get(
+ `${ENDPOINTS.APIEndpoint()}/student/evaluation-results?category=${category}`,
+ );
+ return response.data;
+ } catch (error) {
+ throw new Error(`Failed to fetch ${category} evaluation data`);
+ }
+ }
+
+ /**
+ * Get detailed task information
+ */
+ static async getTaskDetails(taskId) {
+ try {
+ const response = await httpService.get(
+ `${ENDPOINTS.APIEndpoint()}/student/evaluation-results/tasks/${taskId}`,
+ );
+ return response.data;
+ } catch (error) {
+ throw new Error('Failed to fetch task details');
+ }
+ }
+}
+
+export default EvaluationApiService;
diff --git a/src/components/EductionPortal/EvaluationResults/evaluationNotificationService.js b/src/components/EductionPortal/EvaluationResults/evaluationNotificationService.js
new file mode 100644
index 0000000000..45daa067a7
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/evaluationNotificationService.js
@@ -0,0 +1,193 @@
+import { toast } from 'react-toastify';
+import httpService from '../../../services/httpService';
+import { ENDPOINTS } from '../../../utils/URL';
+
+/**
+ * Service for handling evaluation results notifications
+ */
+class EvaluationNotificationService {
+ /**
+ * Trigger notification when new evaluation results are published
+ */
+ static triggerNewResultsNotification(studentId, evaluationData) {
+ try {
+ // Show immediate toast notification
+ toast.success(
+ `🎓 New evaluation results available! Overall score: ${evaluationData.student.overallScore}%`,
+ {
+ position: 'top-right',
+ autoClose: 8000,
+ hideProgressBar: false,
+ closeOnClick: true,
+ pauseOnHover: true,
+ draggable: true,
+ },
+ );
+
+ // Send system notification to student
+ this.createSystemNotification(studentId, {
+ type: 'evaluation_results',
+ title: 'New Evaluation Results Available',
+ message: `Your evaluation results have been published. Overall score: ${evaluationData.student.overallScore}%. View detailed feedback and task breakdown.`,
+ data: {
+ evaluationId: evaluationData.student.id,
+ overallScore: evaluationData.student.overallScore,
+ publishedDate: new Date().toISOString(),
+ },
+ priority: 'medium',
+ actionUrl: 'http://localhost:5173/educationportal/evaluation-results',
+ });
+
+ return true;
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error('Error triggering evaluation notification:', error);
+ return false;
+ }
+ }
+
+ /**
+ * Create system notification for student
+ */
+ static async createSystemNotification(studentId, notificationData) {
+ try {
+ const notification = {
+ recipient: studentId,
+ message: `
+
${notificationData.title}
+
${notificationData.message}
+
Published: ${new Date(
+ notificationData.data.publishedDate,
+ ).toLocaleDateString('en-US', {
+ month: 'short',
+ day: 'numeric',
+ year: 'numeric',
+ })}
+
View Results
+
`,
+ isSystemGenerated: true,
+ type: notificationData.type,
+ priority: notificationData.priority,
+ data: notificationData.data,
+ };
+
+ // Send to notification service
+ const response = await httpService.post(
+ `${ENDPOINTS.APIEndpoint()}/notification/`,
+ notification,
+ );
+
+ if (response.status === 201) {
+ // eslint-disable-next-line no-console
+ console.log('Evaluation notification created successfully');
+ return response.data;
+ }
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error('Error creating system notification:', error);
+ // Fallback to toast if system notification fails
+ toast.info('📚 Check your notifications for new evaluation results!');
+ }
+ }
+
+ /**
+ * Check for new evaluation results and notify if found
+ */
+ static async checkForNewResults(studentId, lastChecked = null) {
+ try {
+ const queryParams = lastChecked ? `?since=${lastChecked}` : '';
+ const response = await httpService.get(
+ `${ENDPOINTS.APIEndpoint()}/student/evaluation-results/notifications${queryParams}`,
+ );
+
+ if (response.data?.hasNewResults) {
+ this.triggerNewResultsNotification(studentId, response.data.evaluationData);
+ return true;
+ }
+
+ return false;
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error('Error checking for new evaluation results:', error);
+ return false;
+ }
+ }
+
+ /**
+ * Mark evaluation notification as viewed
+ */
+ static async markResultsAsViewed(studentId, evaluationId) {
+ try {
+ await httpService.post(
+ `${ENDPOINTS.APIEndpoint()}/student/evaluation-results/${evaluationId}/mark-viewed`,
+ { studentId },
+ );
+ return true;
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error('Error marking results as viewed:', error);
+ return false;
+ }
+ }
+
+ /**
+ * Show specific notification for performance level
+ */
+ static showPerformanceNotification(score, studentName = 'Student') {
+ let message = '';
+ let type = 'info';
+
+ if (score >= 90) {
+ message = `🏆 Excellent work, ${studentName}! You scored ${score}%`;
+ type = 'success';
+ } else if (score >= 80) {
+ message = `👏 Great job, ${studentName}! You scored ${score}%`;
+ type = 'success';
+ } else if (score >= 70) {
+ message = `📈 Good progress, ${studentName}. You scored ${score}%`;
+ type = 'info';
+ } else {
+ message = `💪 Keep working hard, ${studentName}. You scored ${score}%`;
+ type = 'warning';
+ }
+
+ toast[type](message, {
+ position: 'top-right',
+ autoClose: 6000,
+ hideProgressBar: false,
+ closeOnClick: true,
+ pauseOnHover: true,
+ });
+ }
+
+ /**
+ * Batch notification for multiple students (educator use)
+ */
+ static async notifyMultipleStudents(studentIds, evaluationData) {
+ try {
+ const notifications = studentIds.map(studentId => ({
+ studentId,
+ evaluationData,
+ }));
+
+ const response = await httpService.post(
+ `${ENDPOINTS.APIEndpoint()}/evaluation-results/batch-notify`,
+ { notifications },
+ );
+
+ if (response.status === 200) {
+ toast.success(`Notifications sent to ${studentIds.length} students successfully!`);
+ return true;
+ }
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error('Error sending batch notifications:', error);
+ toast.error('Failed to send notifications to some students');
+ return false;
+ }
+ }
+}
+
+export default EvaluationNotificationService;
diff --git a/src/components/EductionPortal/EvaluationResults/mockData_new.js b/src/components/EductionPortal/EvaluationResults/mockData_new.js
new file mode 100644
index 0000000000..cc21d6d3fd
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResults/mockData_new.js
@@ -0,0 +1,252 @@
+// ============================================================================
+// MOCK EVALUATION DATA - Clean Academic Performance Data for New Design
+// ============================================================================
+
+export const mockEvaluationData = {
+ student: {
+ id: 'STU-2024-001',
+ name: 'Alex Johnson',
+ email: 'alex.johnson@school.edu',
+ class: 'Computer Science - Year 3',
+ semester: 'Fall 2024',
+ lastUpdated: '2024-09-25T10:30:00Z',
+ profileImage: '/api/placeholder/60/60',
+ },
+
+ // Overall performance score (calculated from all categories)
+ overallScore: 77.0,
+
+ // Performance categories with detailed breakdown
+ categories: [
+ {
+ id: 'assignments',
+ name: 'Assignments',
+ weightage: 40,
+ totalItems: 5,
+ completedItems: 5,
+ totalMarks: 40,
+ earnedMarks: 32,
+ percentage: 80.0,
+ performanceLevel: 'good',
+ color: '#28a745',
+ icon: 'faClipboardCheck',
+ description: 'Programming assignments, essays, and individual homework tasks',
+ dueDate: '2024-10-14T12:00:00',
+ submissions: {
+ onTime: 4,
+ late: 1,
+ missing: 0,
+ },
+ },
+ {
+ id: 'exams',
+ name: 'Exams',
+ weightage: 35,
+ totalItems: 2,
+ completedItems: 2,
+ totalMarks: 40,
+ earnedMarks: 32,
+ percentage: 80.0,
+ performanceLevel: 'good',
+ color: '#28a745',
+ icon: 'faGraduationCap',
+ description: 'Comprehensive midterm and final examinations',
+ dueDate: '2024-12-09T12:00:00',
+ submissions: {
+ onTime: 2,
+ late: 0,
+ missing: 0,
+ },
+ },
+ {
+ id: 'quizzes',
+ name: 'Quizzes',
+ weightage: 15,
+ totalItems: 8,
+ completedItems: 8,
+ totalMarks: 40,
+ earnedMarks: 24,
+ percentage: 60.0,
+ performanceLevel: 'fair',
+ color: '#ffc107',
+ icon: 'faQuestion',
+ description: 'Short weekly quizzes and knowledge check assessments',
+ dueDate: '2024-09-29T12:00:00',
+ submissions: {
+ onTime: 6,
+ late: 2,
+ missing: 0,
+ },
+ },
+ {
+ id: 'projects',
+ name: 'Projects',
+ weightage: 10,
+ totalItems: 1,
+ completedItems: 1,
+ totalMarks: 40,
+ earnedMarks: 32,
+ percentage: 80.0,
+ performanceLevel: 'good',
+ color: '#28a745',
+ icon: 'faUsers',
+ description: 'Group projects and collaborative work assignments',
+ dueDate: '2024-11-19T12:00:00',
+ submissions: {
+ onTime: 1,
+ late: 0,
+ missing: 0,
+ },
+ },
+ ],
+
+ // Detailed task/assignment list
+ tasks: [
+ {
+ id: 'task-001',
+ name: 'Assignment 1: Essay on Climate Change',
+ category: 'assignments',
+ type: 'Essay Assignment',
+ weightage: 8,
+ totalMarks: 10,
+ earnedMarks: 8,
+ percentage: 80,
+ status: 'On time',
+ statusColor: '#28a745',
+ submissionDate: '2024-08-15T14:30:00Z',
+ dueDate: '2024-08-15T23:59:00Z',
+ teacherFeedback: 'Good analysis and structure. Consider adding more supporting evidence.',
+ },
+ {
+ id: 'task-002',
+ name: 'Mid-Term Exam',
+ category: 'exams',
+ type: 'Examination',
+ weightage: 20,
+ totalMarks: 100,
+ earnedMarks: 75,
+ percentage: 75,
+ status: 'On time',
+ statusColor: '#28a745',
+ submissionDate: '2024-09-15T14:30:00Z',
+ dueDate: '2024-09-15T16:00:00Z',
+ teacherFeedback: 'Solid performance overall. Review concepts from chapter 5.',
+ },
+ {
+ id: 'task-003',
+ name: 'Quiz 1: Basic Concepts',
+ category: 'quizzes',
+ type: 'Quiz',
+ weightage: 2,
+ totalMarks: 20,
+ earnedMarks: 15,
+ percentage: 75,
+ status: 'On time',
+ statusColor: '#28a745',
+ submissionDate: '2024-08-28T14:30:00Z',
+ dueDate: '2024-08-28T23:59:00Z',
+ teacherFeedback: 'Good understanding of basic concepts.',
+ },
+ {
+ id: 'task-004',
+ name: 'Assignment 2: Research Project',
+ category: 'assignments',
+ type: 'Research Assignment',
+ weightage: 12,
+ totalMarks: 10,
+ earnedMarks: 6,
+ percentage: 60,
+ status: 'Late for 2 days',
+ statusColor: '#dc3545',
+ submissionDate: '2024-09-20T14:30:00Z',
+ dueDate: '2024-09-18T23:59:00Z',
+ teacherFeedback: 'Late submission. Content needs more depth and analysis.',
+ },
+ {
+ id: 'task-005',
+ name: 'Quiz 2: Advanced Topics',
+ category: 'quizzes',
+ type: 'Quiz',
+ weightage: 2,
+ totalMarks: 15,
+ earnedMarks: 9,
+ percentage: 60,
+ status: 'On time',
+ statusColor: '#28a745',
+ submissionDate: '2024-09-25T14:30:00Z',
+ dueDate: '2024-09-25T23:59:00Z',
+ teacherFeedback: 'Review advanced concepts. Practice problems recommended.',
+ },
+ {
+ id: 'task-006',
+ name: 'Final Exam',
+ category: 'exams',
+ type: 'Final Examination',
+ weightage: 15,
+ totalMarks: 100,
+ earnedMarks: 82,
+ percentage: 82,
+ status: 'On time',
+ statusColor: '#28a745',
+ submissionDate: '2024-10-15T14:30:00Z',
+ dueDate: '2024-10-15T16:00:00Z',
+ teacherFeedback: 'Excellent improvement from mid-term. Well prepared.',
+ },
+ ],
+
+ // Summary statistics
+ summary: {
+ totalAssignments: 6,
+ completedAssignments: 6,
+ onTimeSubmissions: 5,
+ lateSubmissions: 1,
+ missingSubmissions: 0,
+ averageScore: 72,
+ improvementTrend: '+5%',
+ lastAssignmentDate: '2024-10-15T16:00:00Z',
+ },
+
+ // Teacher feedback (kept for compatibility)
+ teacherFeedback: {
+ teacherName: 'Dr. Emily Rodriguez',
+ teacherTitle: 'Professor of Computer Science',
+ overallRating: 'Good',
+ lastUpdated: '2024-10-25T10:30:00Z',
+ overall:
+ 'You performed strongly in Assignments (80%), Exams (80%), and Projects (80%). You may improve your performance in Quizzes (60%) - consider reviewing quiz preparation strategies.',
+ strengths: [
+ 'Strong analytical thinking and problem-solving skills',
+ 'Excellent written communication in assignments',
+ 'Consistent attendance and participation',
+ ],
+ improvements: [
+ 'Review quiz preparation strategies',
+ 'Practice time management during timed assessments',
+ 'Strengthen foundational concepts',
+ ],
+ },
+};
+
+// Helper functions for performance calculations
+export const getPerformanceLevel = score => {
+ if (score >= 90) return { level: 'excellent', label: 'Excellent', color: 'success' };
+ if (score >= 80) return { level: 'good', label: 'Good', color: 'primary' };
+ if (score >= 70) return { level: 'fair', label: 'Fair', color: 'warning' };
+ return { level: 'poor', label: 'Needs Improvement', color: 'danger' };
+};
+
+export const calculateCategoryProgress = category => {
+ const completionRate = Math.round((category.completedItems / category.totalItems) * 100);
+ const isComplete = category.completedItems === category.totalItems;
+ return { completionRate, isComplete };
+};
+
+export const getStatusInfo = status => {
+ if (status === 'On time' || status === 'completed') {
+ return { color: 'success', icon: 'check-circle' };
+ }
+ if (status?.toLowerCase().includes('late')) {
+ return { color: 'danger', icon: 'exclamation-triangle' };
+ }
+ return { color: 'secondary', icon: 'clock' };
+};
diff --git a/src/components/EductionPortal/EvaluationResultsWrapper.jsx b/src/components/EductionPortal/EvaluationResultsWrapper.jsx
new file mode 100644
index 0000000000..db7046e553
--- /dev/null
+++ b/src/components/EductionPortal/EvaluationResultsWrapper.jsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import { SidebarProvider } from './SidebarContext';
+import EvaluationResults from './EvaluationResults/EvaluationResults';
+
+const EvaluationResultsWithSidebar = props => {
+ return (
+
+
+
+ );
+};
+
+export default EvaluationResultsWithSidebar;
diff --git a/src/components/EductionPortal/SideBar/SideBar.jsx b/src/components/EductionPortal/SideBar/SideBar.jsx
new file mode 100644
index 0000000000..309e8f951a
--- /dev/null
+++ b/src/components/EductionPortal/SideBar/SideBar.jsx
@@ -0,0 +1,90 @@
+import React from 'react';
+import { NavLink, useLocation } from 'react-router-dom';
+import { useSelector } from 'react-redux';
+import { useSidebar } from '../SidebarContext';
+import styles from './SideBar.module.css';
+
+const SideBar = () => {
+ const location = useLocation();
+ const authUser = useSelector(state => state.auth?.user);
+ const { isMinimized, setIsMinimized } = useSidebar();
+
+ const menuItems = [
+ { icon: '🏠', label: 'Homepage', path: '/educationportal' },
+ { icon: '📊', label: 'Knowledge Evaluation', path: '#' },
+ { icon: '📋', label: 'Past Lesson Plans', path: '#' },
+ { icon: '⭐', label: 'My Saved Interests', path: '#' },
+ { icon: '📈', label: 'Evaluation results', path: '/educationportal/evaluation-results' },
+ { icon: '🏗️', label: 'Build Lesson Plan', path: '#' },
+ ];
+
+ const isActive = path => path !== '#' && location.pathname === path;
+
+ return (
+
+ {/* User Welcome Section */}
+
+
👋
+ {!isMinimized && (
+ <>
+
+
Welcome
+
{authUser?.firstName || 'Student'}
+
+
🔔
+ >
+ )}
+ {isMinimized && (
+
setIsMinimized(!isMinimized)}
+ title="Expand sidebar"
+ aria-label="Expand sidebar"
+ >
+ ➜
+
+ )}
+
+
+ {/* Toggle Button - Only show when expanded */}
+ {!isMinimized && (
+
+ setIsMinimized(!isMinimized)}
+ title="Minimize sidebar"
+ aria-label="Minimize sidebar"
+ >
+ ⬅️
+
+
+ )}
+
+ {/* Navigation Menu */}
+
+
+
+
+ );
+};
+
+export default SideBar;
diff --git a/src/components/EductionPortal/SideBar/SideBar.module.css b/src/components/EductionPortal/SideBar/SideBar.module.css
new file mode 100644
index 0000000000..5ae4c501b8
--- /dev/null
+++ b/src/components/EductionPortal/SideBar/SideBar.module.css
@@ -0,0 +1,447 @@
+/* ===== SIDEBAR CONTAINER ===== */
+.sidebar {
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 200px;
+ height: 100vh;
+ background-color: #f5f5f5;
+ border-right: 1px solid #ddd;
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ z-index: 1000;
+ transition: width 0.3s ease;
+}
+
+.sidebar.minimized {
+ width: 70px;
+}
+
+.sidebar.minimized .label,
+.sidebar.minimized .welcomeText,
+.sidebar.minimized .toggleButtonContainer {
+ display: none;
+}
+
+/* ===== USER SECTION ===== */
+.userSection {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 12px;
+ border-bottom: 1px solid #ddd;
+ background-color: #fff;
+}
+
+.welcomeIcon {
+ font-size: 20px;
+ flex-shrink: 0;
+}
+
+.welcomeText {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ min-width: 0;
+}
+
+.welcomeLabel {
+ font-size: 11px;
+ color: #999;
+ font-weight: 500;
+ text-transform: uppercase;
+}
+
+.userName {
+ font-size: 12px;
+ font-weight: 600;
+ color: #333;
+ word-break: break-word;
+}
+
+.notifyIcon {
+ font-size: 16px;
+ flex-shrink: 0;
+ cursor: pointer;
+}
+
+/* ===== NAVIGATION ===== */
+.nav {
+ flex: 1;
+ overflow-y: auto;
+ padding: 8px 0;
+}
+
+.menuList {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.menuItem {
+ margin: 0;
+ padding: 0;
+}
+
+.menuLink {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 10px 12px;
+ color: #333;
+ text-decoration: none;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ width: 100%;
+ text-align: left;
+ font-size: 13px;
+ font-weight: 500;
+ transition: background-color 0.2s ease;
+ min-height: 44px;
+}
+
+.menuLink:hover {
+ background-color: #efefef;
+}
+
+.menuLink.active {
+ background-color: #e0e7ff;
+ color: #4f46e5;
+}
+
+.icon {
+ font-size: 14px;
+ flex-shrink: 0;
+ width: 18px;
+ text-align: center;
+}
+
+.label {
+ flex: 1;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+/* ===== TOGGLE BUTTONS ===== */
+.toggleButtonContainer {
+ display: flex;
+ justify-content: center;
+ padding: 8px;
+ border-top: 1px solid #ddd;
+ background-color: #fff;
+}
+
+.minimizeBtn {
+ background: none;
+ border: 1px solid #ddd;
+ padding: 8px 12px;
+ cursor: pointer;
+ border-radius: 4px;
+ font-size: 14px;
+ transition: all 0.2s ease;
+ width: 100%;
+}
+
+.minimizeBtn:hover {
+ background-color: #f0f0f0;
+ border-color: #999;
+}
+
+.toggleButton {
+ background: none;
+ border: none;
+ padding: 8px;
+ cursor: pointer;
+ font-size: 18px;
+ transition: all 0.2s ease;
+ width: 100%;
+ height: 48px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+}
+
+.toggleButton:hover {
+ background-color: #efefef;
+}
+
+/* ===== RESPONSIVE - DESKTOP (≥992px) ===== */
+@media (min-width: 992px) {
+ /* Desktop: sidebar visible by default */
+}
+
+/* ===== RESPONSIVE - TABLET (768px - 991px) ===== */
+@media (max-width: 991px) {
+ .sidebar {
+ width: 180px;
+ }
+
+ .sidebar.minimized {
+ width: 70px;
+ }
+
+ .userSection {
+ padding: 10px;
+ gap: 6px;
+ }
+
+ .welcomeIcon {
+ font-size: 16px;
+ }
+
+ .welcomeLabel {
+ font-size: 10px;
+ }
+
+ .userName {
+ font-size: 11px;
+ }
+
+ .notifyIcon {
+ font-size: 14px;
+ }
+
+ .menuLink {
+ padding: 8px 10px;
+ font-size: 12px;
+ gap: 6px;
+ }
+
+ .icon {
+ font-size: 12px;
+ width: 16px;
+ }
+}
+
+/* ===== RESPONSIVE - MOBILE (≤767px) ===== */
+@media (max-width: 767px) {
+ .sidebar {
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 240px;
+ height: 100vh;
+ background-color: #f5f5f5;
+ border-right: 1px solid #ddd;
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ z-index: 1000;
+ transition: width 0.3s ease;
+ }
+
+ .sidebar.minimized {
+ width: 70px;
+ }
+
+ .sidebar.minimized .label,
+ .sidebar.minimized .welcomeText,
+ .sidebar.minimized .toggleButtonContainer {
+ display: none;
+ }
+
+ .userSection {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 14px 12px;
+ border-bottom: 1px solid #ddd;
+ background-color: #fff;
+ }
+
+ .welcomeIcon {
+ font-size: 18px;
+ flex-shrink: 0;
+ }
+
+ .welcomeText {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ min-width: 0;
+ }
+
+ .welcomeLabel {
+ font-size: 10px;
+ color: #999;
+ font-weight: 500;
+ text-transform: uppercase;
+ }
+
+ .userName {
+ font-size: 12px;
+ font-weight: 600;
+ color: #333;
+ word-break: break-word;
+ }
+
+ .notifyIcon {
+ font-size: 16px;
+ flex-shrink: 0;
+ cursor: pointer;
+ padding: 6px;
+ border-radius: 4px;
+ transition: background-color 0.2s ease;
+ }
+
+ .notifyIcon:active {
+ background-color: #e0e0e0;
+ }
+
+ .nav {
+ flex: 1;
+ overflow-y: auto;
+ padding: 8px 0;
+ }
+
+ .menuList {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
+
+ .menuItem {
+ margin: 0;
+ padding: 0;
+ }
+
+ .menuLink {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 12px 14px;
+ color: #333;
+ text-decoration: none;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ width: 100%;
+ text-align: left;
+ font-size: 13px;
+ font-weight: 500;
+ transition: all 0.2s ease;
+ min-height: 48px;
+ }
+
+ .menuLink:active {
+ background-color: #f0f0f0;
+ }
+
+ .menuLink:hover {
+ background-color: #efefef;
+ }
+
+ .menuLink.active {
+ background-color: #e0e7ff;
+ color: #4f46e5;
+ border-left: 3px solid #4f46e5;
+ padding-left: 11px;
+ }
+
+ .icon {
+ font-size: 16px;
+ flex-shrink: 0;
+ width: 20px;
+ text-align: center;
+ }
+
+ .label {
+ flex: 1;
+ white-space: normal;
+ overflow: visible;
+ text-overflow: clip;
+ word-wrap: break-word;
+ }
+}
+
+/* ===== RESPONSIVE - SMALL PHONES (≤480px) ===== */
+@media (max-width: 480px) {
+ .sidebar {
+ width: 220px;
+ }
+
+ .sidebar.minimized {
+ width: 70px;
+ }
+
+ .sidebar.minimized .label,
+ .sidebar.minimized .welcomeText,
+ .sidebar.minimized .toggleButtonContainer {
+ display: none;
+ }
+
+ .userSection {
+ padding: 12px 10px;
+ }
+
+ .welcomeIcon {
+ font-size: 16px;
+ }
+
+ .userName {
+ font-size: 11px;
+ }
+
+ .menuLink {
+ padding: 11px 12px;
+ font-size: 12px;
+ gap: 8px;
+ }
+
+ .icon {
+ font-size: 14px;
+ width: 18px;
+ }
+}
+
+/* ===== RESPONSIVE - EXTRA SMALL (≤360px) ===== */
+@media (max-width: 359px) {
+ .sidebar {
+ width: 200px;
+ }
+
+ .sidebar.minimized {
+ width: 70px;
+ }
+
+ .sidebar.minimized .label,
+ .sidebar.minimized .welcomeText,
+ .sidebar.minimized .toggleButtonContainer {
+ display: none;
+ }
+
+ .userSection {
+ padding: 10px 8px;
+ gap: 6px;
+ }
+
+ .welcomeIcon {
+ font-size: 14px;
+ }
+
+ .welcomeLabel {
+ font-size: 9px;
+ }
+
+ .userName {
+ font-size: 10px;
+ }
+
+ .menuLink {
+ padding: 10px 10px;
+ font-size: 11px;
+ gap: 6px;
+ min-height: 44px;
+ }
+
+ .icon {
+ font-size: 12px;
+ width: 16px;
+ }
+}
diff --git a/src/components/EductionPortal/SidebarContext.jsx b/src/components/EductionPortal/SidebarContext.jsx
new file mode 100644
index 0000000000..51664b0fd1
--- /dev/null
+++ b/src/components/EductionPortal/SidebarContext.jsx
@@ -0,0 +1,21 @@
+import React, { createContext, useState } from 'react';
+
+export const SidebarContext = createContext();
+
+export const SidebarProvider = ({ children }) => {
+ const [isMinimized, setIsMinimized] = useState(false);
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useSidebar = () => {
+ const context = React.useContext(SidebarContext);
+ if (!context) {
+ throw new Error('useSidebar must be used within a SidebarProvider');
+ }
+ return context;
+};
diff --git a/src/components/Header/HeaderRenderer.jsx b/src/components/Header/HeaderRenderer.jsx
index ed70df12b2..6df0a5c63d 100644
--- a/src/components/Header/HeaderRenderer.jsx
+++ b/src/components/Header/HeaderRenderer.jsx
@@ -10,7 +10,13 @@ import hasPermission from '../../utils/permissions';
export function HeaderRenderer(props) {
const location = useLocation();
const isCommunityPortal = location.pathname.startsWith('/communityportal');
-
+ const isEducationEvaluation = location.pathname.startsWith('/educationportal/evaluation-results');
+
+ // Hide header for education portal evaluation results page
+ if (isEducationEvaluation) {
+ return null;
+ }
+
// eslint-disable-next-line react/jsx-props-no-spreading
return isCommunityPortal ? : ;
}
diff --git a/src/routes.jsx b/src/routes.jsx
index 119a0d23de..4c571574ed 100644
--- a/src/routes.jsx
+++ b/src/routes.jsx
@@ -166,6 +166,7 @@ import EPProtectedRoute from './components/common/EPDashboard/EPProtectedRoute';
import EPLogin from './components/EductionPortal/Login';
import EPDashboard from './components/EductionPortal';
import GroupList from './components/EductionPortal/GroupList/GroupList';
+import EvaluationResultsWrapper from './components/EductionPortal/EvaluationResultsWrapper';
import PRReviewTeamAnalytics from './components/HGNPRDashboard/PRReviewTeamAnalytics';
import PRDashboardOverview from './components/HGNPRDashboard/PRDashboardOverview';
@@ -763,6 +764,11 @@ export default (
/>
{/* Good Education Portal Routes */}
+