+
+ ✅ Registration Successful!
+
+ ✖
+
+
+
Thank you for Registering!
+
+ You have successfully registered for the event. We have reserved your space. See you
+ there!
+
+
+
Event Name
+
+ (Click for more details)
+
+
User's Full Name
+
+ 📅 Tuesday, January 7th, 2025
+ ⏰ 7:00 PM CST
+ 📍 Location
-
Thank you for Registering!
-
- You have successfully registered for the event. We have reserved your space. See you
- there!
-
-
-
Event Name
-
(Click for more details)
-
User's Full Name
-
-
- 📅 Tuesday, January 7th, 2025
- ⏰ 7:00 PM CST
- 📍 Location
-
-
-
- Add to my calendar
+
+ Add to my calendar
+
+
+
+ View details in Email
+
+
+ Download Ticket
-
-
-
- View details in Email
-
-
- Download Ticket
-
-
@@ -48,4 +63,8 @@ function Popup({ onClose }) {
);
}
+Popup.propTypes = {
+ onClose: PropTypes.func.isRequired,
+};
+
export default Popup;
diff --git a/src/components/CommunityPortal/RegistrationConfirmation/RegistrationPopup.module.css b/src/components/CommunityPortal/RegistrationConfirmation/RegistrationPopup.module.css
index dfdc92f9bd..dfd21c3583 100644
--- a/src/components/CommunityPortal/RegistrationConfirmation/RegistrationPopup.module.css
+++ b/src/components/CommunityPortal/RegistrationConfirmation/RegistrationPopup.module.css
@@ -1,32 +1,46 @@
+/* Popup overlay */
.popupOverlay {
position: fixed;
- inset: 0;
- background: rgb(0 0 0 / 55%);
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgb(0 0 0 / 50%);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
+/* Popup container */
.popup {
- width: 420px;
- max-width: 90%;
- background: #fff;
- color: #1a1a1a;
- border-radius: 12px;
- padding: 24px;
- box-shadow: 0 12px 30px rgb(0 0 0 / 20%);
+ background: white;
+ padding: 20px;
+ width: 400px;
+ border-radius: 8px;
+ box-shadow: 0 4px 10px rgb(0 0 0 / 20%);
+ text-align: center;
+ position: relative;
+}
+
+.popupDark {
+ background: #3a506b;
+ color: white;
+ padding: 20px;
+ width: 400px;
+ border-radius: 8px;
+ box-shadow: 0 4px 10px rgb(0 0 0 / 20%);
text-align: center;
- animation: fade-in 0.2s ease-out;
+ position: relative;
}
+/* Popup header */
.popupHeader {
display: flex;
- align-items: center;
justify-content: space-between;
- font-weight: 600;
- font-size: 15px;
- margin-bottom: 16px;
+ align-items: center;
+ font-size: 16px;
+ font-weight: bold;
}
.closeBtn {
@@ -34,109 +48,70 @@
border: none;
font-size: 18px;
cursor: pointer;
- color: #d32f2f;
-}
-
-.popupContent {
- margin-top: 16px;
}
+/* Event details */
.eventDetails {
- color: #1976d2;
+ color: blue;
cursor: pointer;
- margin: 6px 0 12px;
- font-size: 14px;
-}
-
-.userFullName {
- font-weight: 600;
- margin-bottom: 12px;
+ margin-bottom: 10px;
+ text-decoration: underline;
}
+/* Event info */
.eventInfo {
display: flex;
- flex-direction: column;
- gap: 6px;
- font-size: 14px;
- margin: 16px 0;
+ justify-content: space-between;
+ padding: 10px 0;
}
+/* Buttons */
+.registerBtn,
.calendarBtn,
.emailBtn,
.downloadBtn {
- width: 100%;
- padding: 10px 12px;
- border-radius: 8px;
+ display: block;
+ margin: 10px auto;
+ padding: 10px;
border: none;
+ border-radius: 5px;
font-size: 14px;
cursor: pointer;
}
-.calendarBtn {
- background: #2e7d32;
- color: #fff;
- margin-bottom: 16px;
+.registerBtn {
+ background: #0056b3;
+ color: white;
}
-.popupFooter {
- display: flex;
- gap: 12px;
+.calendarBtn {
+ background: #1a7a32;
+ color: white;
}
.emailBtn {
- background: #01579b;
- color: #fff;
- flex: 1;
+ background: #0d6b7a;
+ color: white;
}
.downloadBtn {
- background: #fbc02d;
- color: #000;
- flex: 1;
-}
-
-/* ==========================================================================
- DARK MODE
- ========================================================================== */
-
-.darkMode .popup {
- background: #2c3e50;
- color: #ecf0f1;
+ background: #7a5c00;
+ color: white;
}
-.darkMode .eventDetails {
- color: #90caf9;
-}
-
-.darkMode .calendarBtn {
- background: #43a047;
-}
-
-.darkMode .emailBtn {
- background: #0277bd;
+.popupFooter {
+ display: flex;
+ justify-content: space-between;
}
-.darkMode .downloadBtn {
- background: #fdd835;
+:global(.darkMode) .eventDetails {
+ color: #90cdf4;
}
-.darkMode .userFullName,
-.darkMode p {
- color: #ecf0f1;
+.userFullName {
+ /* Add any specific styles for user full name if needed */
}
-/* ==========================================================================
- ANIMATIONS
- ========================================================================== */
-
-@keyframes fade-in {
- from {
- opacity: 0;
- transform: translateY(8px);
- }
-
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
+.popupContent {
+ /* Add any specific styles for popup content if needed */
+}
\ No newline at end of file
diff --git a/src/components/CommunityPortal/utils.js b/src/components/CommunityPortal/utils.js
deleted file mode 100644
index d6e62f504b..0000000000
--- a/src/components/CommunityPortal/utils.js
+++ /dev/null
@@ -1,22 +0,0 @@
-export function isTomorrow(dateString) {
- const input = new Date(dateString);
- const today = new Date();
- today.setHours(0, 0, 0, 0);
- const tomorrow = new Date(today);
- tomorrow.setDate(today.getDate() + 1);
- return input >= tomorrow && input < new Date(tomorrow.getTime() + 24 * 60 * 60 * 1000);
-}
-
-export function isComingWeekend(dateString) {
- const input = new Date(dateString);
- const today = new Date();
- today.setHours(0, 0, 0, 0);
- const day = today.getDay();
- const daysUntilSaturday = (6 - day + 7) % 7 || 7;
- const saturday = new Date(today);
- saturday.setDate(today.getDate() + daysUntilSaturday);
- const sunday = new Date(saturday);
- sunday.setDate(saturday.getDate() + 1);
- sunday.setHours(23, 59, 59, 999);
- return input >= saturday && input <= sunday;
-}
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..b1695c0692
--- /dev/null
+++ b/src/components/EductionPortal/EducationPortalSideNav/EducationPortalSideNav.module.css
@@ -0,0 +1,449 @@
+/* stylelint-disable declaration-property-value-keyword-no-deprecated, no-descending-specificity */
+
+/* ===== 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 (width >= 992px) {
+ /* Desktop: sidebar visible by default */
+}
+
+/* ===== RESPONSIVE - TABLET (768px - 991px) ===== */
+@media (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 (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;
+ overflow-wrap: break-word;
+ }
+}
+
+/* ===== RESPONSIVE - SMALL PHONES (≤480px) ===== */
+@media (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 (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;
+ font-size: 11px;
+ gap: 6px;
+ min-height: 44px;
+ }
+
+ .icon {
+ font-size: 12px;
+ width: 16px;
+ }
+}
diff --git a/src/components/EductionPortal/EducatorReports/DashboardLayout/DashboardLayout.jsx b/src/components/EductionPortal/EducatorReports/DashboardLayout/DashboardLayout.jsx
deleted file mode 100644
index 14ddfed416..0000000000
--- a/src/components/EductionPortal/EducatorReports/DashboardLayout/DashboardLayout.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react';
-import { useSelector } from 'react-redux';
-import styles from './DashboardLayout.module.css';
-
-const DashboardLayout = ({ children }) => {
- const darkMode = useSelector(state => state.theme?.darkMode || false);
-
- return (
-
- );
-};
-
-export default DashboardLayout;
diff --git a/src/components/EductionPortal/EducatorReports/DashboardLayout/DashboardLayout.module.css b/src/components/EductionPortal/EducatorReports/DashboardLayout/DashboardLayout.module.css
deleted file mode 100644
index 443af2de1f..0000000000
--- a/src/components/EductionPortal/EducatorReports/DashboardLayout/DashboardLayout.module.css
+++ /dev/null
@@ -1,46 +0,0 @@
-.dashboardLayout {
- display: flex;
- min-height: 100vh;
- background-color: #f8f9fa;
-}
-
-.mainContent {
- flex: 1;
- margin-left: 0;
- min-height: 100vh;
- overflow-x: auto;
-}
-
-.contentWrapper {
- padding: 0 20px;
- max-width: 100%;
-}
-
-@media (width <= 768px) {
- .dashboardLayout {
- flex-direction: column;
- margin-top: 0;
- min-height: 100vh;
- }
-
- .mainContent {
- margin-left: 0;
- width: 100%;
- min-height: auto;
- order: 2;
- }
-
- .contentWrapper {
- padding: 16px;
- }
-}
-
-@media (width <= 480px) {
- .contentWrapper {
- padding: 12px;
- }
-}
-
-.darkMode .dashboardLayout {
- background-color: #0f172a;
-}
diff --git a/src/components/EductionPortal/EducatorReports/ReportChart.jsx b/src/components/EductionPortal/EducatorReports/ReportChart.jsx
deleted file mode 100644
index 199a7efa9f..0000000000
--- a/src/components/EductionPortal/EducatorReports/ReportChart.jsx
+++ /dev/null
@@ -1,125 +0,0 @@
-import React from 'react';
-import {
- Chart as ChartJS,
- CategoryScale,
- LinearScale,
- BarElement,
- Title,
- Tooltip,
- Legend,
- LineElement,
- PointElement,
- ArcElement,
-} from 'chart.js';
-import { Bar, Line, Doughnut } from 'react-chartjs-2';
-import { useSelector } from 'react-redux';
-import styles from './ReportChart.module.css';
-import ChartDataLabels from 'chartjs-plugin-datalabels';
-ChartJS.register(
- CategoryScale,
- LinearScale,
- BarElement,
- Title,
- Tooltip,
- Legend,
- LineElement,
- PointElement,
- ArcElement,
- ChartDataLabels,
-);
-
-const ReportChart = ({
- type = 'bar',
- data,
- height = 300,
- showLegend = true,
- horizontal = false,
- options: customOptions = {},
-}) => {
- const darkMode = useSelector(state => state.theme?.darkMode || false);
-
- const getChartOptions = () => {
- const baseOptions = {
- responsive: true,
- maintainAspectRatio: false,
- indexAxis: horizontal ? 'y' : 'x',
- plugins: {
- datalabels: { display: type !== 'line', color: '#ffffff' },
- legend: {
- display: showLegend,
- labels: {
- color: darkMode ? '#f1f5f9' : '#1e293b',
- font: {
- size: 12,
- },
- },
- },
- tooltip: {
- backgroundColor: darkMode ? '#0f172a' : '#ffffff',
- titleColor: darkMode ? '#f1f5f9' : '#0f172a',
- bodyColor: darkMode ? '#94a3b8' : '#475569',
- borderColor: darkMode ? '#334155' : '#e2e8f0',
- borderWidth: 1,
- },
- },
- scales: {
- x: {
- grid: {
- color: darkMode ? '#334155' : '#cbd5e1',
- },
- ticks: {
- color: darkMode ? '#f1f5f9' : '#1e293b',
- font: {
- size: 11,
- },
- },
- },
- y: {
- grid: {
- color: darkMode ? '#334155' : '#cbd5e1',
- },
- ticks: {
- color: darkMode ? '#f1f5f9' : '#1e293b',
- font: {
- size: 11,
- },
- },
- },
- },
- };
-
- return {
- ...baseOptions,
- ...customOptions,
- plugins: {
- ...baseOptions.plugins,
- ...customOptions.plugins,
- },
- };
- };
-
- const renderChart = () => {
- const chartOptions = getChartOptions();
-
- switch (type) {
- case 'line':
- return
;
- case 'doughnut':
- return
;
- case 'bar':
- default:
- return
;
- }
- };
-
- return (
-
- {renderChart()}
-
- );
-};
-
-export default ReportChart;
diff --git a/src/components/EductionPortal/EducatorReports/ReportChart.module.css b/src/components/EductionPortal/EducatorReports/ReportChart.module.css
deleted file mode 100644
index 608095133c..0000000000
--- a/src/components/EductionPortal/EducatorReports/ReportChart.module.css
+++ /dev/null
@@ -1,16 +0,0 @@
-.chartContainer {
- width: 100%;
- padding: 15px;
- background: var(--bg-color, #fff);
- border-radius: 8px;
- box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
-}
-
-.chartContainer.darkMode {
- background: #1e293b;
- box-shadow: 0 2px 4px rgb(0 0 0 / 30%);
-}
-
-.chartContainer canvas {
- max-height: 100% !important;
-}
diff --git a/src/components/EductionPortal/EducatorReports/ReportsView.jsx b/src/components/EductionPortal/EducatorReports/ReportsView.jsx
deleted file mode 100644
index e065c10fe3..0000000000
--- a/src/components/EductionPortal/EducatorReports/ReportsView.jsx
+++ /dev/null
@@ -1,446 +0,0 @@
-import React, { useState } from 'react';
-import {
- Container,
- Row,
- Col,
- Card,
- CardBody,
- Table,
- Dropdown,
- DropdownToggle,
- DropdownMenu,
- DropdownItem,
- Nav,
- NavItem,
- NavLink,
-} from 'reactstrap';
-import { useSelector } from 'react-redux';
-import styles from './ReportsView.module.css';
-import ReportChart from './ReportChart';
-import IndividualReportView from './components/IndividualReportView/IndividualReportView';
-import ClassPerformanceView from './components/ClassPerformanceView/ClassPerformanceView';
-import { getStatusClass, getStatusIcon, getStatusText } from './utils/statusUtils';
-import {
- strengthsGapsData,
- performanceTrendData,
- teachingStrategiesData,
- lifeStrategiesData,
- subjects,
- students,
- classes,
-} from './mockdata';
-
-const ReportsView = () => {
- const [subjectFilter, setSubjectFilter] = useState('All Subjects');
- const [subjectDropdownOpen, setSubjectDropdownOpen] = useState(false);
- const [performanceDropdownOpen, setPerformanceDropdownOpen] = useState(false);
- const [activeTab, setActiveTab] = useState('overview');
- const [filters, setFilters] = useState({
- studentId: null,
- classId: null,
- subject: 'All Subjects',
- dateRange: null,
- });
-
- const darkMode = useSelector(state => state.theme?.darkMode || false);
-
- // Filter functions
- const getFilteredStrengthsGapsData = () => {
- if (subjectFilter === 'All Subjects') {
- return strengthsGapsData;
- }
- return strengthsGapsData.filter(item => item.subject === subjectFilter);
- };
-
- const getFilteredPerformanceTrendData = () => {
- if (subjectFilter === 'All Subjects') {
- return performanceTrendData;
- }
-
- // Filter datasets to show only the selected subject
- const filteredDatasets = performanceTrendData.datasets.filter(
- dataset => dataset.label === subjectFilter,
- );
-
- return {
- ...performanceTrendData,
- datasets: filteredDatasets,
- };
- };
-
- const handleSubjectFilterChange = subjectName => {
- setSubjectFilter(subjectName);
- setSubjectDropdownOpen(false);
- };
-
- // Status helpers are shared via utils/statusUtils.js
-
- return (
-
-
- {/* Header */}
-
-
Analytics: Actionable Visualizations
-
-
- {/* Tab Navigation */}
-
-
-
- setActiveTab('overview')}
- >
- Overview
-
-
-
- setActiveTab('individual')}
- >
- Individual Student Report
-
-
-
- setActiveTab('class')}
- >
- Class Performance
-
-
-
-
-
- {/* Filter Bar for Individual/Class Views */}
- {(activeTab === 'individual' || activeTab === 'class') && (
-
-
-
-
- {activeTab === 'individual' ? 'Select Student:' : 'Select Class:'}
-
- {
- if (activeTab === 'individual') {
- setFilters({ ...filters, studentId: e.target.value || null });
- } else {
- setFilters({ ...filters, classId: e.target.value || null });
- }
- }}
- >
-
- {activeTab === 'individual' ? '-- Select a Student --' : '-- Select a Class --'}
-
- {activeTab === 'individual'
- ? students.map(student => (
-
- {student.name}
-
- ))
- : classes.map(cls => (
-
- {cls.name}
-
- ))}
-
-
-
-
- )}
-
- {/* Render Active Tab Content */}
- {activeTab === 'overview' && (
-
-
-
-
-
-
-
Strengths & Gaps by Subject
- setSubjectDropdownOpen(!subjectDropdownOpen)}
- className={`${styles.subjectDropdown}`}
- >
-
- {subjectFilter}
-
-
- {subjects.map(subject => (
- handleSubjectFilterChange(subject.name)}
- className={`${styles.dropdownItem} ${styles.coloredDropdownItem}`}
- style={{ color: subject.color }}
- >
- {subject.name}
-
- ))}
-
-
-
-
-
-
-
-
- Subject
- Performance
- Status
- Visual Indicator
-
-
-
- {getFilteredStrengthsGapsData().map(item => (
-
- {item.subject}
-
-
-
-
- {item.performance}%
-
-
-
-
-
- {getStatusText(item.performance)}
-
-
-
-
- {getStatusIcon(item.performance)}
-
-
-
- ))}
-
-
-
-
- {/* Actionable Insight 1 */}
-
-
- Actionable Insight: You consistently excel in Mathematics
- and English. Consider focusing extra effort on Arts/Trades and Values.
-
-
- Set Target Goals
- Study Schedule Tips
-
-
-
-
-
-
-
- {/* Performance Trend by Subject Over Time */}
-
-
-
-
-
-
- Performance Trend by Subject Over Time
-
- setPerformanceDropdownOpen(!performanceDropdownOpen)}
- className={`${styles.subjectDropdown}`}
- >
-
- {subjectFilter}
-
-
- {subjects.map(subject => (
- handleSubjectFilterChange(subject.name)}
- className={`${styles.dropdownItem} ${styles.coloredDropdownItem}`}
- style={{ color: subject.color }}
- >
- {subject.name}
-
- ))}
-
-
-
-
-
-
-
-
-
-
- Actionable Insight: Your performance in Mathematics shows a
- consistent upward trend. Keep up the great work! Notice a dip in Art
- activities during that period.
-
-
-
- Review Notes lesson plans
-
- Get one goal for Art
-
-
-
-
-
-
-
- {/* Teaching Strategies */}
-
-
-
-
- Effectiveness of Teaching Strategies
-
-
-
-
-
-
-
-
- Highly Effective (85%)
-
-
-
- Effective (70-84%)
-
-
-
- Needs Adaptation (<70%)
-
-
-
-
-
- Actionable Insight: You found 'Game Genius' and
- 'Power Play' particularly engaging. These strategies seem to align
- with your learning style. Strategies like 'Curious Dropout' might
- require a different approach for you.
-
-
-
- Ask teacher for more Game Genius lessons
-
-
- Explore Power Play activities
-
-
-
-
-
-
-
-
- {/* Life Strategies */}
-
-
-
-
- Impact of Life Strategies
-
-
-
-
-
-
-
-
- Very Good (85%+)
-
-
-
- Good Impact (70-84%)
-
-
-
- Moderate Impact (50-69%)
-
-
-
- Low Impact (<50%)
-
-
-
-
-
- Actionable Insight: Consistently applying 'Everything
- you do should increase choices' seems to correlate with positive
- learning experiences for you. Consider focusing more on 'Practice
- improving your emotional intelligence' to enhance your overall
- well-being and learning.
-
-
-
- Learn more about choice-making strategies
-
-
- Tips for emotional intelligence
-
-
-
-
-
-
-
-
- )}
-
- {activeTab === 'individual' &&
}
-
- {activeTab === 'class' &&
}
-
-
- );
-};
-
-export default ReportsView;
diff --git a/src/components/EductionPortal/EducatorReports/ReportsView.module.css b/src/components/EductionPortal/EducatorReports/ReportsView.module.css
deleted file mode 100644
index ae5201ba7e..0000000000
--- a/src/components/EductionPortal/EducatorReports/ReportsView.module.css
+++ /dev/null
@@ -1,924 +0,0 @@
-.dashboardContainer {
- padding: 5px 20px 20px;
- background-color: #fff;
- min-height: 100vh;
-}
-
-.darkMode .dashboardContainer {
- background-color: #0f172a;
-}
-
-.dashboardHeader {
- margin-bottom: 20px;
- padding: 10px 0;
- border-bottom: 2px solid #e0e0e0;
-}
-
-.darkMode .dashboardHeader {
- border-bottom-color: rgb(255 255 255 / 12%);
-}
-
-.dashboardTitle {
- color: var(--primary-color, #2c3e50);
- font-size: 28px;
- font-weight: 600;
- margin-bottom: 0;
-}
-
-.darkMode .dashboardTitle {
- color: var(--primary-color-dark, #fff);
-}
-
-.dashboardSubtitle {
- color: var(--text-secondary, #666);
- font-size: 16px;
- margin: 0;
-}
-
-.darkMode .dashboardSubtitle {
- color: var(--text-secondary-dark, #ccc);
-}
-
-.sectionRow {
- margin-bottom: 30px;
- padding: 0;
-}
-
-.reportCard {
- border: none;
- border-radius: 12px;
- box-shadow: 0 4px 6px rgb(0 0 0 / 10%);
- transition: all 0.3s ease;
- background: white;
-}
-
-.cardBody {
- background-color: #f8fafc;
-}
-
-.darkMode .cardBody {
- background-color: #1e293b;
-}
-
-.reportCard:hover {
- box-shadow: 0 6px 12px rgb(0 0 0 / 15%);
-}
-
-.darkMode .reportCard {
- background: #1e293b;
- box-shadow: 0 4px 6px rgb(0 0 0 / 30%);
-}
-
-/* Card Headers */
-.cardHeader {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
-}
-
-.cardTitle {
- color: var(--primary-color, #1d283a);
- font-size: 20px;
- font-weight: 600;
- margin: 0;
-}
-
-.darkMode .cardTitle {
- color: var(--primary-color-dark, #fff);
-}
-
-.subjectDropdown {
- min-width: 140px;
-}
-
-.dropdownToggle {
- background: var(--primary-color, #0069d9);
- border: none;
- border-radius: 6px;
- padding: 8px 16px;
- font-size: 14px;
-}
-
-.darkMode .dropdownToggle {
- background: #4f46e5;
- color: #fff;
-}
-
-.darkMode .dropdownToggle::after {
- border-top-color: #fff;
-}
-
-.darkMode .dropdownToggle:focus,
-.darkMode .dropdownToggle:active,
-.darkMode .dropdownToggle span {
- background: #4f46e5;
- color: #fff;
- box-shadow: none;
-}
-
-.dropdownMenu {
- border-radius: 8px;
- box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
- border: none;
-}
-
-.dropdownItem {
- padding: 10px 16px;
- font-size: 14px;
- transition: background-color 0.2s ease;
-}
-
-.dropdownItem:hover {
- background-color: var(--hover-color, #f8f9fa);
-}
-
-.darkMode .dropdownMenu {
- background-color: #1e293b;
- box-shadow: 0 10px 28px rgb(0 0 0 / 55%);
- border: 1px solid #334155;
-}
-
-.darkMode .dropdownItem {
- background-color: #1e293b;
-}
-
-.darkMode .dropdownItem:hover {
- background-color: rgb(255 255 255 / 8%);
-}
-
-.coloredDropdownItem {
- font-weight: 500;
-}
-
-.coloredDropdownItem:hover {
- background-color: rgb(0 0 0 / 5%);
- opacity: 0.8;
-}
-
-.strengthsGapsSection {
- background: white;
- border-radius: 12px;
- padding: 25px;
- margin-bottom: 30px;
- box-shadow: 0 4px 6px rgb(0 0 0 / 10%);
-}
-
-.darkMode .strengthsGapsSection {
- background: #1e293b;
- box-shadow: 0 4px 6px rgb(0 0 0 / 30%);
-}
-
-.strengthsTable {
- width: 100%;
- border-collapse: separate;
- border-spacing: 0;
-}
-
-.strengthsTable th {
- background-color: #f9fafb;
- color: #374151;
- font-weight: 600;
- border: none;
- padding: 1rem 0.75rem;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- font-size: 0.75rem;
-}
-
-.tableHeader {
- background: linear-gradient(135deg, #4338ca 0%, #6b21a8 100%);
- color: white;
-}
-
-.darkMode .tableHeader {
- background: linear-gradient(135deg, #4f66d6 0%, #5f3c86 100%);
-}
-
-.tableHeader th {
- padding: 15px 20px;
- font-weight: 600;
- text-align: left;
- border: none;
- font-size: 14px;
-}
-
-.tableHeader th:first-child {
- border-radius: 8px 0 0;
-}
-
-.tableHeader th:last-child {
- border-radius: 0 8px 0 0;
-}
-
-.darkMode .strengthsTable th {
- background-color: #374151;
- color: #d1d5db;
-}
-
-.strengthsTable tbody tr {
- border-bottom: 1px solid #e0e0e0;
- transition: background-color 0.2s ease;
-}
-
-.strengthsTable tbody tr:hover {
- background-color: #f8f9fa;
-}
-
-.darkMode .strengthsTable tbody tr {
- border-bottom-color: #334155;
-}
-
-.strengthsTable td {
- padding: 15px 20px;
- vertical-align: middle;
- border: none;
- font-size: 14px;
- color: #333;
-}
-
-.darkMode .strengthsTable td {
- color: #f1f5f9;
-}
-
-.subjectCell {
- font-weight: 500;
- color: #1d283a;
-}
-
-.darkMode .subjectCell {
- color: #f1f5f9;
-}
-
-.performanceCell {
- min-width: 160px;
-}
-
-.visualCell {
- text-align: center;
-}
-
-.subjectName {
- font-weight: 500;
- color: var(--primary-color, #2c3e50);
-}
-
-.darkMode .subjectName {
- color: var(--primary-color-dark, #64b5f6);
-}
-
-.progressContainer {
- display: flex;
- align-items: center;
- gap: 12px;
-}
-
-.progressBar {
- flex: 1;
- height: 8px;
- background-color: #e0e0e0;
- border-radius: 4px;
- overflow: hidden;
-}
-
-.darkMode .progressBar {
- background-color: #334155;
-}
-
-.progressFill {
- height: 100%;
- border-radius: 4px;
- transition: width 0.6s ease;
-}
-
-.progressFill.strength {
- background: linear-gradient(90deg, #4caf50, #8bc34a);
-}
-
-.progressFill.moderate {
- background: linear-gradient(90deg, #ff9800, #ffc107);
-}
-
-.progressFill.gap {
- background: linear-gradient(90deg, #f44336, #e91e63);
-}
-
-.progressText {
- font-weight: 600;
- font-size: 13px;
- min-width: 40px;
- text-align: right;
-}
-
-.progressText.strength {
- color: #4caf50;
-}
-
-.progressText.moderate {
- color: #ff9800;
-}
-
-.progressText.gap {
- color: #f44336;
-}
-
-.darkMode .progressText {
- color: rgb(255 255 255 / 92%);
-}
-
-.chartContainer {
- margin: 20px 0;
- min-height: 300px;
-}
-
-.legend {
- display: flex;
- justify-content: center;
- gap: 24px;
- margin-top: 20px;
- flex-wrap: wrap;
-}
-
-.legendItem {
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 13px;
- color: var(--text-primary, #333);
-}
-
-.darkMode .legendItem {
- color: var(--text-primary-dark, #fff);
-}
-
-.legendColor {
- width: 16px;
- height: 16px;
- border-radius: 3px;
- flex-shrink: 0;
-}
-
-.legendColor.highlyEffective {
- background: #4caf50;
-}
-
-.legendColor.effective {
- background: #8bc34a;
-}
-
-.legendColor.needsAdaptation {
- background: #ff9800;
-}
-
-.legendColor.veryGood {
- background: #2196f3;
-}
-
-.legendColor.goodImpact {
- background: #4caf50;
-}
-
-.legendColor.moderateImpact {
- background: #ff9800;
-}
-
-.legendColor.lowImpact {
- background: #f44336;
-}
-
-.insightAlert {
- margin-top: 20px;
- border: none;
- border-radius: 8px;
- padding: 20px;
-}
-
-.insightAlertInfo {
- background-color: #d1ecf1;
- border: 1px solid #bee5eb;
- color: #0c5460;
-}
-
-.insightAlertSuccess {
- background-color: #d4edda;
- border: 1px solid #c3e6cb;
- color: #155724;
-}
-
-.insightAlertWarning {
- background-color: #fff3cd;
- border: 1px solid #ffeeba;
- color: #856404;
-}
-
-.insightAlertDanger {
- background-color: #f8d7da;
- border: 1px solid #f5c6cb;
- color: #721c24;
-}
-
-.insightAlertPrimary {
- background-color: #cce5ff;
- border: 1px solid #b8daff;
- color: #004085;
-}
-
-.actionButton {
- background: var(--primary-color, #0069d9);
- color: white;
- border: none;
- border-radius: 6px;
- padding: 8px 16px;
- font-size: 13px;
- font-weight: 500;
- cursor: pointer;
- transition: all 0.2s ease;
-}
-
-.actionButton:hover {
- background: var(--primary-hover, #0056b3);
- transform: translateY(-1px);
-}
-
-.darkMode .actionButton {
- background: var(--primary-color-dark, #2563eb);
-}
-
-.insightAlertInfo .actionButton {
- background: #0ea5e9;
-}
-
-.insightAlertSuccess .actionButton {
- background: #22c55e;
-}
-
-.insightAlertWarning .actionButton {
- background: #b45309;
- color: #fff;
-}
-
-.insightAlertDanger .actionButton {
- background: #ef4444;
-}
-
-.insightAlertInfo .actionButton:hover {
- background: #0284c7;
-}
-
-.insightAlertSuccess .actionButton:hover {
- background: #16a34a;
-}
-
-.insightAlertWarning .actionButton:hover {
- background: #9a3412;
-}
-
-.insightAlertDanger .actionButton:hover {
- background: #dc2626;
-}
-
-.darkMode .insightAlert {
- color: #e2e8f0;
- background-color: #1e293b;
- box-shadow: 0 10px 24px rgb(0 0 0 / 35%);
- border: 1px solid #334155;
-}
-
-.darkMode .insightAlert strong {
- color: #f1f5f9;
-}
-
-.darkMode .insightAlert.insightAlertInfo {
- background-color: #172554;
- border-color: #1e40af;
- color: #93c5fd;
-}
-
-.darkMode .insightAlert.insightAlertSuccess {
- background-color: #052e16;
- border-color: #166534;
- color: #86efac;
-}
-
-.darkMode .insightAlert.insightAlertWarning {
- background-color: #451a03;
- border-color: #92400e;
- color: #fde68a;
-}
-
-.darkMode .insightAlert.insightAlertDanger {
- background-color: #450a0a;
- border-color: #991b1b;
- color: #fca5a5;
-}
-
-.darkMode .insightAlert.insightAlertPrimary {
- background-color: #172554;
- border-color: #1e40af;
- color: #93c5fd;
-}
-
-.darkMode .insightAlert .actionButton {
- color: #fff;
-}
-
-.insightContent {
- margin-bottom: 15px;
- line-height: 1.6;
- font-size: 14px;
-}
-
-.insightActions {
- display: flex;
- gap: 12px;
- flex-wrap: wrap;
-}
-
-.darkMode .insightAlert.insightAlertInfo .actionButton {
- background: #0284c7;
-}
-
-.darkMode .insightAlert.insightAlertSuccess .actionButton {
- background: #16a34a;
-}
-
-.darkMode .insightAlert.insightAlertWarning .actionButton {
- background: #b45309;
- color: #fff;
-}
-
-.darkMode .insightAlert.insightAlertDanger .actionButton {
- background: #dc2626;
-}
-
-.darkMode .insightAlert.insightAlertInfo .actionButton:hover {
- background: #0369a1;
-}
-
-.darkMode .insightAlert.insightAlertSuccess .actionButton:hover {
- background: #15803d;
-}
-
-.darkMode .insightAlert.insightAlertWarning .actionButton:hover {
- background: #9a3412;
-}
-
-.darkMode .insightAlert.insightAlertDanger .actionButton:hover {
- background: #b91c1c;
-}
-
-.statusBadge {
- display: inline-block;
- padding: 5px 12px;
- border-radius: 16px;
- font-size: 12px;
- font-weight: 600;
- text-align: center;
- min-width: 80px;
- border: 1px solid transparent;
-}
-
-.statusBadge.excellent {
- background-color: #dcfce7;
- color: #15803d;
- border-color: #bbf7d0;
-}
-
-.statusBadge.good {
- background-color: #fefce8;
- color: #a16207;
- border-color: #fef08a;
-}
-
-.statusBadge.needsImprovement {
- background-color: #fff7ed;
- color: #c2410c;
- border-color: #fed7aa;
-}
-
-.statusBadge.critical {
- background-color: #fee2e2;
- color: #b91c1c;
- border-color: #fecaca;
-}
-
-.darkMode .statusBadge.excellent {
- background-color: #064e3b;
- color: #6ee7b7 !important;
- border-color: #065f46;
-}
-
-.darkMode .statusBadge.good {
- background-color: #78350f;
- color: #fde68a !important;
- border-color: #92400e;
-}
-
-.darkMode .statusBadge.needsImprovement {
- background-color: #7c2d12;
- color: #fed7aa !important;
- border-color: #9a3412;
-}
-
-.darkMode .statusBadge.critical {
- background-color: #7f1d1d;
- color: #fecaca !important;
- border-color: #991b1b;
-}
-
-.visualIndicator {
- font-size: 18px;
- display: inline-block;
-}
-
-.tableContainer {
- overflow-x: auto;
- -webkit-overflow-scrolling: touch;
-}
-
-/* Form Control (replaces Bootstrap form-control) */
-.formControl {
- display: block;
- width: 100%;
- padding: 0.375rem 0.75rem;
- font-size: 1rem;
- font-weight: 400;
- line-height: 1.5;
- color: #333;
- background-color: #fff;
- background-clip: padding-box;
- border: 1px solid #ced4da;
- appearance: none;
- border-radius: 6px;
- transition:
- border-color 0.15s ease-in-out,
- box-shadow 0.15s ease-in-out;
-}
-
-.formControl:focus {
- border-color: #4f46e5;
- outline: 0;
- box-shadow: 0 0 0 3px rgb(79 70 229 / 15%);
-}
-
-.darkMode .formControl {
- background-color: #334155;
- border-color: #475569;
- color: #f1f5f9;
-}
-
-.darkMode .formControl:focus {
- border-color: #818cf8;
- box-shadow: 0 0 0 3px rgb(129 140 248 / 15%);
-}
-
-@media (width <= 768px) {
- .dashboardContainer {
- padding: 10px;
- min-height: auto;
- }
-
- .dashboardHeader {
- margin-bottom: 15px;
- padding: 10px 0;
- }
-
- .dashboardTitle {
- font-size: 20px;
- }
-
- .sectionRow {
- margin-bottom: 20px;
- }
-
- .cardHeader {
- flex-direction: column;
- gap: 15px;
- align-items: flex-start;
- }
-
- .legend {
- justify-content: flex-start;
- gap: 16px;
- }
-
- .insightActions {
- flex-direction: column;
- }
-
- .actionButton {
- width: 100%;
- text-align: center;
- }
-
- .tableCell {
- padding: 12px 8px;
- font-size: 12px;
- }
-
- .tableHeader th {
- padding: 12px 8px;
- font-size: 12px;
- }
-
- .strengthsTable {
- font-size: 12px;
- }
-
- .strengthsTable th,
- .strengthsTable td {
- min-width: 80px;
- white-space: nowrap;
- }
-
- .statusBadge {
- display: inline-block;
- padding: 4px 8px;
- border-radius: 12px;
- font-size: 10px;
- font-weight: 600;
- text-align: center;
- min-width: 60px;
- }
-
- .statusBadge.excellent {
- background-color: #e8f5e8;
- color: #2e7d32;
- }
-
- .statusBadge.good {
- background-color: #fff3e0;
- color: #bf360c;
- }
-
- .statusBadge.needsImprovement {
- background-color: #ffebee;
- color: #b71c1c;
- }
-
- .statusBadge.critical {
- background-color: #fce4ec;
- color: #c2185b;
- }
-
- .progressContainer {
- flex-direction: column;
- gap: 8px;
- }
-
- .progressText {
- text-align: left;
- }
-}
-
-@media (width <= 576px) {
- .dashboardTitle {
- font-size: 24px;
- }
-
- .cardTitle {
- font-size: 18px;
- }
-
- .tableCell {
- padding: 10px 12px;
- font-size: 12px;
- }
-
- .tableHeader th {
- padding: 12px;
- font-size: 13px;
- }
-}
-
-.darkMode .reportCard:hover {
- box-shadow: 0 6px 12px rgb(0 0 0 / 40%);
- transform: translateY(-2px);
-}
-
-.darkMode .strengthsTable tbody tr:hover {
- background-color: #334155;
-}
-
-.darkMode .coloredDropdownItem:hover {
- background-color: rgb(255 255 255 / 8%);
- opacity: 1;
-}
-
-.tabNavigation {
- margin-bottom: 20px;
-}
-
-.navTabs {
- border-bottom: 2px solid #e0e0e0;
- display: flex;
- gap: 4px;
-}
-
-.darkMode .navTabs {
- border-bottom-color: #334155;
-}
-
-.navTabs :global(.nav-link) {
- border: none;
- border-bottom: 3px solid transparent;
- color: #475569;
- font-weight: 600;
- font-size: 14px;
- padding: 12px 20px;
- cursor: pointer;
- transition:
- color 0.2s ease,
- background-color 0.2s ease,
- border-color 0.2s ease,
- box-shadow 0.2s ease;
- background-color: #f1f5f9;
- border-radius: 8px 8px 0 0;
- margin-bottom: -2px;
-}
-
-.darkMode .navTabs :global(.nav-link) {
- color: #94a3b8;
- background-color: #1e293b;
-}
-
-.navTabs :global(.nav-link):hover {
- color: #1e293b;
- background-color: #e2e8f0;
- border-bottom-color: #94a3b8;
-}
-
-.darkMode .navTabs :global(.nav-link):hover {
- color: #f1f5f9;
- background-color: #334155;
- border-bottom-color: #64748b;
-}
-
-.activeTab {
- color: #4f46e5 !important;
- border-bottom-color: #4f46e5 !important;
- background-color: #fff !important;
- box-shadow: 0 -2px 8px rgb(79 70 229 / 15%);
-}
-
-.darkMode .activeTab {
- color: #818cf8 !important;
- border-bottom-color: #818cf8 !important;
- background-color: #0f172a !important;
- box-shadow: 0 -2px 8px rgb(129 140 248 / 20%);
-}
-
-.filterBar {
- background-color: #f8f9fa;
- padding: 15px 20px;
- border-radius: 8px;
- margin-bottom: 20px;
-}
-
-.filterBar label {
- font-weight: 500;
- margin-bottom: 5px;
- display: block;
- color: #333;
-}
-
-.darkMode .filterBar label {
- color: #ccc;
-}
-
-.filterBar select {
- border: 1px solid #ddd;
- border-radius: 6px;
- padding: 8px 12px;
- padding-right: 35px;
- appearance: none;
- background: #fff
- url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E")
- no-repeat right 12px center;
-}
-
-.filterBar select:focus {
- outline: none;
- border-color: #4f46e5;
-}
-
-.filterBar select option {
- background-color: #fff;
- color: #333;
-}
-
-.darkMode .filterBar {
- background-color: #1e293b;
-}
-
-.darkMode .filterBar select {
- background-color: #334155;
- border-color: #475569;
- color: #f1f5f9;
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2394a3b8' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
-}
-
-.darkMode .filterBar select option {
- background-color: #334155;
- color: #f1f5f9;
-}
diff --git a/src/components/EductionPortal/EducatorReports/components/ClassPerformanceView/ClassPerformanceView.jsx b/src/components/EductionPortal/EducatorReports/components/ClassPerformanceView/ClassPerformanceView.jsx
deleted file mode 100644
index 8b52cbafd3..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/ClassPerformanceView/ClassPerformanceView.jsx
+++ /dev/null
@@ -1,500 +0,0 @@
-import React, { useState, useEffect } from 'react';
-import { Row, Col, Card, CardBody, Table } from 'reactstrap';
-import { useSelector } from 'react-redux';
-import styles from './ClassPerformanceView.module.css';
-import MetricCard from '../MetricCard/MetricCard';
-import ReportChart from '../ReportChart/ReportChart';
-import { getStatusClass, getStatusIcon, getStatusText } from '../../utils/statusUtils';
-
-const getClassMockData = classId => {
- const classDataMap = {
- '1': {
- class: { id: '1', name: 'Grade 5A - Mathematics', studentCount: 25, teacher: 'Ms. Johnson' },
- metrics: { classAverage: 78, completionRate: 85, engagementRate: 82, activeLearners: 23 },
- changes: { classAverage: 3.5, completionRate: 7.2, engagementRate: -1.8, activeLearners: 2 },
- subjectPerformance: [
- { subject: 'Arts/Trades', performance: 69, color: '#8b5cf6' },
- { subject: 'Mathematics', performance: 83, color: '#4f46e5' },
- { subject: 'English', performance: 74, color: '#10b981' },
- { subject: 'Science', performance: 68, color: '#f59e0b' },
- { subject: 'Health', performance: 62, color: '#ef4444' },
- { subject: 'Social Studies', performance: 71, color: '#06b6d4' },
- { subject: 'Tech & Innovation', performance: 79, color: '#06b6d4' },
- { subject: 'Values', performance: 87, color: '#84cc16' },
- ],
- teachingStrategies: {
- labels: [
- 'Game Lesson',
- 'Power Play',
- 'Book Smart Exploration',
- 'Core Creative Centered Composition',
- 'Exercised Smart Generation',
- 'Curious Dropout',
- ],
- datasets: [
- {
- label: 'Effectiveness',
- data: [92, 85, 85, 67, 78, 65],
- backgroundColor: ['#10b981', '#10b981', '#10b981', '#3b82f6', '#3b82f6', '#ef4444'],
- },
- ],
- },
- lifeStrategies: {
- labels: [
- 'Everything you do Should Increase Choices',
- 'Ask "what would Jesus do?"',
- 'Choose to trust with observation',
- 'Practice nurturing your emotional intelligence',
- ],
- datasets: [
- {
- label: 'Impact',
- data: [91, 89, 82, 78],
- backgroundColor: ['#10b981', '#10b981', '#fbbf24', '#fbbf24'],
- },
- ],
- },
- insights: [
- {
- type: 'success',
- title: 'Game Lesson Strategy',
- message:
- 'The Game Lesson Strategy has been effective. Students respond well to interactive gameplay.',
- action: 'Analyze Micro Lesson Strategies',
- },
- {
- type: 'warning',
- title: 'Conversation Practice',
- message:
- 'Conversing practice showed room for improvement. Consider focusing more on practical applications.',
- action: 'Learn about application strategies',
- },
- ],
- },
- '2': {
- class: { id: '2', name: 'Grade 6B - Science', studentCount: 28, teacher: 'Mr. Smith' },
- metrics: { classAverage: 85, completionRate: 92, engagementRate: 88, activeLearners: 26 },
- changes: { classAverage: 5.2, completionRate: 8.5, engagementRate: 3.1, activeLearners: 4 },
- subjectPerformance: [
- { subject: 'Arts/Trades', performance: 77, color: '#8b5cf6' },
- { subject: 'Science', performance: 89, color: '#f59e0b' },
- { subject: 'Mathematics', performance: 82, color: '#4f46e5' },
- { subject: 'English', performance: 76, color: '#10b981' },
- { subject: 'Tech & Innovation', performance: 85, color: '#06b6d4' },
- { subject: 'Social Studies', performance: 71, color: '#8b5cf6' },
- { subject: 'Health', performance: 67, color: '#ef4444' },
- { subject: 'Values', performance: 84, color: '#84cc16' },
- ],
- teachingStrategies: {
- labels: [
- 'Power Play',
- 'Experiment Lab',
- 'Nature Walk Discovery',
- 'Tech Exploration',
- 'Group Discussion',
- 'Video Analysis',
- ],
- datasets: [
- {
- label: 'Effectiveness',
- data: [95, 90, 88, 82, 76, 70],
- backgroundColor: ['#10b981', '#10b981', '#10b981', '#10b981', '#3b82f6', '#3b82f6'],
- },
- ],
- },
- lifeStrategies: {
- labels: [
- 'Everything you do Should Increase Choices',
- 'Ask "what would Jesus do?"',
- 'Practice observation skills',
- 'Collaborative learning',
- ],
- datasets: [
- {
- label: 'Impact',
- data: [94, 91, 86, 82],
- backgroundColor: ['#10b981', '#10b981', '#10b981', '#fbbf24'],
- },
- ],
- },
- insights: [
- {
- type: 'success',
- title: 'Excellent Performance',
- message:
- 'Grade 6B is performing above average. The Experiment Lab strategy is highly effective.',
- action: 'Review lesson plans',
- },
- {
- type: 'info',
- title: 'Growing Engagement',
- message: 'Video Analysis is improving. Continue integrating multimedia into lessons.',
- action: 'Explore more videos',
- },
- ],
- },
- '3': {
- class: { id: '3', name: 'Grade 4C - English', studentCount: 22, teacher: 'Mrs. Davis' },
- metrics: { classAverage: 72, completionRate: 78, engagementRate: 68, activeLearners: 18 },
- changes: {
- classAverage: -2.1,
- completionRate: 1.5,
- engagementRate: -5.3,
- activeLearners: -1,
- },
- subjectPerformance: [
- { subject: 'Arts/Trades', performance: 60, color: '#8b5cf6' },
- { subject: 'English', performance: 73, color: '#10b981' },
- { subject: 'Mathematics', performance: 66, color: '#4f46e5' },
- { subject: 'Science', performance: 61, color: '#f59e0b' },
- { subject: 'Social Studies', performance: 58, color: '#8b5cf6' },
- { subject: 'Health', performance: 54, color: '#ef4444' },
- { subject: 'Tech & Innovation', performance: 64, color: '#06b6d4' },
- { subject: 'Values', performance: 77, color: '#84cc16' },
- ],
- teachingStrategies: {
- labels: [
- 'Story Time',
- 'Reading Circle',
- 'Creative Writing',
- 'Peer Review',
- 'Grammar Games',
- 'Silent Reading',
- ],
- datasets: [
- {
- label: 'Effectiveness',
- data: [88, 85, 78, 72, 65, 58],
- backgroundColor: ['#10b981', '#10b981', '#3b82f6', '#3b82f6', '#f59e0b', '#ef4444'],
- },
- ],
- },
- lifeStrategies: {
- labels: [
- 'Everything you do Should Increase Choices',
- 'Ask "what would Jesus do?"',
- 'Practice patience while reading',
- 'Empathy in storytelling',
- ],
- datasets: [
- {
- label: 'Impact',
- data: [85, 80, 72, 68],
- backgroundColor: ['#10b981', '#10b981', '#fbbf24', '#ef4444'],
- },
- ],
- },
- insights: [
- {
- type: 'warning',
- title: 'Below Average Performance',
- message:
- 'Grade 4C needs additional support in English. Consider differentiated instruction.',
- action: 'Review student assessments',
- },
- {
- type: 'info',
- title: 'Strength: Story Time',
- message:
- 'Story Time is highly effective. Increase frequency of narrative-based activities.',
- action: 'Plan story sessions',
- },
- ],
- },
- };
- return classDataMap[classId] || classDataMap['1'];
-};
-
-const ClassPerformanceView = ({ filters }) => {
- const [loading, setLoading] = useState(true);
- const [classData, setClassData] = useState(null);
- const darkMode = useSelector(state => state.theme?.darkMode || false);
-
- useEffect(() => {
- const fetchClassData = async () => {
- setLoading(true);
- await new Promise(resolve => setTimeout(resolve, 1000));
- setClassData(getClassMockData(filters.classId));
- setLoading(false);
- };
-
- if (filters.classId) {
- fetchClassData();
- } else {
- setClassData(null);
- setLoading(false);
- }
- }, [filters.classId, filters.subject, filters.dateRange]);
-
- if (!filters.classId) {
- return (
-
-
-
-
Select a Class
-
- Choose a class from the filter above to view class performance analytics and insights.
-
-
-
- );
- }
-
- return (
-
- {/* Key Metrics Row */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Strengths & Gaps by Subject */}
-
-
-
-
-
Strengths & Gaps by Subject
-
-
- {loading && (
-
-
-
Loading subject performance...
-
- )}
-
- {!loading && (
-
-
-
-
- Subject
- Performance
- Status
- Visual Indicator
-
-
-
- {classData?.subjectPerformance?.map(item => (
-
- {item.subject}
-
-
-
-
{item.performance}%
-
-
-
-
- {getStatusText(item.performance)}
-
-
-
-
- {getStatusIcon(item.performance)}
-
-
-
- ))}
-
-
-
- )}
-
-
-
-
- {/* Teaching Strategies Effectiveness */}
-
-
-
-
-
Effectiveness of Teaching Strategies
-
-
- {loading ? (
-
-
-
Loading strategies data...
-
- ) : (
-
-
-
-
-
- Highly Effective (85%)
-
-
-
- Effective (70%)
-
-
-
- Needs Improvement (65%)
-
-
-
- )}
-
-
-
-
- {/* Impact of Life Strategies */}
-
-
-
-
-
Impact of Life Strategies
-
-
- {loading ? (
-
-
-
Loading impact data...
-
- ) : (
-
-
-
-
-
- Very Good (89%)
-
-
-
- Good Impact (76%)
-
-
-
- Moderate Impact (76%)
-
-
-
- Low Impact (76%)
-
-
-
- )}
-
-
-
-
-
- {/* Actionable Insights */}
-
-
-
-
- Actionable Insight
-
- {loading ? (
-
-
-
Generating insights...
-
- ) : (
- classData?.insights.map(insight => (
-
-
-
- {insight.title}:
-
-
{insight.message}
- {insight.action && (
-
-
- {insight.action}
-
-
- )}
-
-
- ))
- )}
-
-
-
-
-
-
- );
-};
-
-export default ClassPerformanceView;
diff --git a/src/components/EductionPortal/EducatorReports/components/ClassPerformanceView/ClassPerformanceView.module.css b/src/components/EductionPortal/EducatorReports/components/ClassPerformanceView/ClassPerformanceView.module.css
deleted file mode 100644
index 0dcc1c1560..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/ClassPerformanceView/ClassPerformanceView.module.css
+++ /dev/null
@@ -1,793 +0,0 @@
-/* ClassPerformanceView.module.css */
-
-.classPerformance {
- padding: 1.5rem;
- transition: all 0.3s ease;
- animation: fade-in 0.5s ease-out;
-}
-
-.classPerformance.darkMode {
- color: #fff;
-}
-
-/* Empty State */
-.emptyState {
- display: flex;
- align-items: center;
- justify-content: center;
- min-height: 400px;
- padding: 2rem;
-}
-
-.emptyState.darkMode {
- color: #fff;
-}
-
-.emptyContent {
- text-align: center;
- max-width: 400px;
-}
-
-.emptyContent i {
- font-size: 4rem;
- color: #d1d5db;
- margin-bottom: 1rem;
-}
-
-.loading i {
- font-size: 2rem;
- margin-bottom: 1rem;
-}
-
-.loading p {
- margin: 0;
- font-weight: 500;
-}
-
-.darkMode .emptyContent i {
- color: #6b7280;
-}
-
-.emptyContent h3 {
- font-size: 1.5rem;
- font-weight: 600;
- color: #374151;
- margin-bottom: 0.5rem;
-}
-
-.darkMode .emptyContent h3 {
- color: #f9fafb;
-}
-
-.emptyContent p {
- color: #6b7280;
- font-size: 1rem;
- line-height: 1.6;
- margin: 0;
-}
-
-.darkMode .emptyContent p {
- color: #9ca3af;
-}
-
-/* Metrics Row */
-.metricsRow {
- margin-bottom: 2rem;
-}
-
-.metricCol {
- margin-bottom: 1rem;
-}
-
-/* Report Cards */
-.reportCard {
- background-color: #fff;
- border: 1px solid #e5e7eb;
- border-radius: 12px;
- box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
- margin-bottom: 1.5rem;
- transition: all 0.3s ease;
-}
-
-/* Reactstrap
wrapper */
-
-.darkMode .cardBody {
- background-color: #0f172a;
-}
-
-.reportCard.darkMode {
- background-color: #1f2937;
- border-color: #374151;
- box-shadow: 0 1px 3px rgb(0 0 0 / 30%);
-}
-
-.reportCard:focus-within {
- outline: 2px solid #4f46e5;
- outline-offset: 2px;
-}
-
-.reportCard:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
-}
-
-.darkMode .reportCard:focus-within {
- outline-color: #818cf8;
-}
-
-.darkMode .reportCard:hover {
- box-shadow: 0 4px 12px rgb(0 0 0 / 40%);
-}
-
-/* Card Headers */
-.cardHeader {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 1.5rem;
- padding-bottom: 1rem;
- border-bottom: 1px solid #e5e7eb;
-}
-
-.darkMode .cardHeader {
- border-bottom-color: #374151;
-}
-
-.cardTitle {
- font-size: 1.25rem;
- font-weight: 600;
- color: #111827;
- margin: 0;
-}
-
-.darkMode .cardTitle {
- color: #f9fafb;
-}
-
-/* Chart Styles */
-.chartCol {
- margin-bottom: 30px;
-}
-
-/* Table Styles (match ReportsView) */
-.tableContainer {
- overflow-x: auto;
- -webkit-overflow-scrolling: touch;
-}
-
-.performanceTable {
- margin: 0;
- font-size: 0.875rem;
-}
-
-.performanceTable th {
- background-color: #f9fafb;
- color: #374151;
- font-weight: 600;
- border: none;
- padding: 1rem 0.75rem;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- font-size: 0.75rem;
-}
-
-.darkMode .performanceTable th {
- background-color: #374151;
- color: #d1d5db;
-}
-
-.performanceTable td {
- padding: 1rem 0.75rem;
- border-top: 1px solid #e5e7eb;
- vertical-align: middle;
-}
-
-.darkMode .performanceTable td {
- border-top-color: #374151;
- color: #d1d5db;
-}
-
-.performanceTable tbody tr:hover {
- background-color: #f9fafb;
-}
-
-.darkMode .performanceTable tbody tr:hover {
- background-color: #374151;
-}
-
-.subjectCell {
- font-weight: 500;
- color: #111827;
-}
-
-.darkMode .subjectCell {
- color: #f9fafb;
-}
-
-.performanceCell {
- font-size: 0.875rem;
-}
-
-.performanceBar {
- position: relative;
- height: 20px;
- background-color: #e5e7eb;
- border-radius: 10px;
- overflow: hidden;
-}
-
-.darkMode .performanceBar {
- background-color: rgb(255 255 255 / 12%);
-}
-
-.performanceFill {
- height: 100%;
- border-radius: 10px;
- transition: width 0.6s ease;
-}
-
-.performanceText {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- font-size: 12px;
- font-weight: 600;
- color: #111827;
- text-shadow: 0 1px 1px rgb(255 255 255 / 65%);
-}
-
-.darkMode .performanceText {
- color: #f9fafb;
- text-shadow: 0 1px 1px rgb(0 0 0 / 60%);
-}
-
-.visualCell {
- text-align: center;
-}
-
-.chartContainer {
- position: relative;
- margin: 20px 0;
-}
-
-.legend {
- display: flex;
- flex-wrap: wrap;
- gap: 1rem;
- justify-content: center;
- margin-top: 1rem;
- padding-top: 1rem;
- border-top: 1px solid #e5e7eb;
-}
-
-.darkMode .legend {
- border-top-color: #374151;
-}
-
-.legendItem {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- font-size: 0.875rem;
- color: #374151;
-}
-
-.darkMode .legendItem {
- color: #d1d5db;
-}
-
-.legendColor {
- width: 12px;
- height: 12px;
- border-radius: 3px;
- display: inline-block;
-}
-
-.legendColor.highlyEffective {
- background-color: #10b981;
-}
-
-.legendColor.effective {
- background-color: #3b82f6;
-}
-
-.legendColor.needsImprovement {
- background-color: #ef4444;
-}
-
-.legendColor.veryGood {
- background-color: #10b981;
-}
-
-.legendColor.good {
- background-color: #10b981;
-}
-
-.legendColor.moderate {
- background-color: #fbbf24;
-}
-
-.legendColor.low {
- background-color: #fbbf24;
-}
-
-/* Loading States */
-.loading {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: 2rem;
- color: #6b7280;
-}
-
-.darkMode .loading {
- color: #9ca3af;
-}
-
-/* Insights Section */
-.insightsContainer {
- margin-top: 1rem;
-}
-
-.insightAlert {
- border: none;
- border-radius: 8px;
- margin-bottom: 1rem;
- padding: 0.75rem 1rem;
- box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
-}
-
-/* Alert variants — match ReportsView colors exactly */
-.insightAlert.insightAlertInfo {
- background-color: #d1ecf1;
- border: 1px solid #bee5eb;
- color: #0c5460;
-}
-
-.insightAlert.insightAlertSuccess {
- background-color: #d4edda;
- border: 1px solid #c3e6cb;
- color: #155724;
-}
-
-.insightAlert.insightAlertWarning {
- background-color: #fff3cd;
- border: 1px solid #ffeeba;
- color: #856404;
-}
-
-.insightAlert.insightAlertDanger {
- background-color: #f8d7da;
- border: 1px solid #f5c6cb;
- color: #721c24;
-}
-
-.insightAlert.insightAlertPrimary {
- background-color: #cce5ff;
- border: 1px solid #b8daff;
- color: #004085;
-}
-
-.darkMode .insightAlert {
- color: #e2e8f0;
- background-color: #1e293b;
- box-shadow: 0 10px 24px rgb(0 0 0 / 35%);
- border: 1px solid #334155;
-}
-
-.darkMode .insightAlert.insightAlertInfo {
- background-color: #172554;
- border-color: #1e40af;
- color: #93c5fd;
-}
-
-.darkMode .insightAlert.insightAlertSuccess {
- background-color: #052e16;
- border-color: #166534;
- color: #86efac;
-}
-
-.darkMode .insightAlert.insightAlertWarning {
- background-color: #451a03;
- border-color: #92400e;
- color: #fde68a;
-}
-
-.darkMode .insightAlert.insightAlertDanger {
- background-color: #450a0a;
- border-color: #991b1b;
- color: #fca5a5;
-}
-
-.darkMode .insightAlert.insightAlertPrimary {
- background-color: #172554;
- border-color: #1e40af;
- color: #93c5fd;
-}
-
-.insightAlert:last-child {
- margin-bottom: 0;
-}
-
-.insightContent {
- line-height: 1.6;
-}
-
-.insightHeader {
- margin-bottom: 0.5rem;
-}
-
-.insightHeader strong {
- font-weight: 600;
- font-size: 1rem;
-}
-
-.insightMessage {
- margin-bottom: 1rem;
- color: #374151;
-}
-
-.darkMode .insightMessage {
- color: #d1d5db;
-}
-
-.insightAction {
- display: flex;
- justify-content: flex-end;
- margin-top: 1rem;
- padding-top: 1rem;
- border-top: 1px solid rgb(0 0 0 / 10%);
-}
-
-.darkMode .insightAction {
- border-top-color: rgb(255 255 255 / 10%);
-}
-
-.actionButton {
- background-color: #4f46e5;
- color: #fff;
- border: none;
- border-radius: 6px;
- padding: 0.5rem 1rem;
- font-size: 0.875rem;
- font-weight: 500;
- cursor: pointer;
- transition: all 0.2s ease;
- text-decoration: none;
-}
-
-.actionButton:hover {
- background-color: #3730a3;
- transform: translateY(-1px);
- box-shadow: 0 2px 4px rgb(79 70 229 / 30%);
-}
-
-.actionButton:active {
- transform: translateY(0);
-}
-
-.actionButton:focus {
- outline: 2px solid #4f46e5;
- outline-offset: 2px;
-}
-
-.darkMode .actionButton {
- background-color: #4338ca;
-}
-
-/* Keep buttons high-contrast on colored alerts */
-.insightAlertInfo .actionButton {
- background: #0ea5e9;
-}
-
-.insightAlertSuccess .actionButton {
- background: #22c55e;
-}
-
-.insightAlertWarning .actionButton {
- background: #b45309;
- color: #fff;
-}
-
-.insightAlertDanger .actionButton {
- background: #ef4444;
-}
-
-.insightAlertInfo .actionButton:hover {
- background: #0284c7;
-}
-
-.insightAlertSuccess .actionButton:hover {
- background: #16a34a;
-}
-
-.insightAlertWarning .actionButton:hover {
- background: #9a3412;
-}
-
-.insightAlertDanger .actionButton:hover {
- background: #dc2626;
-}
-
-.darkMode .actionButton:hover {
- background-color: #3730a3;
-}
-
-.darkMode .actionButton:focus {
- outline-color: #818cf8;
-}
-
-.darkMode .insightAlert .actionButton {
- color: #fff;
-}
-
-.darkMode .insightAlert.insightAlertInfo .actionButton {
- background: #0284c7;
-}
-
-.darkMode .insightAlert.insightAlertSuccess .actionButton {
- background: #16a34a;
-}
-
-.darkMode .insightAlert.insightAlertWarning .actionButton {
- background: #b45309;
-}
-
-.darkMode .insightAlert.insightAlertDanger .actionButton {
- background: #dc2626;
-}
-
-.darkMode .insightAlert.insightAlertInfo .actionButton:hover {
- background: #0369a1;
-}
-
-.darkMode .insightAlert.insightAlertSuccess .actionButton:hover {
- background: #15803d;
-}
-
-.darkMode .insightAlert.insightAlertWarning .actionButton:hover {
- background: #9a3412;
-}
-
-.darkMode .insightAlert.insightAlertDanger .actionButton:hover {
- background: #b91c1c;
-}
-
-/* Responsive Design */
-@media (width <= 992px) {
- .classPerformance {
- padding: 1rem;
- }
-
- .metricsRow {
- margin-bottom: 1.5rem;
- }
-
- .chartCol {
- margin-bottom: 1.5rem;
- }
-
- .legend {
- gap: 0.75rem;
- }
-
- .legendItem {
- font-size: 0.8rem;
- }
-}
-
-@media (width <= 768px) {
- .classPerformance {
- padding: 0.5rem;
- }
-
- .reportCard {
- margin: 0 -0.5rem 1.5rem;
- }
-
- .cardTitle {
- font-size: 1.125rem;
- }
-
- .legend {
- flex-direction: column;
- align-items: center;
- gap: 0.5rem;
- }
-
- .legendItem {
- justify-content: center;
- }
-
- .metricCol {
- margin-bottom: 1rem;
- }
-
- .insightAction {
- justify-content: center;
- }
-
- .actionButton {
- width: 100%;
- max-width: 200px;
- }
-}
-
-@media (width <= 480px) {
- .emptyContent i {
- font-size: 3rem;
- }
-
- .emptyContent h3 {
- font-size: 1.25rem;
- }
-
- .emptyContent p {
- font-size: 0.9rem;
- }
-
- .cardTitle {
- font-size: 1rem;
- }
-
- .legendColor {
- width: 10px;
- height: 10px;
- }
-
- .legendItem {
- font-size: 0.75rem;
- }
-
- .actionButton {
- font-size: 0.8rem;
- padding: 0.4rem 0.8rem;
- }
-}
-
-@keyframes fade-in {
- from {
- opacity: 0;
- transform: translateY(10px);
- }
-
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-/* Print Styles */
-@media print {
- .classPerformance {
- background: white !important;
- color: black !important;
- }
-
- .reportCard {
- background: white !important;
- box-shadow: none;
- border: 1px solid #ccc;
- break-inside: avoid;
- margin-bottom: 1rem;
- }
-
- .legend {
- display: none;
- }
-
- .insightAlert {
- background: transparent !important;
- border: 1px solid currentcolor;
- }
-
- .actionButton {
- background: transparent !important;
- color: black !important;
- border: 1px solid black;
- }
-}
-
-/* Chart-specific adjustments */
-.chartContainer canvas {
- max-height: 350px;
-}
-
-/* Strategy effectiveness colors for consistency */
-.strategyBar.highlyEffective {
- background-color: #10b981;
-}
-
-.strategyBar.effective {
- background-color: #3b82f6;
-}
-
-.strategyBar.needsImprovement {
- background-color: #ef4444;
-}
-
-/* Impact colors for life strategies */
-.impactBar.veryGood {
- background-color: #10b981;
-}
-
-.impactBar.good {
- background-color: #10b981;
-}
-
-.impactBar.moderate {
- background-color: #fbbf24;
-}
-
-.impactBar.low {
- background-color: #fbbf24;
-}
-
-/* Status Badge Styles */
-.statusBadge {
- display: inline-block;
- padding: 5px 12px;
- border-radius: 16px;
- font-size: 12px;
- font-weight: 600;
- text-align: center;
- min-width: 80px;
- border: 1px solid transparent;
-}
-
-.statusBadge.excellent {
- background-color: #dcfce7;
- color: #15803d;
- border-color: #bbf7d0;
-}
-
-.statusBadge.good {
- background-color: #fefce8;
- color: #a16207;
- border-color: #fef08a;
-}
-
-.statusBadge.needsImprovement,
-.statusBadge.needs-improvement {
- background-color: #fff7ed;
- color: #c2410c;
- border-color: #fed7aa;
-}
-
-.statusBadge.critical {
- background-color: #fee2e2;
- color: #b91c1c;
- border-color: #fecaca;
-}
-
-.darkMode .statusBadge.excellent {
- background-color: #064e3b;
- color: #6ee7b7 !important;
- border-color: #065f46;
-}
-
-.darkMode .statusBadge.good {
- background-color: #78350f;
- color: #fde68a !important;
- border-color: #92400e;
-}
-
-.darkMode .statusBadge.needsImprovement,
-.darkMode .statusBadge.needs-improvement {
- background-color: #7c2d12;
- color: #fed7aa !important;
- border-color: #9a3412;
-}
-
-.darkMode .statusBadge.critical {
- background-color: #7f1d1d;
- color: #fecaca !important;
- border-color: #991b1b;
-}
-
-.visualIndicator {
- font-size: 18px;
- display: inline-block;
-}
diff --git a/src/components/EductionPortal/EducatorReports/components/IndividualReportView/IndividualReportView.jsx b/src/components/EductionPortal/EducatorReports/components/IndividualReportView/IndividualReportView.jsx
deleted file mode 100644
index c30c5138e2..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/IndividualReportView/IndividualReportView.jsx
+++ /dev/null
@@ -1,465 +0,0 @@
-import React, { useState, useEffect } from 'react';
-import { Row, Col, Card, CardBody, Table } from 'reactstrap';
-import { useSelector } from 'react-redux';
-import styles from './IndividualReportView.module.css';
-import MetricCard from '../MetricCard/MetricCard';
-import ReportChart from '../ReportChart/ReportChart';
-import { getStatusClass, getStatusIcon, getStatusText } from '../../utils/statusUtils';
-
-const getStudentMockData = studentId => {
- const studentDataMap = {
- 1: {
- student: { id: '1', name: 'Alex Johnson', grade: '5A', avatar: null },
- metrics: {
- averageScore: 82,
- lessonsCompleted: 45,
- engagementRate: 78,
- timeSpent: '24h 30min',
- },
- changes: { averageScore: 5.2, lessonsCompleted: 12.5, engagementRate: -2.1, timeSpent: 8.3 },
- subjectPerformance: [
- { subject: 'Arts/Trades', performance: 85 },
- { subject: 'English', performance: 88 },
- { subject: 'Health', performance: 65 },
- { subject: 'Mathematics', performance: 92 },
- { subject: 'Science', performance: 78 },
- { subject: 'Social Studies', performance: 71 },
- { subject: 'Tech & Innovation', performance: 89 },
- { subject: 'Values', performance: 95 },
- ],
- performanceTrend: {
- labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],
- datasets: [
- {
- label: 'Math',
- data: [78, 82, 85, 88],
- borderColor: '#4f46e5',
- backgroundColor: '#4f46e520',
- },
- {
- label: 'English',
- data: [72, 75, 78, 82],
- borderColor: '#10b981',
- backgroundColor: '#10b98120',
- },
- {
- label: 'Science',
- data: [68, 70, 74, 78],
- borderColor: '#f59e0b',
- backgroundColor: '#f59e0b20',
- },
- ],
- },
- insights: [
- {
- type: 'success',
- title: 'Strong Performance',
- message: 'No concerns need to be addressed for this student.',
- },
- {
- type: 'info',
- title: 'Actionable Insight',
- message:
- 'Student shows consistent improvement in Mathematics. Consider advancing to more challenging problems.',
- },
- ],
- },
- 2: {
- student: { id: '2', name: 'Sarah Williams', grade: '5A', avatar: null },
- metrics: {
- averageScore: 91,
- lessonsCompleted: 52,
- engagementRate: 88,
- timeSpent: '32h 15min',
- },
- changes: { averageScore: 8.5, lessonsCompleted: 15.2, engagementRate: 5.3, timeSpent: 12.1 },
- subjectPerformance: [
- { subject: 'Arts/Trades', performance: 92 },
- { subject: 'English', performance: 95 },
- { subject: 'Health', performance: 78 },
- { subject: 'Mathematics', performance: 88 },
- { subject: 'Science', performance: 85 },
- { subject: 'Social Studies', performance: 82 },
- { subject: 'Tech & Innovation', performance: 75 },
- { subject: 'Values', performance: 98 },
- ],
- performanceTrend: {
- labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],
- datasets: [
- {
- label: 'Math',
- data: [80, 84, 87, 91],
- borderColor: '#4f46e5',
- backgroundColor: '#4f46e520',
- },
- {
- label: 'English',
- data: [85, 88, 92, 95],
- borderColor: '#10b981',
- backgroundColor: '#10b98120',
- },
- {
- label: 'Science',
- data: [78, 80, 83, 85],
- borderColor: '#f59e0b',
- backgroundColor: '#f59e0b20',
- },
- ],
- },
- insights: [
- {
- type: 'success',
- title: 'Top Performer',
- message: 'Sarah is performing in the top 10% of the class across all subjects.',
- },
- {
- type: 'info',
- title: 'Recommendation',
- message: 'Consider advanced placement or enrichment activities in English and Values.',
- },
- ],
- },
- 3: {
- student: { id: '3', name: 'Michael Brown', grade: '5A', avatar: null },
- metrics: {
- averageScore: 68,
- lessonsCompleted: 32,
- engagementRate: 62,
- timeSpent: '18h 45min',
- },
- changes: {
- averageScore: -3.2,
- lessonsCompleted: -5.1,
- engagementRate: -8.4,
- timeSpent: -4.2,
- },
- subjectPerformance: [
- { subject: 'Arts/Trades', performance: 72 },
- { subject: 'English', performance: 65 },
- { subject: 'Health', performance: 58 },
- { subject: 'Mathematics', performance: 75 },
- { subject: 'Science', performance: 70 },
- { subject: 'Social Studies', performance: 62 },
- { subject: 'Tech & Innovation', performance: 78 },
- { subject: 'Values', performance: 68 },
- ],
- performanceTrend: {
- labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],
- datasets: [
- {
- label: 'Math',
- data: [78, 76, 75, 72],
- borderColor: '#4f46e5',
- backgroundColor: '#4f46e520',
- },
- {
- label: 'English',
- data: [70, 68, 66, 62],
- borderColor: '#10b981',
- backgroundColor: '#10b98120',
- },
- {
- label: 'Science',
- data: [72, 71, 70, 68],
- borderColor: '#f59e0b',
- backgroundColor: '#f59e0b20',
- },
- ],
- },
- insights: [
- {
- type: 'warning',
- title: 'Needs Support',
- message: 'Michael is struggling in English and Health. Consider additional tutoring.',
- },
- {
- type: 'info',
- title: 'Strength Area',
- message:
- 'Tech & Innovation shows promise. Use this as engagement opportunity for other subjects.',
- },
- ],
- },
- 4: {
- student: { id: '4', name: 'Emily Davis', grade: '5A', avatar: null },
- metrics: {
- averageScore: 76,
- lessonsCompleted: 41,
- engagementRate: 72,
- timeSpent: '21h 20min',
- },
- changes: { averageScore: 2.1, lessonsCompleted: 8.3, engagementRate: 1.2, timeSpent: 3.5 },
- subjectPerformance: [
- { subject: 'Arts/Trades', performance: 80 },
- { subject: 'English', performance: 78 },
- { subject: 'Health', performance: 72 },
- { subject: 'Mathematics', performance: 68 },
- { subject: 'Science', performance: 82 },
- { subject: 'Social Studies', performance: 75 },
- { subject: 'Tech & Innovation', performance: 85 },
- { subject: 'Values', performance: 80 },
- ],
- performanceTrend: {
- labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],
- datasets: [
- {
- label: 'Math',
- data: [65, 66, 67, 68],
- borderColor: '#4f46e5',
- backgroundColor: '#4f46e520',
- },
- {
- label: 'English',
- data: [74, 76, 77, 78],
- borderColor: '#10b981',
- backgroundColor: '#10b98120',
- },
- {
- label: 'Science',
- data: [78, 80, 81, 82],
- borderColor: '#f59e0b',
- backgroundColor: '#f59e0b20',
- },
- ],
- },
- insights: [
- {
- type: 'success',
- title: 'Improving',
- message: 'Emily shows consistent improvement across most subjects.',
- },
- {
- type: 'info',
- title: 'Focus Area',
- message: 'Mathematics could benefit from additional practice. Excel in Science and Tech!',
- },
- ],
- },
- };
- return studentDataMap[studentId] || studentDataMap['1'];
-};
-
-const IndividualReportView = ({ filters }) => {
- const [loading, setLoading] = useState(true);
- const [studentData, setStudentData] = useState(null);
- const darkMode = useSelector(state => state.theme?.darkMode || false);
-
- useEffect(() => {
- const fetchStudentData = async () => {
- setLoading(true);
- await new Promise(resolve => setTimeout(resolve, 1000));
- setStudentData(getStudentMockData(filters.studentId));
- setLoading(false);
- };
-
- if (filters.studentId) {
- fetchStudentData();
- } else {
- setStudentData(null);
- setLoading(false);
- }
- }, [filters.studentId, filters.subject, filters.dateRange]);
-
- const getStatusBadgeClass = performance => {
- const status = getStatusClass(performance);
- const statusMap = {
- excellent: styles.statusBadgeExcellent,
- good: styles.statusBadgeGood,
- needsImprovement: styles.statusBadgeNeedsImprovement,
- critical: styles.statusBadgeCritical,
- };
- return statusMap[status] || '';
- };
-
- const formatPerformance = performance => `${Math.round(performance)}%`;
-
- if (!filters.studentId) {
- return (
-
-
-
-
Select a Student
-
Choose a student from the filter above to view their individual performance report.
-
-
- );
- }
-
- return (
-
-
- {/* Key Metrics Row */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Strengths & Gaps Table */}
-
-
-
-
-
Strengths & Gaps by Subject
-
- All Subjects
-
-
-
- {loading ? (
-
-
-
Loading student data...
-
- ) : (
-
-
-
-
- Subject
- Performance
- Status
- Visual Indicator
-
-
-
- {studentData?.subjectPerformance.map(item => (
-
- {item.subject}
-
- {formatPerformance(item.performance)}
-
-
-
- {getStatusText(item.performance)}
-
-
-
-
- {getStatusIcon(item.performance)}
-
-
-
- ))}
-
-
-
- )}
-
-
-
-
- {/* Performance Trend Chart */}
-
-
-
- Performance Trend by Subject Over Time
-
- {loading ? (
-
-
-
Loading chart data...
-
- ) : (
-
- )}
-
-
-
-
-
-
- {/* Actionable Insights */}
-
-
-
-
- Actionable Insight
-
- {loading ? (
-
-
-
Generating insights...
-
- ) : (
- studentData?.insights.map(insight => (
-
-
- {insight.title}: {insight.message}
-
-
- ))
- )}
-
-
-
-
-
-
-
- );
-};
-
-export default IndividualReportView;
diff --git a/src/components/EductionPortal/EducatorReports/components/IndividualReportView/IndividualReportView.module.css b/src/components/EductionPortal/EducatorReports/components/IndividualReportView/IndividualReportView.module.css
deleted file mode 100644
index 135116c9b8..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/IndividualReportView/IndividualReportView.module.css
+++ /dev/null
@@ -1,590 +0,0 @@
-/* IndividualReportView.module.css */
-
-.individualReport {
- padding: 1.5rem;
- transition: all 0.3s ease;
- animation: fade-in 0.5s ease-out;
-}
-
-.darkMode .individualReport {
- color: #fff;
-}
-
-/* Empty State */
-.emptyState {
- display: flex;
- align-items: center;
- justify-content: center;
- min-height: 400px;
- padding: 2rem;
-}
-
-.emptyState.darkMode {
- color: #fff;
-}
-
-.emptyContent {
- text-align: center;
- max-width: 400px;
-}
-
-.emptyContent i {
- font-size: 4rem;
- color: #d1d5db;
- margin-bottom: 1rem;
-}
-
-.chartLoading i {
- font-size: 2rem;
- margin-bottom: 1rem;
-}
-
-.chartLoading p {
- margin: 0;
- font-weight: 500;
-}
-
-.loading i {
- font-size: 2rem;
- margin-bottom: 1rem;
-}
-
-.loading p {
- margin: 0;
- font-weight: 500;
-}
-
-.darkMode .emptyContent i {
- color: #6b7280;
-}
-
-.emptyContent h3 {
- font-size: 1.5rem;
- font-weight: 600;
- color: #374151;
- margin-bottom: 0.5rem;
-}
-
-.darkMode .emptyContent h3 {
- color: #f9fafb;
-}
-
-.emptyContent p {
- color: #6b7280;
- font-size: 1rem;
- line-height: 1.6;
- margin: 0;
-}
-
-.darkMode .emptyContent p {
- color: #9ca3af;
-}
-
-/* Metrics Row */
-.metricsRow {
- margin-bottom: 2rem;
-}
-
-.metricCol {
- margin-bottom: 1rem;
-}
-
-/* Report Cards */
-.reportCard {
- background-color: #fff;
- border: 1px solid #e5e7eb;
- border-radius: 12px;
- box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
- margin-bottom: 1.5rem;
- transition: all 0.3s ease;
-}
-
-.darkMode .reportCard {
- background-color: #1f2937;
- border-color: #374151;
- box-shadow: 0 1px 3px rgb(0 0 0 / 30%);
-}
-
-.reportCard:focus-within {
- outline: 2px solid #4f46e5;
- outline-offset: 2px;
-}
-
-.reportCard:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
-}
-
-.darkMode .reportCard:focus-within {
- outline-color: #818cf8;
-}
-
-.darkMode .reportCard:hover {
- box-shadow: 0 4px 12px rgb(0 0 0 / 40%);
-}
-
-/* Card Headers */
-.cardHeader {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 1.5rem;
- padding-bottom: 1rem;
- border-bottom: 1px solid #e5e7eb;
-}
-
-.darkMode .cardHeader {
- border-bottom-color: #374151;
-}
-
-.cardTitle {
- font-size: 1.25rem;
- font-weight: 600;
- color: #111827;
- margin: 0;
-}
-
-.darkMode .cardTitle {
- color: #f9fafb;
-}
-
-.headerActions {
- display: flex;
- align-items: center;
- gap: 1rem;
-}
-
-.subjectCount {
- font-size: 0.875rem;
- color: #374151;
- background-color: #f3f4f6;
- padding: 0.25rem 0.75rem;
- border-radius: 20px;
- font-weight: 500;
-}
-
-.darkMode .subjectCount {
- color: #d1d5db;
- background-color: #374151;
-}
-
-/* Table Styles */
-.tableContainer {
- overflow-x: auto;
-}
-
-.performanceTable {
- margin: 0;
- font-size: 0.875rem;
-}
-
-.performanceTable th {
- background-color: #f9fafb;
- color: #374151;
- font-weight: 600;
- border: none;
- padding: 1rem 0.75rem;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- font-size: 0.75rem;
-}
-
-.darkMode .performanceTable th {
- background-color: #374151;
- color: #d1d5db;
-}
-
-.performanceTable td {
- padding: 1rem 0.75rem;
- border-top: 1px solid #e5e7eb;
- vertical-align: middle;
-}
-
-.darkMode .performanceTable td {
- border-top-color: #374151;
- color: #d1d5db;
-}
-
-.performanceTable tbody tr:hover {
- background-color: #f9fafb;
-}
-
-.darkMode .performanceTable tbody tr:hover {
- background-color: #374151;
-}
-
-.subjectCell {
- font-weight: 500;
- color: #111827;
-}
-
-.darkMode .subjectCell {
- color: #f9fafb;
-}
-
-.performanceCell {
- font-size: 0.875rem;
-}
-
-.performanceCell strong {
- color: #4f46e5;
- font-weight: 600;
-}
-
-.insightContent strong {
- font-weight: 600;
-}
-
-.darkMode .performanceCell strong {
- color: #818cf8;
-}
-
-/* Status Badges */
-.statusBadge {
- display: inline-block;
- padding: 5px 12px;
- border-radius: 16px;
- font-size: 12px;
- font-weight: 600;
- text-align: center;
- min-width: 80px;
- border: 1px solid transparent;
-}
-
-/* Visual Indicators */
-.visualCell {
- text-align: center;
-}
-
-.visualIndicator {
- font-size: 18px;
- display: inline-block;
-}
-
-/* Chart Styles */
-.chartCol {
- margin-bottom: 30px;
-}
-
-.darkMode .cardBody {
- background-color: #0f172a !important;
-}
-
-.chartContainer {
- height: 300px;
- position: relative;
- margin: 20px 0 60px;
-}
-
-.chartLoading {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- height: 200px;
- color: #6b7280;
-}
-
-.darkMode .chartLoading {
- color: #9ca3af;
-}
-
-/* Loading States */
-.loading {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: 2rem;
- color: #6b7280;
-}
-
-.darkMode .loading {
- color: #9ca3af;
-}
-
-/* Insights Section */
-.insightsContainer {
- margin-top: 1rem;
-}
-
-.insightAlert {
- border: none;
- border-radius: 8px;
- margin-bottom: 1rem;
- padding: 0.75rem 1rem;
- box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
-}
-
-/* Insight alert variants — match ReportsView colors exactly */
-.insightAlert.insightAlertInfo {
- background-color: #d1ecf1;
- border: 1px solid #bee5eb;
- color: #0c5460;
-}
-
-.insightAlert.insightAlertSuccess {
- background-color: #d4edda;
- border: 1px solid #c3e6cb;
- color: #155724;
-}
-
-.insightAlert.insightAlertWarning {
- background-color: #fff3cd;
- border: 1px solid #ffeeba;
- color: #856404;
-}
-
-.insightAlert.insightAlertDanger {
- background-color: #f8d7da;
- border: 1px solid #f5c6cb;
- color: #721c24;
-}
-
-.insightAlert.insightAlertPrimary {
- background-color: #cce5ff;
- border: 1px solid #b8daff;
- color: #004085;
-}
-
-.darkMode .insightAlert {
- color: #e2e8f0;
- background-color: #1e293b;
- box-shadow: 0 10px 24px rgb(0 0 0 / 35%);
- border: 1px solid #334155;
-}
-
-.darkMode .insightAlert.insightAlertInfo {
- background-color: #172554;
- border-color: #1e40af;
- color: #93c5fd;
-}
-
-.darkMode .insightAlert.insightAlertSuccess {
- background-color: #052e16;
- border-color: #166534;
- color: #86efac;
-}
-
-.darkMode .insightAlert.insightAlertWarning {
- background-color: #451a03;
- border-color: #92400e;
- color: #fde68a;
-}
-
-.darkMode .insightAlert.insightAlertDanger {
- background-color: #450a0a;
- border-color: #991b1b;
- color: #fca5a5;
-}
-
-.darkMode .insightAlert.insightAlertPrimary {
- background-color: #172554;
- border-color: #1e40af;
- color: #93c5fd;
-}
-
-.insightAlert:last-child {
- margin-bottom: 0;
-}
-
-.insightContent {
- line-height: 1.6;
-}
-
-.darkMode .insightContent {
- color: #e5e7eb;
-}
-
-.darkMode .insightContent strong {
- color: #f9fafb;
-}
-
-/* Responsive Design */
-@media (width <= 992px) {
- .individualReport {
- padding: 1rem;
- }
-
- .metricsRow {
- margin-bottom: 1.5rem;
- }
-
- .chartCol,
- .tableCol {
- margin-bottom: 1.5rem;
- }
-
- .cardHeader {
- flex-direction: column;
- align-items: flex-start;
- gap: 1rem;
- }
-
- .headerActions {
- width: 100%;
- justify-content: flex-end;
- }
-}
-
-@media (width <= 768px) {
- .individualReport {
- padding: 0.5rem;
- }
-
- .reportCard {
- margin: 0 -0.5rem 1.5rem;
- }
-
- .performanceTable {
- font-size: 0.8rem;
- }
-
- .performanceTable th,
- .performanceTable td {
- padding: 0.75rem 0.5rem;
- }
-
- .cardTitle {
- font-size: 1.125rem;
- }
-
- .chartContainer {
- height: 250px;
- }
-
- .metricCol {
- margin-bottom: 1rem;
- }
-}
-
-@media (width <= 480px) {
- .emptyContent i {
- font-size: 3rem;
- }
-
- .emptyContent h3 {
- font-size: 1.25rem;
- }
-
- .emptyContent p {
- font-size: 0.9rem;
- }
-
- .performanceTable {
- font-size: 0.75rem;
- }
-
- .statusBadge {
- font-size: 0.7rem;
- padding: 0.2rem 0.5rem;
- }
-
- .visualIndicator {
- font-size: 1rem;
- }
-
- .chartContainer {
- height: 200px;
- }
-}
-
-@keyframes fade-in {
- from {
- opacity: 0;
- transform: translateY(10px);
- }
-
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-/* Print Styles */
-@media print {
- .individualReport {
- background: white !important;
- color: black !important;
- }
-
- .reportCard {
- background: white !important;
- box-shadow: none;
- border: 1px solid #ccc;
- break-inside: avoid;
- margin-bottom: 1rem;
- }
-
- .chartContainer {
- height: 250px !important;
- }
-
- .statusBadge {
- background: transparent !important;
- border: 1px solid currentcolor;
- }
-
- .insightAlert {
- background: transparent !important;
- border: 1px solid currentcolor;
- }
-}
-
-/* Accessibility */
-.performanceTable:focus-within {
- outline: 2px solid #4f46e5;
- outline-offset: 2px;
-}
-
-.darkMode .performanceTable:focus-within {
- outline-color: #818cf8;
-}
-
-.statusBadgeExcellent {
- background-color: #dcfce7;
- color: #15803d;
- border-color: #bbf7d0;
-}
-
-.statusBadgeGood {
- background-color: #fefce8;
- color: #a16207;
- border-color: #fef08a;
-}
-
-.statusBadgeNeedsImprovement {
- background-color: #fff7ed;
- color: #c2410c;
- border-color: #fed7aa;
-}
-
-.statusBadgeCritical {
- background-color: #fee2e2;
- color: #b91c1c;
- border-color: #fecaca;
-}
-
-.darkMode .statusBadgeExcellent {
- background-color: #064e3b;
- color: #6ee7b7 !important;
- border-color: #065f46;
-}
-
-.darkMode .statusBadgeGood {
- background-color: #78350f;
- color: #fde68a !important;
- border-color: #92400e;
-}
-
-.darkMode .statusBadgeNeedsImprovement {
- background-color: #7c2d12;
- color: #fed7aa !important;
- border-color: #9a3412;
-}
-
-.darkMode .statusBadgeCritical {
- background-color: #7f1d1d;
- color: #fecaca !important;
- border-color: #991b1b;
-}
diff --git a/src/components/EductionPortal/EducatorReports/components/MetricCard/MetricCard.jsx b/src/components/EductionPortal/EducatorReports/components/MetricCard/MetricCard.jsx
deleted file mode 100644
index 44e3e7ff57..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/MetricCard/MetricCard.jsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import React from 'react';
-import { useSelector } from 'react-redux';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import {
- faChartLine,
- faBook,
- faHeart,
- faClock,
- faChartBar,
- faCheckCircle,
- faUserGraduate,
-} from '@fortawesome/free-solid-svg-icons';
-import styles from './MetricCard.module.css';
-
-const iconMap = {
- 'fa-chart-line': faChartLine,
- 'fa-book': faBook,
- 'fa-heart': faHeart,
- 'fa-clock': faClock,
- 'fa-chart-bar': faChartBar,
- 'fa-check-circle': faCheckCircle,
- 'fa-user-graduate': faUserGraduate,
-};
-
-const MetricCard = ({
- title,
- value,
- unit = '',
- change,
- changeType = 'neutral',
- icon,
- color = 'primary',
- size = 'medium',
- description,
- loading = false,
-}) => {
- const darkMode = useSelector(state => state.theme?.darkMode || false);
-
- const getChangeIcon = () => {
- switch (changeType) {
- case 'positive':
- return 'fa-arrow-up';
- case 'negative':
- return 'fa-arrow-down';
- default:
- return 'fa-minus';
- }
- };
-
- const getChangeText = () => {
- if (change === undefined || change === null) return null;
-
- const sign = change > 0 ? '+' : '';
- return `${sign}${change}%`;
- };
-
- if (loading) {
- return (
-
- );
- }
-
- const faIcon = iconMap[icon];
-
- return (
-
- {/* Header with icon and title */}
-
- {icon && faIcon && (
-
-
-
- )}
-
{title}
-
-
- {/* Main value display */}
-
-
- {value}
- {unit && {unit} }
-
-
- {/* Change indicator */}
- {getChangeText() && (
-
-
- {getChangeText()}
-
- )}
-
-
- {/* Description */}
- {description && (
-
- )}
-
- {/* Visual accent */}
-
-
- );
-};
-
-export default MetricCard;
diff --git a/src/components/EductionPortal/EducatorReports/components/MetricCard/MetricCard.module.css b/src/components/EductionPortal/EducatorReports/components/MetricCard/MetricCard.module.css
deleted file mode 100644
index 75469ab679..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/MetricCard/MetricCard.module.css
+++ /dev/null
@@ -1,473 +0,0 @@
-/* MetricCard.module.css */
-
-.metricCard {
- background-color: #fff;
- border-radius: 12px;
- padding: 1.5rem;
- box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
- border: 1px solid #e5e7eb;
- transition: all 0.3s ease;
- position: relative;
- animation: fade-in-scale 0.5s ease-out;
- overflow: hidden;
- height: fit-content;
-}
-
-.metricCard.darkMode {
- background-color: #1f2937;
- border-color: #374151;
- box-shadow: 0 1px 3px rgb(0 0 0 / 30%);
-}
-
-/* Size Variants */
-.small {
- padding: 1rem;
- min-height: 120px;
-}
-
-.medium {
- padding: 1.5rem;
- min-height: 140px;
-}
-
-.large {
- padding: 2rem;
- min-height: 180px;
-}
-
-/* Color Variants */
-.primary {
- border-left: 4px solid #4f46e5;
-}
-
-.darkMode.primary {
- border-left-color: #818cf8;
-}
-
-.success {
- border-left: 4px solid #10b981;
-}
-
-.darkMode.success {
- border-left-color: #34d399;
-}
-
-.warning {
- border-left: 4px solid #f59e0b;
-}
-
-.darkMode.warning {
- border-left-color: #fbbf24;
-}
-
-.danger {
- border-left: 4px solid #ef4444;
-}
-
-.darkMode.danger {
- border-left-color: #f87171;
-}
-
-.info {
- border-left: 4px solid #06b6d4;
-}
-
-.darkMode.info {
- border-left-color: #67e8f9;
-}
-
-.secondary {
- border-left: 4px solid #8b5cf6;
-}
-
-.darkMode.secondary {
- border-left-color: #a78bfa;
-}
-
-/* Header Section */
-.cardHeader {
- display: flex;
- align-items: center;
- gap: 0.75rem;
- margin-bottom: 1rem;
-}
-
-.iconContainer {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 2.5rem;
- height: 2.5rem;
- border-radius: 8px;
- background-color: #f3f4f6;
- color: #374151;
- font-size: 1.125rem;
-}
-
-.darkMode .iconContainer {
- background-color: #374151;
- color: #d1d5db;
-}
-
-.primary .iconContainer {
- background-color: #eef2ff;
- color: #4f46e5;
-}
-
-.success .iconContainer {
- background-color: #ecfdf5;
- color: #047857;
-}
-
-.warning .iconContainer {
- background-color: #fffbeb;
- color: #b45309;
-}
-
-.danger .iconContainer {
- background-color: #fef2f2;
- color: #b91c1c;
-}
-
-.info .iconContainer {
- background-color: #ecfeff;
- color: #0e7490;
-}
-
-.secondary .iconContainer {
- background-color: #faf5ff;
- color: #6d28d9;
-}
-
-.darkMode.primary .iconContainer {
- background-color: #312e81;
- color: #a5b4fc;
-}
-
-.darkMode.success .iconContainer {
- background-color: #064e3b;
- color: #34d399;
-}
-
-.darkMode.warning .iconContainer {
- background-color: #78350f;
- color: #fbbf24;
-}
-
-.darkMode.danger .iconContainer {
- background-color: #7f1d1d;
- color: #fca5a5;
-}
-
-.darkMode.info .iconContainer {
- background-color: #164e63;
- color: #67e8f9;
-}
-
-.darkMode.secondary .iconContainer {
- background-color: #581c87;
- color: #c4b5fd;
-}
-
-.title {
- font-size: 0.875rem;
- font-weight: 600;
- color: #374151;
- margin: 0;
- text-transform: uppercase;
- letter-spacing: 0.05em;
-}
-
-.darkMode .title {
- color: #d1d5db;
-}
-
-/* Value Section */
-.valueContainer {
- display: flex;
- justify-content: space-between;
- align-items: flex-end;
- margin-bottom: 1rem;
-}
-
-.mainValue {
- display: flex;
- align-items: baseline;
- gap: 0.25rem;
-}
-
-.value {
- font-size: 2.25rem;
- font-weight: 700;
- color: #111827;
- line-height: 1;
-}
-
-.darkMode .value {
- color: #f9fafb;
-}
-
-.small .value {
- font-size: 1.75rem;
-}
-
-.large .value {
- font-size: 2.75rem;
-}
-
-.unit {
- font-size: 1rem;
- font-weight: 500;
- color: #6b7280;
- margin-left: 0.25rem;
-}
-
-.darkMode .unit {
- color: #9ca3af;
-}
-
-/* Change Indicator */
-.changeIndicator {
- display: flex;
- align-items: center;
- gap: 0.25rem;
- font-size: 0.875rem;
- font-weight: 600;
- padding: 0.25rem 0.5rem;
- border-radius: 6px;
- white-space: nowrap;
-}
-
-.changeIndicator.positive {
- background-color: #ecfdf5;
- color: #047857;
-}
-
-.darkMode .changeIndicator.positive {
- background-color: #064e3b;
- color: #34d399;
-}
-
-.changeIndicator.negative {
- background-color: #fef2f2;
- color: #b91c1c;
-}
-
-.darkMode .changeIndicator.negative {
- background-color: #7f1d1d;
- color: #fca5a5;
-}
-
-.changeIndicator.neutral {
- background-color: #f3f4f6;
- color: #374151;
-}
-
-.darkMode .changeIndicator.neutral {
- background-color: #374151;
- color: #d1d5db;
-}
-
-.changeValue {
- font-size: 0.8rem;
-}
-
-/* Description */
-.description {
- margin-top: auto;
-}
-
-.description p {
- font-size: 0.875rem;
- color: #6b7280;
- margin: 0;
- line-height: 1.5;
-}
-
-.darkMode .description p {
- color: #9ca3af;
-}
-
-/* Visual Accent */
-.accent {
- position: absolute;
- top: 0;
- right: 0;
- width: 100px;
- height: 100px;
- background: linear-gradient(135deg, transparent 50%, rgb(79 70 229 / 5%) 50%);
- border-radius: 0 12px 0 100px;
- pointer-events: none;
-}
-
-.darkMode .accent {
- background: linear-gradient(135deg, transparent 50%, rgb(129 140 248 / 10%) 50%);
-}
-
-/* Loading State */
-.loading {
- position: relative;
- overflow: hidden;
-}
-
-.loadingShimmer {
- display: flex;
- flex-direction: column;
- gap: 1rem;
- padding: 1rem 0;
-}
-
-.shimmerLine {
- height: 1rem;
- background: linear-gradient(90deg, #f3f4f6 25%, #e5e7eb 50%, #f3f4f6 75%);
- background-size: 200% 100%;
- border-radius: 4px;
- animation: shimmer 1.5s infinite;
-}
-
-.darkMode .shimmerLine {
- background: linear-gradient(90deg, #374151 25%, #4b5563 50%, #374151 75%);
- background-size: 200% 100%;
-}
-
-.shimmerLine:nth-child(1) {
- width: 60%;
- height: 0.75rem;
-}
-
-.shimmerLine:nth-child(2) {
- width: 80%;
- height: 2rem;
-}
-
-.shimmerLine:nth-child(3) {
- width: 40%;
- height: 0.75rem;
-}
-
-@keyframes shimmer {
- 0% {
- background-position: -200% 0;
- }
-
- 100% {
- background-position: 200% 0;
- }
-}
-
-/* Hover Effects */
-.metricCard:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
-}
-
-/* Accessibility */
-.metricCard:focus-within {
- outline: 2px solid #4f46e5;
- outline-offset: 2px;
-}
-
-.darkMode .metricCard:hover {
- box-shadow: 0 4px 12px rgb(0 0 0 / 40%);
-}
-
-.darkMode .metricCard:focus-within {
- outline-color: #818cf8;
-}
-
-/* Responsive Design */
-@media (width <= 768px) {
- .metricCard {
- padding: 1rem;
- }
-
- .small,
- .medium,
- .large {
- padding: 1rem;
- min-height: auto;
- }
-
- .value {
- font-size: 1.875rem;
- }
-
- .small .value {
- font-size: 1.5rem;
- }
-
- .large .value {
- font-size: 2rem;
- }
-
- .valueContainer {
- flex-direction: column;
- align-items: flex-start;
- gap: 0.5rem;
- }
-
- .changeIndicator {
- align-self: flex-end;
- }
-
- .iconContainer {
- width: 2rem;
- height: 2rem;
- font-size: 1rem;
- }
-
- .title {
- font-size: 0.8rem;
- }
-}
-
-@media (width <= 480px) {
- .cardHeader {
- flex-direction: column;
- align-items: flex-start;
- gap: 0.5rem;
- }
-
- .iconContainer {
- width: 1.75rem;
- height: 1.75rem;
- font-size: 0.875rem;
- }
-
- .accent {
- width: 60px;
- height: 60px;
- }
-}
-
-/* Print Styles */
-@media print {
- .metricCard {
- background: white !important;
- box-shadow: none;
- border: 1px solid #ccc;
- break-inside: avoid;
- margin-bottom: 1rem;
- }
-
- .accent {
- display: none;
- }
-
- .changeIndicator {
- background: transparent !important;
- border: 1px solid currentcolor;
- }
-}
-
-@keyframes fade-in-scale {
- from {
- opacity: 0;
- transform: scale(0.95);
- }
-
- to {
- opacity: 1;
- transform: scale(1);
- }
-}
diff --git a/src/components/EductionPortal/EducatorReports/components/ReportChart/ReportChart.jsx b/src/components/EductionPortal/EducatorReports/components/ReportChart/ReportChart.jsx
deleted file mode 100644
index 4d25372872..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/ReportChart/ReportChart.jsx
+++ /dev/null
@@ -1,236 +0,0 @@
-import React from 'react';
-import {
- Chart as ChartJS,
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- BarElement,
- ArcElement,
- Title,
- Tooltip,
- Legend,
-} from 'chart.js';
-import { Bar, Line, Pie } from 'react-chartjs-2';
-import { useSelector } from 'react-redux';
-import styles from './ReportChart.module.css';
-
-// Register Chart.js components
-ChartJS.register(
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- BarElement,
- ArcElement,
- Title,
- Tooltip,
- Legend,
-);
-
-const ReportChart = ({
- type = 'bar',
- data,
- title,
- height = 300,
- showLegend = true,
- backgroundColor,
- borderColor,
- gradient = false,
-}) => {
- const darkMode = useSelector(state => state.theme?.darkMode || false);
-
- // Default color schemes
- const defaultColors = {
- light: {
- primary: '#4f46e5',
- secondary: '#06b6d4',
- success: '#10b981',
- warning: '#f59e0b',
- danger: '#ef4444',
- info: '#8b5cf6',
- },
- dark: {
- primary: '#818cf8',
- secondary: '#67e8f9',
- success: '#34d399',
- warning: '#fbbf24',
- danger: '#f87171',
- info: '#a78bfa',
- },
- };
-
- const colors = darkMode ? defaultColors.dark : defaultColors.light;
-
- const getLegendOptions = () => ({
- display: showLegend,
- position: 'top',
- labels: {
- color: darkMode ? '#d1d5db' : '#374151',
- usePointStyle: true,
- padding: 20,
- font: {
- size: 12,
- family: "'Inter', sans-serif",
- },
- },
- });
-
- const getTitleOptions = () => ({
- display: !!title,
- text: title,
- color: darkMode ? '#f9fafb' : '#111827',
- font: {
- size: 16,
- weight: '600',
- family: "'Inter', sans-serif",
- },
- padding: {
- top: 10,
- bottom: 20,
- },
- });
-
- const getTooltipOptions = () => ({
- backgroundColor: darkMode ? '#1f2937' : '#ffffff',
- titleColor: darkMode ? '#f9fafb' : '#111827',
- bodyColor: darkMode ? '#d1d5db' : '#374151',
- borderColor: darkMode ? '#374151' : '#e5e7eb',
- borderWidth: 1,
- cornerRadius: 8,
- displayColors: true,
- });
-
- const getScalesOptions = () => {
- if (type === 'pie') return {};
-
- const tickColor = darkMode ? '#9ca3af' : '#6b7280';
- const gridColor = darkMode ? '#374151' : '#f3f4f6';
- const borderColor = darkMode ? '#4b5563' : '#d1d5db';
-
- return {
- x: {
- ticks: {
- color: tickColor,
- font: {
- size: 11,
- },
- },
- grid: {
- color: gridColor,
- borderColor,
- },
- },
- y: {
- ticks: {
- color: tickColor,
- font: {
- size: 11,
- },
- },
- grid: {
- color: gridColor,
- borderColor,
- },
- },
- };
- };
-
- // Common chart options
- const getBaseOptions = () => ({
- responsive: true,
- maintainAspectRatio: false,
- plugins: {
- legend: getLegendOptions(),
- title: getTitleOptions(),
- tooltip: getTooltipOptions(),
- },
- scales: getScalesOptions(),
- });
-
- // Process data based on chart type
- const processChartData = () => {
- if (!data) return null;
-
- const processedData = { ...data };
-
- // Apply default colors if not provided
- if (data.datasets) {
- processedData.datasets = data.datasets.map((dataset, index) => {
- const colorKeys = Object.keys(colors);
- const colorKey = colorKeys[index % colorKeys.length];
- const baseColor = colors[colorKey];
-
- const processedDataset = {
- ...dataset,
- backgroundColor: (() => {
- if (backgroundColor) return backgroundColor;
- if (dataset.backgroundColor) return dataset.backgroundColor;
- if (type === 'pie') return Object.values(colors);
- if (gradient) return `linear-gradient(45deg, ${baseColor}, ${baseColor}99)`;
- return `${baseColor}20`;
- })(),
- borderColor: borderColor || dataset.borderColor || baseColor,
- borderWidth: dataset.borderWidth || (type === 'line' ? 3 : 2),
- };
-
- // Additional styling for line charts
- if (type === 'line') {
- processedDataset.fill = dataset.fill !== undefined ? dataset.fill : true;
- processedDataset.tension = dataset.tension || 0.4;
- processedDataset.pointBackgroundColor = baseColor;
- processedDataset.pointBorderColor = '#ffffff';
- processedDataset.pointBorderWidth = 2;
- processedDataset.pointRadius = 4;
- processedDataset.pointHoverRadius = 6;
- }
-
- // Additional styling for bar charts
- if (type === 'bar') {
- processedDataset.borderRadius = 4;
- processedDataset.borderSkipped = false;
- }
-
- return processedDataset;
- });
- }
-
- return processedData;
- };
-
- const chartData = processChartData();
- const options = getBaseOptions();
-
- if (!chartData) {
- return (
-
- );
- }
-
- const renderChart = () => {
- switch (type) {
- case 'line':
- return ;
- case 'pie':
- return ;
- case 'bar':
- default:
- return ;
- }
- };
-
- return (
-
- );
-};
-
-export default ReportChart;
diff --git a/src/components/EductionPortal/EducatorReports/components/ReportChart/ReportChart.module.css b/src/components/EductionPortal/EducatorReports/components/ReportChart/ReportChart.module.css
deleted file mode 100644
index ca2ba6632b..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/ReportChart/ReportChart.module.css
+++ /dev/null
@@ -1,185 +0,0 @@
-/* ReportChart.module.css */
-
-.chartContainer {
- background-color: #fff;
- border-radius: 12px;
- padding: 1.5rem;
- box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
- border: 1px solid #e5e7eb;
- transition: all 0.3s ease;
- margin-bottom: 1.5rem;
- animation: fade-in-up 0.5s ease-out;
-}
-
-.chartContainer.darkMode {
- background-color: #1f2937;
- border-color: #374151;
- box-shadow: 0 1px 3px rgb(0 0 0 / 30%);
-}
-
-.chartWrapper {
- position: relative;
- width: 100%;
- height: 300px;
- margin: 0 auto;
-}
-
-.noData {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- height: 200px;
- color: #6b7280;
- font-size: 1rem;
-}
-
-.darkMode .noData {
- color: #9ca3af;
-}
-
-.noData i {
- font-size: 3rem;
- margin-bottom: 1rem;
- opacity: 0.5;
-}
-
-.noData p {
- margin: 0;
- font-weight: 500;
-}
-
-/* Responsive Design */
-@media (width <= 768px) {
- .chartContainer {
- padding: 1rem;
- margin: 0 -0.5rem 1.5rem;
- }
-
- .chartWrapper {
- height: 250px;
- }
-}
-
-@media (width <= 480px) {
- .chartContainer {
- padding: 0.75rem;
- }
-
- .chartWrapper {
- height: 200px;
- }
-
- .noData {
- height: 150px;
- }
-
- .noData i {
- font-size: 2rem;
- }
-
- .noData p {
- font-size: 0.9rem;
- }
-}
-
-/* Chart Loading Animation */
-.chartContainer.loading {
- position: relative;
- overflow: hidden;
-}
-
-.chartContainer.loading::before {
- content: '';
- position: absolute;
- top: 0;
- left: -100%;
- width: 100%;
- height: 100%;
- background: linear-gradient(90deg, transparent, rgb(79 70 229 / 10%), transparent);
- animation: loading 1.5s infinite;
-}
-
-@keyframes loading {
- 0% {
- left: -100%;
- }
-
- 100% {
- left: 100%;
- }
-}
-
-/* Chart Hover Effects */
-.chartContainer:hover {
- box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
- transform: translateY(-2px);
-}
-
-/* Accessibility */
-.chartContainer:focus-within {
- outline: 2px solid #4f46e5;
- outline-offset: 2px;
-}
-
-.darkMode .chartContainer:hover {
- box-shadow: 0 4px 12px rgb(0 0 0 / 40%);
-}
-
-.darkMode .chartContainer:focus-within {
- outline-color: #818cf8;
-}
-
-/* Print Styles */
-@media print {
- .chartContainer {
- background: white !important;
- box-shadow: none;
- border: 1px solid #ccc;
- break-inside: avoid;
- margin-bottom: 1rem;
- }
-
- .chartWrapper {
- height: 250px !important;
- }
-}
-
-@keyframes fade-in-up {
- from {
- opacity: 0;
- transform: translateY(20px);
- }
-
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-/* Custom scrollbar for chart containers if needed */
-.chartContainer::-webkit-scrollbar {
- width: 6px;
- height: 6px;
-}
-
-.chartContainer::-webkit-scrollbar-track {
- background: transparent;
-}
-
-.chartContainer::-webkit-scrollbar-thumb {
- background: #d1d5db;
- border-radius: 3px;
-}
-
-.darkMode .chartContainer::-webkit-scrollbar-thumb {
- background: #4b5563;
-}
-
-.chartContainer::-webkit-scrollbar-thumb:hover {
- background: #9ca3af;
-}
-
-.darkMode .chartContainer::-webkit-scrollbar-thumb:hover {
- background: #6b7280;
-}
diff --git a/src/components/EductionPortal/EducatorReports/components/ReportFilterBar/ReportFilterBar.jsx b/src/components/EductionPortal/EducatorReports/components/ReportFilterBar/ReportFilterBar.jsx
deleted file mode 100644
index db94860137..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/ReportFilterBar/ReportFilterBar.jsx
+++ /dev/null
@@ -1,155 +0,0 @@
-import React from 'react';
-import { Row, Col, Form, FormGroup, Label, Input } from 'reactstrap';
-import { useSelector } from 'react-redux';
-import styles from './ReportFilterBar.module.css';
-import { students, classes, filterSubjects, dateRanges } from '../../mockdata';
-
-const ReportFilterBar = ({ filters, onFilterChange, activeTab }) => {
- const darkMode = useSelector(state => state.theme?.darkMode || false);
-
- const handleInputChange = (field, value) => {
- onFilterChange({ [field]: value });
- };
-
- const handleExport = () => {
- alert('Export functionality coming soon!');
- };
-
- return (
-
- );
-};
-
-export default ReportFilterBar;
diff --git a/src/components/EductionPortal/EducatorReports/components/ReportFilterBar/ReportFilterBar.module.css b/src/components/EductionPortal/EducatorReports/components/ReportFilterBar/ReportFilterBar.module.css
deleted file mode 100644
index fb74cf8b5b..0000000000
--- a/src/components/EductionPortal/EducatorReports/components/ReportFilterBar/ReportFilterBar.module.css
+++ /dev/null
@@ -1,285 +0,0 @@
-/* ReportFilterBar.module.css */
-
-.filterBar {
- background-color: #fff;
- border-radius: 12px;
- padding: 1.5rem;
- margin-bottom: 1.5rem;
- box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
- border: 1px solid #e5e7eb;
- transition: all 0.3s ease;
- animation: slide-down 0.3s ease-out;
-}
-
-.filterBar.darkMode {
- background-color: #1f2937;
- border-color: #374151;
- box-shadow: 0 1px 3px rgb(0 0 0 / 30%);
-}
-
-.filterRow {
- align-items: end;
- margin: 0 -0.5rem;
-}
-
-.filterCol {
- padding: 0 0.5rem;
- margin-bottom: 1rem;
-}
-
-.filterLabel {
- font-size: 0.875rem;
- font-weight: 600;
- color: #374151;
- margin-bottom: 0.5rem;
- display: block;
-}
-
-.darkMode .filterLabel {
- color: #d1d5db;
-}
-
-.filterSelect {
- border: 1px solid #d1d5db;
- border-radius: 8px;
- padding: 0.75rem 1rem;
- font-size: 0.875rem;
- background-color: #fff;
- color: #374151;
- transition: all 0.2s ease;
- width: 100%;
- appearance: none;
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
- background-position: right 0.75rem center;
- background-repeat: no-repeat;
- background-size: 1.125em 1.125em;
- padding-right: 2.5rem;
-}
-
-.filterSelect:focus {
- outline: none;
- border-color: #4f46e5;
- box-shadow: 0 0 0 3px rgb(79 70 229 / 10%);
-}
-
-.filterSelect:disabled {
- opacity: 0.6;
- cursor: not-allowed;
-}
-
-.darkMode .filterSelect {
- background-color: #374151;
- border-color: #4b5563;
- color: #d1d5db;
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%259ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
-}
-
-.darkMode .filterSelect:focus {
- border-color: #818cf8;
- box-shadow: 0 0 0 3px rgb(129 140 248 / 10%);
-}
-
-/* Action Buttons */
-.actionButtons {
- display: flex;
- gap: 0.75rem;
- height: 100%;
- align-items: end;
-}
-
-.actionBtn {
- background-color: #4f46e5;
- color: #fff;
- border: none;
- border-radius: 8px;
- padding: 0.75rem 1rem;
- font-size: 0.875rem;
- font-weight: 500;
- cursor: pointer;
- transition: all 0.2s ease;
- display: flex;
- align-items: center;
- gap: 0.5rem;
- white-space: nowrap;
-}
-
-.actionBtn:hover {
- background-color: #3730a3;
- transform: translateY(-1px);
- box-shadow: 0 4px 8px rgb(79 70 229 / 30%);
-}
-
-.actionBtn:active {
- transform: translateY(0);
-}
-
-.refreshBtn {
- background-color: #059669;
-}
-
-.refreshBtn:hover {
- background-color: #047857;
- box-shadow: 0 4px 8px rgb(5 150 105 / 30%);
-}
-
-.exportBtn {
- background-color: #dc2626;
-}
-
-.exportBtn:hover {
- background-color: #b91c1c;
- box-shadow: 0 4px 8px rgb(220 38 38 / 30%);
-}
-
-.actionBtn:focus {
- outline: 2px solid #4f46e5;
- outline-offset: 2px;
-}
-
-.actionBtn:disabled {
- opacity: 0.6;
- cursor: not-allowed;
- transform: none;
-}
-
-.darkMode .actionBtn {
- background-color: #4338ca;
-}
-
-.darkMode .actionBtn:focus {
- outline-color: #818cf8;
-}
-
-.darkMode .actionBtn:hover {
- background-color: #3730a3;
-}
-
-.actionBtn:disabled:hover {
- transform: none;
- box-shadow: none;
-}
-
-.darkMode .refreshBtn {
- background-color: #047857;
-}
-
-.darkMode .refreshBtn:hover {
- background-color: #065f46;
-}
-
-.darkMode .exportBtn {
- background-color: #b91c1c;
-}
-
-.darkMode .exportBtn:hover {
- background-color: #991b1b;
-}
-
-/* Custom Date Range */
-.customDateRow {
- margin-top: 1rem;
- padding-top: 1rem;
- border-top: 1px solid #e5e7eb;
- margin-left: 0;
- margin-right: 0;
-}
-
-.darkMode .customDateRow {
- border-top-color: #374151;
-}
-
-/* Responsive Design */
-@media (width <= 992px) {
- .filterRow {
- margin: 0 -0.25rem;
- }
-
- .filterCol {
- padding: 0 0.25rem;
- margin-bottom: 1rem;
- }
-
- .actionButtons {
- flex-direction: column;
- align-items: stretch;
- }
-
- .actionBtn {
- justify-content: center;
- margin-bottom: 0.5rem;
- }
-}
-
-@media (width <= 768px) {
- .filterBar {
- padding: 1rem;
- margin: 0 -0.5rem 1.5rem;
- border-radius: 8px;
- }
-
- .filterRow {
- flex-direction: column;
- margin: 0;
- }
-
- .filterCol {
- padding: 0;
- margin-bottom: 1rem;
- width: 100%;
- }
-
- .actionButtons {
- flex-direction: row;
- justify-content: space-between;
- }
-
- .actionBtn {
- flex: 1;
- margin-bottom: 0;
- font-size: 0.8rem;
- padding: 0.65rem 0.5rem;
- }
-}
-
-@media (width <= 480px) {
- .actionButtons {
- flex-direction: column;
- gap: 0.5rem;
- }
-
- .actionBtn {
- width: 100%;
- }
-
- .filterLabel {
- font-size: 0.8rem;
- }
-
- .filterSelect {
- font-size: 0.8rem;
- padding: 0.65rem 0.75rem;
- }
-}
-
-/* Animation */
-@keyframes slide-down {
- from {
- opacity: 0;
- transform: translateY(-10px);
- }
-
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-/* Icon Spacing */
-.actionBtn i {
- font-size: 0.875rem;
-}
-
-/* Form Group Spacing */
-.filterCol .form-group {
- margin-bottom: 0;
-}
diff --git a/src/components/EductionPortal/EducatorReports/config/layoutConfig.js b/src/components/EductionPortal/EducatorReports/config/layoutConfig.js
deleted file mode 100644
index 36507af9cb..0000000000
--- a/src/components/EductionPortal/EducatorReports/config/layoutConfig.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Layout configuration for the Educator Reports dashboard
-export const LAYOUT_CONFIG = {
- // Header height - adjust this value to match your application's header
- HEADER_HEIGHT: '110px', // Increased for better clearance below top nav
-
- // Sidebar width
- SIDEBAR_WIDTH: '250px',
-
- // Responsive breakpoints
- MOBILE_BREAKPOINT: '768px',
- TABLET_BREAKPOINT: '992px',
-
- // Z-index values
- HEADER_Z_INDEX: 1100,
- SIDEBAR_Z_INDEX: 1000,
- MODAL_Z_INDEX: 1200,
-};
-
-// CSS custom properties for use in components
-export const getCSSVariables = () => ({
- '--header-height': LAYOUT_CONFIG.HEADER_HEIGHT,
- '--sidebar-width': LAYOUT_CONFIG.SIDEBAR_WIDTH,
-});
diff --git a/src/components/EductionPortal/EducatorReports/index.js b/src/components/EductionPortal/EducatorReports/index.js
deleted file mode 100644
index 97613ad2ec..0000000000
--- a/src/components/EductionPortal/EducatorReports/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export { default } from './ReportsView';
-export { default as IndividualReportView } from './components/IndividualReportView/IndividualReportView';
-export { default as ClassPerformanceView } from './components/ClassPerformanceView/ClassPerformanceView';
-export { default as ReportFilterBar } from './components/ReportFilterBar/ReportFilterBar';
diff --git a/src/components/EductionPortal/EducatorReports/mockdata.js b/src/components/EductionPortal/EducatorReports/mockdata.js
deleted file mode 100644
index cecba18558..0000000000
--- a/src/components/EductionPortal/EducatorReports/mockdata.js
+++ /dev/null
@@ -1,198 +0,0 @@
-export const strengthsGapsData = [
- { subject: 'Arts/Trades', performance: 95, status: 'excellent', color: '#10b981' },
- { subject: 'English', performance: 90, status: 'excellent', color: '#10b981' },
- { subject: 'Health', performance: 48, status: 'needs-improvement', color: '#f59e0b' },
- { subject: 'Mathematics', performance: 67, status: 'good', color: '#fbbf24' },
- { subject: 'Science', performance: 83, status: 'good', color: '#f59e0b' },
- { subject: 'Social Studies', performance: 84, status: 'excellent', color: '#10b981' },
- { subject: 'Tech & Innovation', performance: 35, status: 'needs-improvement', color: '#ef4444' },
- { subject: 'Values', performance: 72, status: 'good', color: '#10b981' },
-];
-
-export const performanceTrendData = {
- labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
- datasets: [
- {
- label: 'Arts/Trades',
- data: [95, 94, 95, 96, 95, 95],
- borderColor: '#10b981',
- backgroundColor: '#10b981',
- },
- {
- label: 'English',
- data: [88, 89, 90, 91, 90, 90],
- borderColor: '#3b82f6',
- backgroundColor: '#3b82f6',
- },
- {
- label: 'Health',
- data: [45, 46, 47, 48, 48, 48],
- borderColor: '#f59e0b',
- backgroundColor: '#f59e0b',
- },
- {
- label: 'Mathematics',
- data: [65, 66, 67, 68, 67, 67],
- borderColor: '#fbbf24',
- backgroundColor: '#fbbf24',
- },
- {
- label: 'Science',
- data: [80, 81, 82, 83, 83, 83],
- borderColor: '#06b6d4',
- backgroundColor: '#06b6d4',
- },
- {
- label: 'Social Studies',
- data: [82, 83, 84, 85, 84, 84],
- borderColor: '#8b5cf6',
- backgroundColor: '#8b5cf6',
- },
- {
- label: 'Tech & Innovation',
- data: [32, 33, 34, 35, 35, 35],
- borderColor: '#ef4444',
- backgroundColor: '#ef4444',
- },
- {
- label: 'Values',
- data: [70, 71, 72, 73, 72, 72],
- borderColor: '#10b981',
- backgroundColor: '#10b981',
- },
- ],
-};
-
-export const teachingStrategiesData = {
- labels: [
- 'Game Genius',
- 'Power Play',
- 'Body Smart Exploration',
- 'Crazy Creative Combo Competition',
- 'Existential Smart Exploration',
- 'Curious Dropout',
- ],
- datasets: [
- {
- label: 'Effectiveness',
- data: [92, 88, 85, 82, 78, 65],
- backgroundColor: ['#10b981', '#10b981', '#10b981', '#3b82f6', '#3b82f6', '#ef4444'],
- },
- ],
-};
-
-export const lifeStrategiesData = {
- labels: [
- 'Everything you do should increase choices',
- 'Ask "what would Jesus do?"',
- 'Choose to trust with observation',
- 'Practice improving your emotional intelligence',
- ],
- datasets: [
- {
- label: 'Impact',
- data: [92, 85, 82, 76],
- backgroundColor: ['#10b981', '#10b981', '#fbbf24', '#fbbf24'],
- },
- ],
-};
-
-export const subjects = [
- { name: 'All Subjects', color: '#6b7280' },
- { name: 'Arts/Trades', color: '#ff8c00' },
- { name: 'English', color: '#9c27b0' },
- { name: 'Health', color: '#4caf50' },
- { name: 'Mathematics', color: '#2196f3' },
- { name: 'Science', color: '#009688' },
- { name: 'Social Studies', color: '#ff9800' },
- { name: 'Tech & Innovation', color: '#607d8b' },
- { name: 'Values', color: '#f44336' },
-];
-
-export const filterSubjects = [
- { value: 'all', label: 'All Subjects' },
- { value: 'mathematics', label: 'Mathematics' },
- { value: 'science', label: 'Science' },
- { value: 'english', label: 'English' },
- { value: 'history', label: 'History' },
- { value: 'art', label: 'Art' },
- { value: 'health', label: 'Health' },
- { value: 'social-studies', label: 'Social Studies' },
- { value: 'tech-innovation', label: 'Tech & Innovation' },
- { value: 'values', label: 'Values' },
-];
-
-export const students = [
- { id: '1', name: 'Alex Johnson' },
- { id: '2', name: 'Sarah Williams' },
- { id: '3', name: 'Michael Brown' },
- { id: '4', name: 'Emily Davis' },
-];
-
-export const classes = [
- { id: '1', name: 'Grade 5A - Mathematics' },
- { id: '2', name: 'Grade 6B - Science' },
- { id: '3', name: 'Grade 4C - English' },
-];
-
-export const dateRanges = [
- { value: 'lastWeek', label: 'Last Week' },
- { value: 'lastMonth', label: 'Last Month' },
- { value: 'lastQuarter', label: 'Last Quarter' },
- { value: 'lastSemester', label: 'Last Semester' },
- { value: 'lastYear', label: 'Last Year' },
- { value: 'custom', label: 'Custom Range' },
-];
-
-export const sidebarMenuItems = [
- {
- icon: '🏠',
- label: 'Homepage',
- path: '',
- isActive: false,
- },
- {
- icon: '📊',
- label: 'Knowledge Evaluation',
- path: '',
- isActive: false,
- },
- {
- icon: '📋',
- label: 'Past Lesson Plans',
- path: '/educator/reports',
- isActive: false,
- },
- {
- icon: '⭐',
- label: 'My Saved Interests',
- path: '/saved-interests',
- isActive: false,
- },
- {
- icon: '📈',
- label: 'Evaluation results',
- path: '/evaluation-results',
- isActive: false,
- },
- {
- icon: '🏗️',
- label: 'Build Lesson Plan',
- path: '/build-lesson-plan',
- isActive: false,
- },
-];
-
-export const sidebarBottomMenuItems = [
- {
- icon: '⚙️',
- label: 'Settings',
- path: '/settings',
- },
- {
- icon: '🚪',
- label: 'Log out',
- path: '/logout',
- isLogout: true,
- },
-];
diff --git a/src/components/EductionPortal/EducatorReports/utils/statusUtils.js b/src/components/EductionPortal/EducatorReports/utils/statusUtils.js
deleted file mode 100644
index 8a0e1615ac..0000000000
--- a/src/components/EductionPortal/EducatorReports/utils/statusUtils.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Shared status helpers for report tables.
-
-const toNumber = value => {
- if (typeof value === 'number') return value;
- if (typeof value === 'string') {
- const parsed = Number.parseFloat(value.replace('%', '').trim());
- return Number.isFinite(parsed) ? parsed : 0;
- }
- return 0;
-};
-
-export const getStatusIcon = performance => {
- const p = toNumber(performance);
- if (p >= 85) return '🟢';
- if (p >= 70) return '🟡';
- if (p >= 50) return '🟠';
- return '🔴';
-};
-
-export const getStatusText = performance => {
- const p = toNumber(performance);
- if (p >= 85) return 'Excellent';
- if (p >= 70) return 'Good';
- if (p >= 50) return 'Needs Improvement';
- return 'Critical';
-};
-
-export const getStatusClass = performance => {
- const p = toNumber(performance);
- if (p >= 85) return 'excellent';
- if (p >= 70) return 'good';
- if (p >= 50) return 'needsImprovement';
- return 'critical';
-};
diff --git a/src/components/EductionPortal/EvaluationResults/EvaluationResults.jsx b/src/components/EductionPortal/EvaluationResults/EvaluationResults.jsx
index 8d59e67330..92a2b52e29 100644
--- a/src/components/EductionPortal/EvaluationResults/EvaluationResults.jsx
+++ b/src/components/EductionPortal/EvaluationResults/EvaluationResults.jsx
@@ -15,10 +15,13 @@ import {
} 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');
@@ -184,384 +187,393 @@ const EvaluationResults = ({ auth }) => {
};
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'}
+ <>
+
+
+ {/* 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
-
-
-
-
-
+
+ {/* Overall Performance Summary */}
+
+
+
Overall Performance Summary
+
+ {percentageScore}%
+ Overall Grade
+
-
-
- Total Score: {totalEarnedPoints}/{totalPossiblePoints} points
-
+
+
+
+
+ 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)}%
-
-
-
+ {/* 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
+ {/* 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
-
-
+ {/* 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)}%)
+ {/* Mobile Cards (shown on small screens) */}
+
+ {tasks.slice(0, 6).map(task => (
+
+
+
{task.name}
+
+ {task.status || 'On time'}
-
-
Submitted: {new Date(task.submissionDate).toLocaleDateString()}
+
+
+ Weightage: {task.weightage || '8'}%
+
+
+ Score: {task.earnedMarks}/{task.totalMarks}
+
+ {' '}
+ ({Math.round(task.percentage)}%)
+
+
+
+ Submitted: {' '}
+ {new Date(task.submissionDate).toLocaleDateString()}
+
+
+
+ openFeedbackModal(task)}
+ >
+
+ View Feedback
+
-
- 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}
+ {/* Teacher Feedback Section */}
+
+
+
+
+ Teacher Feedback - Structured feedback display with strengths and recommendations
+
+
+
+ {evaluationData.teacherFeedback.teacherName}
+
+
+ {evaluationData.teacherFeedback.teacherTitle}
+
+
- {/* Strengths and Improvements */}
-
-
-
-
- Strengths
-
-
- {evaluationData.teacherFeedback.strengths.map((strength, index) => (
-
- ✓
- {strength}
-
- ))}
-
+
+ {/* Overall Feedback */}
+
+
Overall Assessment
+
{evaluationData.teacherFeedback.overall}
-
-
-
- Areas for Improvement
-
-
- {evaluationData.teacherFeedback.improvements.map((improvement, index) => (
-
- →
- {improvement}
-
- ))}
-
+ {/* 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
+ {/* 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()}
-
+ {/* 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}%)
+ {/* Performance Summary */}
+
+
+
Your Score
+
+ {feedbackModal.task.earnedMarks}/{feedbackModal.task.totalMarks}
+ ({feedbackModal.task.percentage}%)
+
-
-
-
Weightage
-
-
- {feedbackModal.task.weightage}%
+
+
Weightage
+
+
+ {feedbackModal.task.weightage}%
+
-
-
-
Status
-
- {feedbackModal.task.status}
+
+
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()}
-
+ {/* Teacher Feedback */}
+
+
+
+ Teacher Feedback
+
+
{feedbackModal.task.teacherFeedback}
-
-
Grade Category:
-
{feedbackModal.task.category}
+
+ {/* Additional Details */}
+
+
+ Submission Date:
+
+ {new Date(feedbackModal.task.submissionDate).toLocaleDateString()} at{' '}
+ {new Date(feedbackModal.task.submissionDate).toLocaleTimeString()}
+
+
+
+ Grade Category:
+ {feedbackModal.task.category}
+
-
- )}
-
-
-
-
- Close
-
-
-
-
+ )}
+
+
+
+
+ Close
+
+
+
+
+ >
);
};
diff --git a/src/components/EductionPortal/EvaluationResults/EvaluationResults.module.css b/src/components/EductionPortal/EvaluationResults/EvaluationResults.module.css
index 558acbdf98..785ca6d60d 100644
--- a/src/components/EductionPortal/EvaluationResults/EvaluationResults.module.css
+++ b/src/components/EductionPortal/EvaluationResults/EvaluationResults.module.css
@@ -1,3 +1,5 @@
+/* stylelint-disable declaration-property-value-keyword-no-deprecated, no-descending-specificity */
+
/* ============================================================================
EVALUATION RESULTS - CLEAN ACADEMIC DASHBOARD
Modern table-based design matching the provided mockup
@@ -28,8 +30,53 @@
min-height: 100vh;
background-color: var(--bg-light);
padding: 0;
- margin-left: 0;
- transition: none;
+ 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 (width <= 991px) {
+ .evaluationResultsPage {
+ margin-left: 180px;
+ }
+
+ .evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+ }
+}
+
+@media (width <= 767px) {
+ .evaluationResultsPage {
+ margin-left: 240px;
+ }
+
+ .evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+ }
+}
+
+@media (width <= 480px) {
+ .evaluationResultsPage {
+ margin-left: 220px;
+ }
+
+ .evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+ }
+}
+
+@media (width <= 359px) {
+ .evaluationResultsPage {
+ margin-left: 200px;
+ }
+
+ .evaluationResultsPage[data-sidebar-minimized='true'] {
+ margin-left: 70px;
+ }
}
/* ============================================================================
@@ -451,6 +498,7 @@
color: var(--text-dark);
font-size: 0.9rem;
line-height: 1.3;
+ word-break: break-word;
overflow-wrap: anywhere;
}
@@ -768,6 +816,14 @@
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;
@@ -782,14 +838,6 @@
white-space: nowrap;
}
- /* Keep headers visible when scrolling horizontally */
- .assignmentTable thead th {
- position: sticky;
- top: 0;
- background: #f8f9fa;
- z-index: 1;
- }
-
.teacherFeedbackSection {
padding: 1.25rem;
margin: 0 0 1.25rem;
@@ -1193,7 +1241,8 @@
.feedbackTextItem {
flex: 1 1 auto;
min-width: 0;
- overflow-wrap: anywhere;
+ overflow-wrap: break-word;
+ word-break: break-word;
}
/* ============================================================================
@@ -1415,16 +1464,16 @@
============================================================================ */
/* Tablets (768px and below) */
-@media (768px <= width <= 991px) {
+@media (width <= 991px) and (width >= 768px) {
.evaluationResultsPage {
- margin-left: 0;
+ margin-left: 180px;
}
}
/* Mobile phones (767px and below) */
@media (width <= 767px) {
.evaluationResultsPage {
- margin-left: 0;
+ margin-left: 240px;
}
.headerSection {
@@ -1533,7 +1582,7 @@
/* Mobile phones (480px and below) */
@media (width <= 480px) {
.evaluationResultsPage {
- margin-left: 0;
+ margin-left: 220px;
}
.headerSection {
@@ -1631,7 +1680,7 @@
/* Small phones (below 360px) */
@media (width <= 359px) {
.evaluationResultsPage {
- margin-left: 0;
+ margin-left: 200px;
}
.pageTitle {
diff --git a/src/components/EductionPortal/EvaluationResultsWrapper.jsx b/src/components/EductionPortal/EvaluationResultsWrapper.jsx
index 0fc32b7484..db7046e553 100644
--- a/src/components/EductionPortal/EvaluationResultsWrapper.jsx
+++ b/src/components/EductionPortal/EvaluationResultsWrapper.jsx
@@ -1,3 +1,13 @@
+import React from 'react';
+import { SidebarProvider } from './SidebarContext';
import EvaluationResults from './EvaluationResults/EvaluationResults';
-export default EvaluationResults;
+const EvaluationResultsWithSidebar = props => {
+ return (
+
+
+
+ );
+};
+
+export default EvaluationResultsWithSidebar;
diff --git a/src/components/EductionPortal/Login/EPLogin.jsx b/src/components/EductionPortal/Login/EPLogin.jsx
index 1e75393946..99d506140c 100644
--- a/src/components/EductionPortal/Login/EPLogin.jsx
+++ b/src/components/EductionPortal/Login/EPLogin.jsx
@@ -20,19 +20,12 @@ function EPLogin(props) {
// push to dashboard if user is authenticated
useEffect(() => {
- if (auth.user.access) {
- const access = auth.user.access;
- const hasGEFlag = Object.hasOwn(access, 'canAccessGEPortal');
- const canAccessEP = hasGEFlag ? access.canAccessGEPortal : access.canAccessBMPortal;
- if (!canAccessEP) return;
-
- sessionStorage.removeItem('gePortalLoggedOut');
+ if (auth.user.access && auth.user.access.canAccessGEPortal) {
history.push(prevLocation.pathname);
}
- }, [auth.user.access, history, prevLocation.pathname]);
+ }, []);
useEffect(() => {
if (hasAccess) {
- sessionStorage.removeItem('gePortalLoggedOut');
history.push(prevLocation.pathname);
}
}, [hasAccess, history, prevLocation.pathname]);
@@ -71,20 +64,19 @@ function EPLogin(props) {
}
const res = await dispatch(loginBMUser({ email: enteredEmail, password: enterPassword }));
// server side error validation
- if (res.statusText !== 'OK') {
- if (res.status === 422) {
+ if (!res || res.status !== 200) {
+ if (res && res.status === 422) {
return setValidationError({
label: res.data.label,
message: res.data.message,
});
}
return setValidationError({
- label: '',
- message: '',
+ label: 'form',
+ message: 'Login failed. Please check your credentials and try again.',
});
}
// initiate push to EP if validated (ie received token)
- sessionStorage.removeItem('gePortalLoggedOut');
return setHasAccess(!!res.data.token);
};
@@ -125,6 +117,9 @@ function EPLogin(props) {
{validationError.message}
)}
+ {validationError && validationError.label === 'form' && (
+
{validationError.message}
+ )}
Submit
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..b1695c0692
--- /dev/null
+++ b/src/components/EductionPortal/SideBar/SideBar.module.css
@@ -0,0 +1,449 @@
+/* stylelint-disable declaration-property-value-keyword-no-deprecated, no-descending-specificity */
+
+/* ===== 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 (width >= 992px) {
+ /* Desktop: sidebar visible by default */
+}
+
+/* ===== RESPONSIVE - TABLET (768px - 991px) ===== */
+@media (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 (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;
+ overflow-wrap: break-word;
+ }
+}
+
+/* ===== RESPONSIVE - SMALL PHONES (≤480px) ===== */
+@media (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 (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;
+ 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
index 574745d655..51664b0fd1 100644
--- a/src/components/EductionPortal/SidebarContext.jsx
+++ b/src/components/EductionPortal/SidebarContext.jsx
@@ -1,28 +1,15 @@
-import React, { createContext, useEffect, useMemo, useState } from 'react';
+import React, { createContext, useState } from 'react';
export const SidebarContext = createContext();
export const SidebarProvider = ({ children }) => {
- const [isMinimized, setIsMinimized] = useState(() => {
- try {
- return localStorage.getItem('ep.sidebar.minimized') === 'true';
- } catch {
- // localStorage unavailable (private browsing / SSR)
- return false;
- }
- });
+ const [isMinimized, setIsMinimized] = useState(false);
- useEffect(() => {
- try {
- localStorage.setItem('ep.sidebar.minimized', isMinimized ? 'true' : 'false');
- } catch {
- // localStorage unavailable — silently ignore
- }
- }, [isMinimized]);
-
- const value = useMemo(() => ({ isMinimized, setIsMinimized }), [isMinimized]);
-
- return
{children} ;
+ return (
+
+ {children}
+
+ );
};
export const useSidebar = () => {
diff --git a/src/components/EductionPortal/StudentTasks/StudentDashboard.jsx b/src/components/EductionPortal/StudentTasks/StudentDashboard.jsx
index d64a5b4598..2f3f7746f5 100644
--- a/src/components/EductionPortal/StudentTasks/StudentDashboard.jsx
+++ b/src/components/EductionPortal/StudentTasks/StudentDashboard.jsx
@@ -1,6 +1,7 @@
import React from 'react';
import { useHistory } from 'react-router-dom';
import { useSelector } from 'react-redux';
+import Sidebar from './StudentSidebar';
import styles from './StudentDashboard.module.css';
const LIFE_CARD_IDS = ['lc-a', 'lc-b', 'lc-c', 'lc-d', 'lc-e', 'lc-f'];
@@ -43,6 +44,7 @@ export default function StudentDashboard() {
return (
+
Dashboard
diff --git a/src/components/EductionPortal/StudentTasks/StudentDashboard.module.css b/src/components/EductionPortal/StudentTasks/StudentDashboard.module.css
index f5515ef8dc..fe18de7f51 100644
--- a/src/components/EductionPortal/StudentTasks/StudentDashboard.module.css
+++ b/src/components/EductionPortal/StudentTasks/StudentDashboard.module.css
@@ -1,5 +1,6 @@
/* stylelint-disable */
.pageLayout {
+ display: flex;
min-height: calc(100vh - 72px);
background: #f9fafb;
}
diff --git a/src/components/EductionPortal/StudentTasks/StudentSidebar.jsx b/src/components/EductionPortal/StudentTasks/StudentSidebar.jsx
new file mode 100644
index 0000000000..1aab8f1904
--- /dev/null
+++ b/src/components/EductionPortal/StudentTasks/StudentSidebar.jsx
@@ -0,0 +1,163 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { useSelector } from 'react-redux';
+import styles from './StudentSidebar.module.css';
+
+function Icon({ name }) {
+ const commonProps = { 'aria-hidden': 'true', focusable: 'false' };
+ const icons = {
+ menu: (
+
+
+
+ ),
+ home: (
+
+
+
+ ),
+ chart: (
+
+
+
+ ),
+ folder: (
+
+
+
+ ),
+ star: (
+
+
+
+ ),
+ calendar: (
+
+
+
+ ),
+ pencil: (
+
+
+
+ ),
+ cog: (
+
+
+
+ ),
+ logout: (
+
+
+
+ ),
+ };
+ return
{icons[name] || null} ;
+}
+
+Icon.propTypes = {
+ name: PropTypes.string.isRequired,
+};
+
+export default function Sidebar({ active, onLogout }) {
+ const darkMode = useSelector(state => state.theme?.darkMode);
+ const safeLogout = onLogout || (() => {});
+
+ return (
+
+
+
+
+
+
+ {['home', 'chart', 'folder', 'star', 'calendar', 'pencil'].map(icon => (
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+Sidebar.propTypes = {
+ active: PropTypes.string,
+ onLogout: PropTypes.func,
+};
+
+Sidebar.defaultProps = {
+ active: 'home',
+ onLogout: undefined,
+};
diff --git a/src/components/EductionPortal/StudentTasks/StudentSidebar.module.css b/src/components/EductionPortal/StudentTasks/StudentSidebar.module.css
new file mode 100644
index 0000000000..74bef09372
--- /dev/null
+++ b/src/components/EductionPortal/StudentTasks/StudentSidebar.module.css
@@ -0,0 +1,142 @@
+/* stylelint-disable */
+:root {
+ --rail-w: 72px;
+ --header-h: 72px;
+ --rail-bg: #fff;
+ --rail-border: #ececec;
+ --icon: #000;
+ --pill: #dedede;
+ --pill-hover: #e9e9e9;
+ --radius: 10px;
+}
+
+/* ✅ Fixed to viewport, not within scrollable container */
+.sidebar {
+ position: sticky;
+ top: 72px;
+ width: 72px;
+ height: calc(100vh - 72px);
+ background: #fff;
+ border-right: 1px solid #ececec;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ box-sizing: border-box;
+ z-index: 10;
+ overflow: hidden auto;
+ scrollbar-width: thin;
+}
+
+.hamburger {
+ width: 44px;
+ height: 44px;
+ margin: 8px 0 6px;
+ border: none;
+ background: transparent;
+ color: var(--icon);
+ display: grid;
+ place-items: center;
+ cursor: pointer;
+}
+
+.icon {
+ width: 22px;
+ height: 22px;
+ color: var(--icon);
+ display: inline-grid;
+ place-items: center;
+}
+
+.nav {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 12px;
+ padding: 12px 0;
+ flex: 1;
+ padding-bottom: 110px;
+ box-sizing: border-box;
+}
+
+.navItem {
+ width: 100%;
+ height: 56px;
+ border: none;
+ background: transparent;
+ border-radius: var(--radius);
+ display: grid;
+ place-items: center;
+ cursor: pointer;
+ transition: background 0.15s ease;
+}
+
+.navItem:hover {
+ background: var(--pill-hover);
+}
+
+.active {
+ background: var(--pill);
+}
+
+.bottom {
+ position: sticky;
+ bottom: 0;
+ width: 100%;
+ background: #fff;
+ border-top: 1px solid #ececec;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 10px;
+ padding: 10px 0 12px;
+ box-sizing: border-box;
+ z-index: 5;
+}
+
+.bottomIcon {
+ width: 44px;
+ height: 44px;
+ display: grid;
+ place-items: center;
+ background: transparent;
+ border: none;
+ border-radius: 8px;
+ color: #000;
+ cursor: pointer;
+}
+
+.bottomIcon:hover {
+ background: var(--pill-hover);
+}
+
+/* ===== Dark mode for sidebar ===== */
+.sidebarDark {
+ background: #0f172a;
+ border-right: 1px solid #1f2937;
+}
+
+.sidebarDark .icon {
+ color: #e5e7eb;
+}
+
+.sidebarDark .navItem:hover {
+ background: #111827;
+}
+
+.sidebarDark .active {
+ background: #1f2937;
+}
+
+.sidebarDark .bottom {
+ background: #0f172a;
+ border-top: 1px solid #1f2937;
+}
+
+.sidebarDark .bottomIcon {
+ color: #e5e7eb;
+}
+
+.sidebarDark .bottomIcon:hover {
+ background: #111827;
+}
diff --git a/src/components/EductionPortal/StudentTasks/StudentTasks.jsx b/src/components/EductionPortal/StudentTasks/StudentTasks.jsx
index d521f3aaaf..d56ad0e5aa 100644
--- a/src/components/EductionPortal/StudentTasks/StudentTasks.jsx
+++ b/src/components/EductionPortal/StudentTasks/StudentTasks.jsx
@@ -1,15 +1,51 @@
import React, { useState, useEffect, useMemo } from 'react';
-import { useSelector } from 'react-redux';
+import { useSelector, useDispatch } from 'react-redux';
+import Sidebar from './StudentSidebar';
import TaskCard from './TaskCard';
import RubricModal from './RubricModal';
+import { fetchStudentTasks } from '../../../actions/studentTasks';
import styles from './StudentTasks.module.css';
const FILTER_OPTIONS = ['All', 'Incomplete', 'Submitted', 'Graded'];
const GROUP_OPTIONS = ['subject', 'colorLevel', 'activityGroup', 'strategy'];
const MS_PER_DAY = 1000 * 60 * 60 * 24;
+// Map API status values to display labels used by TaskCard / filters
+const STATUS_DISPLAY_MAP = {
+ assigned: 'Incomplete',
+ in_progress: 'Incomplete',
+ completed: 'Submitted',
+ graded: 'Graded',
+};
+
+// Normalise a Redux task (flat format from actions) into the shape TaskCard expects
+const normalizeTask = task => ({
+ ...task,
+ title: task.subtitle || task.course_name || 'Untitled Task',
+ subject: task.subject?.name || task.course_name || 'Unknown Subject',
+ colorLevel: task.color_level || 'Unknown',
+ activityGroup: task.activity_group || 'Unassigned',
+ strategy: task.strategy || 'General',
+ description: task.subtitle || '',
+ status: STATUS_DISPLAY_MAP[task.status] || 'Incomplete',
+ progress:
+ task.suggested_total_hours > 0
+ ? Math.round((task.logged_hours / task.suggested_total_hours) * 100)
+ : 0,
+ dueDate: task.dueAt ? new Date(task.dueAt).toISOString().split('T')[0] : 'N/A',
+ logged_hours: task.logged_hours || 0,
+ suggested_total_hours: task.suggested_total_hours || 0,
+});
+
const StudentTasks = () => {
+ const dispatch = useDispatch();
const darkMode = useSelector(state => state.theme?.darkMode);
+ const reduxTasks = useSelector(state => state.studentTasks?.taskItems || []);
+ const loading = useSelector(state => state.studentTasks?.fetching);
+
+ useEffect(() => {
+ dispatch(fetchStudentTasks());
+ }, [dispatch]);
useEffect(() => {
const htmlEl = document.documentElement;
@@ -31,50 +67,7 @@ const StudentTasks = () => {
};
}, [darkMode]);
- const [tasks] = useState([
- {
- id: 1,
- title: 'Activity 1: Technology, Art, Trades, Health',
- subject: 'Technology / Art / Health',
- colorLevel: 'Red',
- activityGroup: 'Creative Projects',
- strategy: 'Teaching Strategy',
- description:
- 'Choose a person listed in the Technology Subject Page and a related trade. Visit at least 1 location and observe 5 professionals in action. Create a blog post or video.',
- status: 'Incomplete',
- progress: 25,
- dueDate: '2025-10-15',
- rubric: ['Clarity', 'Creativity', 'Effort'],
- },
- {
- id: 2,
- title: 'Activity 2: Math, Science, Innovation',
- subject: 'Math / Science',
- colorLevel: 'Blue',
- activityGroup: 'Research Assignments',
- strategy: 'Life Strategy',
- description:
- 'Research patterns of climate bands and write a pamphlet showing your findings. Distribute pamphlets to students.',
- status: 'Submitted',
- progress: 50,
- dueDate: '2025-10-20',
- rubric: ['Accuracy', 'Presentation', 'Depth of Research'],
- },
- {
- id: 3,
- title: 'Activity 3: Social Sciences, English, Values',
- subject: 'Social Sciences / English',
- colorLevel: 'Violet',
- activityGroup: 'Written Work',
- strategy: 'Teaching Strategy',
- description:
- 'Write a 10–15 page research paper on cultural development. Include fictional story and empathy-driven examples.',
- status: 'Graded',
- progress: 80,
- dueDate: '2025-10-25',
- rubric: ['Critical Thinking', 'Empathy', 'Writing Style'],
- },
- ]);
+ const tasks = useMemo(() => reduxTasks.map(normalizeTask), [reduxTasks]);
const [selectedTask, setSelectedTask] = useState(null);
const [filter, setFilter] = useState('All');
@@ -139,6 +132,8 @@ const StudentTasks = () => {
{darkMode &&
}
+
+
{
))}
+ {loading &&
Loading tasks…
}
+
+ {!loading && groupKeys.length === 0 && (
+
No tasks found.
+ )}
{groupKeys.map(key => (