|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Teacher Portal - Smart Learn</title> |
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet"> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"> |
|
<style> |
|
:root { |
|
--primary-color: #3498db; |
|
--secondary-color: #2c3e50; |
|
--background-color: rgba(236, 240, 241, 0.8); |
|
--text-color: #333; |
|
--card-background: #fff; |
|
} |
|
|
|
body { |
|
font-family: 'Roboto', sans-serif; |
|
margin: 0; |
|
padding: 0; |
|
background-color: var(--background-color); |
|
color: var(--text-color); |
|
line-height: 1.6; |
|
background-image: url('https://i.pinimg.com/736x/d0/b1/39/d0b1395ab921f995d3340b4a45007dd2.jpg'); |
|
background-size: cover; |
|
background-position: center; |
|
background-attachment: fixed; |
|
} |
|
|
|
.teacher-portal { |
|
max-width: 1200px; |
|
margin: 40px auto; |
|
padding: 30px; |
|
background: var(--card-background); |
|
border-radius: 15px; |
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
.header { |
|
text-align: center; |
|
margin-bottom: 40px; |
|
position: relative; |
|
} |
|
|
|
.header h1 { |
|
font-size: 3em; |
|
margin-bottom: 10px; |
|
color: var(--primary-color); |
|
letter-spacing: 1px; |
|
text-transform: uppercase; |
|
} |
|
|
|
.header p { |
|
font-size: 1.2em; |
|
color: var(--secondary-color); |
|
} |
|
|
|
.dashboard { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); |
|
gap: 30px; |
|
margin-bottom: 40px; |
|
} |
|
|
|
.dashboard-card { |
|
background: var(--card-background); |
|
border-radius: 10px; |
|
padding: 20px; |
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); |
|
transition: transform 0.3s ease; |
|
text-align: center; |
|
} |
|
|
|
.dashboard-card:hover { |
|
transform: translateY(-5px); |
|
} |
|
|
|
.dashboard-card h3 { |
|
font-size: 1.5em; |
|
color: var(--primary-color); |
|
margin-bottom: 15px; |
|
} |
|
|
|
.dashboard-card p { |
|
font-size: 2em; |
|
font-weight: bold; |
|
color: var(--secondary-color); |
|
margin: 0; |
|
} |
|
|
|
.dashboard-card i { |
|
font-size: 3em; |
|
color: var(--primary-color); |
|
margin-bottom: 15px; |
|
} |
|
|
|
#student-list { |
|
background: var(--card-background); |
|
border-radius: 10px; |
|
padding: 20px; |
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
#student-list h3 { |
|
font-size: 1.8em; |
|
color: var(--primary-color); |
|
margin-bottom: 20px; |
|
text-align: center; |
|
} |
|
|
|
.student-grid { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); |
|
gap: 20px; |
|
} |
|
|
|
.student-card { |
|
background: var(--background-color); |
|
border-radius: 8px; |
|
padding: 15px; |
|
text-align: center; |
|
transition: transform 0.3s ease, box-shadow 0.3s ease; |
|
} |
|
|
|
.student-card:hover { |
|
transform: translateY(-5px); |
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
.student-card h4 { |
|
margin: 0 0 10px; |
|
color: var(--secondary-color); |
|
} |
|
|
|
.student-card p { |
|
margin: 5px 0; |
|
font-size: 0.9em; |
|
color: var(--text-color); |
|
} |
|
|
|
.button-container { |
|
text-align: center; |
|
margin-top: 30px; |
|
} |
|
|
|
button { |
|
background: var(--primary-color); |
|
color: white; |
|
border: none; |
|
padding: 12px 25px; |
|
font-size: 1em; |
|
border-radius: 5px; |
|
cursor: pointer; |
|
transition: background 0.3s, transform 0.3s; |
|
text-transform: uppercase; |
|
letter-spacing: 1px; |
|
} |
|
|
|
button:hover { |
|
background: #2980b9; |
|
transform: translateY(-2px); |
|
} |
|
|
|
#timetable-generator { |
|
margin-top: 40px; |
|
background: var(--card-background); |
|
border-radius: 10px; |
|
padding: 20px; |
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
#timetable-generator h3 { |
|
font-size: 1.8em; |
|
color: var(--primary-color); |
|
margin-bottom: 20px; |
|
text-align: center; |
|
} |
|
|
|
#timetable-generator form { |
|
display: grid; |
|
gap: 10px; |
|
max-width: 500px; |
|
margin: 0 auto; |
|
} |
|
|
|
#timetable-generator label { |
|
font-size: 1em; |
|
font-weight: bold; |
|
} |
|
|
|
#timetable-generator input { |
|
padding: 10px; |
|
border: 1px solid #ccc; |
|
border-radius: 5px; |
|
font-size: 1em; |
|
} |
|
|
|
#timetable-generator button { |
|
background: var(--primary-color); |
|
color: white; |
|
border: none; |
|
padding: 12px; |
|
font-size: 1em; |
|
border-radius: 5px; |
|
cursor: pointer; |
|
transition: background 0.3s, transform 0.3s; |
|
margin-top: 20px; |
|
} |
|
|
|
#timetable-generator button:hover { |
|
background: #2980b9; |
|
transform: translateY(-2px); |
|
} |
|
|
|
#timetable-result { |
|
margin-top: 20px; |
|
padding: 15px; |
|
background: #fff; |
|
border-radius: 5px; |
|
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1); |
|
white-space: pre-wrap; |
|
} |
|
|
|
.fade-in { |
|
animation: fadeIn 0.5s ease-in; |
|
} |
|
|
|
@keyframes fadeIn { |
|
from { opacity: 0; } |
|
to { opacity: 1; } |
|
} |
|
.navbar { |
|
background-color: var(--primary-color); |
|
padding: 10px 0; |
|
position: sticky; |
|
top: 0; |
|
z-index: 1000; |
|
} |
|
|
|
.navbar ul { |
|
list-style-type: none; |
|
margin: 0; |
|
padding: 0; |
|
display: flex; |
|
justify-content: center; |
|
} |
|
|
|
.navbar li { |
|
margin: 0 15px; |
|
} |
|
|
|
.navbar a { |
|
color: white; |
|
text-decoration: none; |
|
font-size: 1.1em; |
|
transition: color 0.3s; |
|
} |
|
|
|
.navbar a:hover { |
|
color: var(--secondary-color); |
|
} |
|
.modal { |
|
display: none; |
|
position: fixed; |
|
z-index: 1; |
|
left: 0; |
|
top: 0; |
|
width: 100%; |
|
height: 100%; |
|
overflow: auto; |
|
background-color: rgba(0,0,0,0.4); |
|
} |
|
|
|
.modal-content { |
|
background-color: #fefefe; |
|
margin: 15% auto; |
|
padding: 20px; |
|
border: 1px solid #888; |
|
width: 80%; |
|
max-width: 600px; |
|
border-radius: 10px; |
|
} |
|
|
|
.close { |
|
color: #aaa; |
|
float: right; |
|
font-size: 28px; |
|
font-weight: bold; |
|
} |
|
|
|
.close:hover, |
|
.close:focus { |
|
color: black; |
|
text-decoration: none; |
|
cursor: pointer; |
|
} |
|
|
|
#generate-ai-report { |
|
background-color: var(--primary-color); |
|
color: white; |
|
border: none; |
|
padding: 10px 20px; |
|
margin-top: 20px; |
|
cursor: pointer; |
|
border-radius: 5px; |
|
} |
|
|
|
#generate-ai-report:hover { |
|
background-color: #2980b9; |
|
} |
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap'); |
|
|
|
:root { |
|
--primary-color: #4e54c8; |
|
--secondary-color: #8f94fb; |
|
--accent-color: #ff6b6b; |
|
--text-color: #333; |
|
--bg-color: #f9f9f9; |
|
} |
|
|
|
body { |
|
font-family: 'Poppins', sans-serif; |
|
margin: 0; |
|
padding: 0; |
|
background-color: var(--bg-color); |
|
color: var(--text-color); |
|
line-height: 1.6; |
|
} |
|
|
|
.container { |
|
max-width: 1340px; |
|
margin: 0 auto; |
|
padding: 0 20px; |
|
} |
|
|
|
header { |
|
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); |
|
padding: 15px 0; |
|
position: sticky; |
|
top: 0; |
|
z-index: 1000; |
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1); |
|
} |
|
|
|
.header-content { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
} |
|
|
|
.logo { |
|
font-size: 28px; |
|
font-weight: 700; |
|
color: #fff; |
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.1); |
|
} |
|
|
|
.search-bar { |
|
flex-grow: 1; |
|
margin: 0 20px; |
|
position: relative; |
|
} |
|
|
|
.search-bar input { |
|
width: 100%; |
|
padding: 12px 20px; |
|
border: none; |
|
border-radius: 30px; |
|
font-size: 16px; |
|
background-color: rgba(255,255,255,0.2); |
|
color: #fff; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.search-bar input::placeholder { |
|
color: rgba(255,255,255,0.7); |
|
} |
|
|
|
.search-bar input:focus { |
|
background-color: rgba(255,255,255,0.3); |
|
outline: none; |
|
} |
|
|
|
.ai-tools { |
|
position: absolute; |
|
right: 10px; |
|
top: 50%; |
|
transform: translateY(-50%); |
|
} |
|
|
|
.ai-tools i { |
|
font-size: 20px; |
|
margin-left: 15px; |
|
cursor: pointer; |
|
color: #fff; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.ai-tools i:hover { |
|
color: var(--accent-color); |
|
transform: scale(1.1); |
|
} |
|
|
|
.user-actions { |
|
display: flex; |
|
align-items: center; |
|
} |
|
|
|
.points-display { |
|
font-size: 18px; |
|
font-weight: bold; |
|
color: #fff; |
|
margin-right: 20px; |
|
background-color: rgba(255,255,255,0.2); |
|
padding: 5px 15px; |
|
border-radius: 20px; |
|
} |
|
|
|
.profile-icon { |
|
width: 40px; |
|
height: 40px; |
|
border-radius: 50%; |
|
background-color: var(--accent-color); |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
font-weight: bold; |
|
color: #fff; |
|
cursor: pointer; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.profile-icon:hover { |
|
transform: scale(1.1); |
|
} |
|
|
|
.nav-bar { |
|
background-color: #fff; |
|
padding: 10px 0; |
|
box-shadow: 0 2px 5px rgba(0,0,0,0.1); |
|
} |
|
|
|
.nav-bar ul { |
|
list-style-type: none; |
|
margin: 0; |
|
padding: 0; |
|
display: flex; |
|
justify-content: center; |
|
} |
|
|
|
.nav-bar li { |
|
margin: 0 15px; |
|
} |
|
|
|
.nav-bar a { |
|
text-decoration: none; |
|
color: var(--text-color); |
|
font-weight: 600; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.nav-bar a:hover { |
|
color: var(--primary-color); |
|
} |
|
|
|
.hero { |
|
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); |
|
padding: 25px 0; |
|
text-align: center; |
|
color: #fff; |
|
position: relative; |
|
overflow: hidden; |
|
} |
|
|
|
.hero::before { |
|
content: ''; |
|
position: absolute; |
|
top: 0; |
|
left: 0; |
|
right: 0; |
|
bottom: 0; |
|
background: url('https://source.unsplash.com/random/1600x900?education') no-repeat center center; |
|
background-size: cover; |
|
opacity: 0.1; |
|
z-index: 0; |
|
} |
|
|
|
.hero-content { |
|
position: relative; |
|
z-index: 1; |
|
} |
|
|
|
.hero h1 { |
|
font-size: 48px; |
|
margin-bottom: 20px; |
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.3); |
|
} |
|
|
|
.hero p { |
|
font-size: 20px; |
|
margin-bottom: 30px; |
|
text-shadow: 1px 1px 2px rgba(0,0,0,0.2); |
|
} |
|
|
|
.btn { |
|
display: inline-block; |
|
background-color: var(--accent-color); |
|
color: #fff; |
|
padding: 12px 30px; |
|
text-decoration: none; |
|
font-weight: 600; |
|
border-radius: 30px; |
|
transition: all 0.3s ease; |
|
box-shadow: 0 4px 15px rgba(0,0,0,0.2); |
|
} |
|
|
|
.btn:hover { |
|
background-color: #ff4757; |
|
transform: translateY(-3px); |
|
} |
|
|
|
.categories, .features, .learning-section { |
|
padding: 60px 0; |
|
background-color: #fff; |
|
margin: 40px 0; |
|
border-radius: 10px; |
|
box-shadow: 0 5px 15px rgba(0,0,0,0.1); |
|
} |
|
|
|
.section-title { |
|
font-size: 32px; |
|
text-align: center; |
|
margin-bottom: 40px; |
|
color: var(--primary-color); |
|
} |
|
|
|
.category-list, .feature-grid, .learning-grid { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); |
|
gap: 30px; |
|
} |
|
|
|
.category-item, .feature-card, .learning-item { |
|
background-color: #fff; |
|
border-radius: 10px; |
|
padding: 20px; |
|
text-align: center; |
|
transition: all 0.3s ease; |
|
box-shadow: 0 5px 15px rgba(0,0,0,0.1); |
|
} |
|
|
|
.category-item:hover, .feature-card:hover, .learning-item:hover { |
|
transform: translateY(-10px); |
|
box-shadow: 0 15px 30px rgba(0,0,0,0.2); |
|
} |
|
|
|
.feature-grid { |
|
display: grid; |
|
grid-template-columns: repeat(3, 1fr); |
|
grid-gap: 20px; |
|
} |
|
|
|
.feature-card { |
|
background: #fff; |
|
border: 1px solid #ddd; |
|
border-radius: 8px; |
|
padding: 20px; |
|
text-align: center; |
|
} |
|
|
|
.feature-card img { |
|
max-width: 100%; |
|
border-radius: 8px; |
|
margin-bottom: 15px; |
|
} |
|
.search-bar { |
|
flex-grow: 1; |
|
margin: 0 20px; |
|
position: relative; |
|
max-width: 900px; |
|
} |
|
.profile-sidebar { |
|
display: none; |
|
position: fixed; |
|
top: 0; |
|
right: 0; |
|
width: 300px; |
|
height: 100%; |
|
background-color: #fff; |
|
box-shadow: -2px 0 5px rgba(0,0,0,0.1); |
|
padding: 20px; |
|
overflow-y: auto; |
|
} |
|
|
|
.feature-card h3 { |
|
margin: 10px 0; |
|
} |
|
|
|
.feature-card p { |
|
margin: 10px 0 20px; |
|
} |
|
|
|
.feature-card .btn { |
|
display: inline-block; |
|
padding: 10px 20px; |
|
background-color: #007BFF; |
|
color: #fff; |
|
text-decoration: none; |
|
border-radius: 4px; |
|
} |
|
#subjects-container { |
|
max-width: 600px; |
|
margin: 0 auto; |
|
padding: 30px; |
|
background: var(--card-background); |
|
border-radius: 15px; |
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
gap: 30px; |
|
} |
|
|
|
#subjects-container h3 { |
|
font-size: 1.8em; |
|
color: var(--primary-color); |
|
margin-bottom: 20px; |
|
text-align: center; |
|
} |
|
|
|
.subject-card { |
|
background: var(--card-background); |
|
border-radius: 10px; |
|
padding: 20px; |
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); |
|
transition: transform 0.3s ease; |
|
text-align: center; |
|
width: 100%; |
|
} |
|
|
|
.subject-card:hover { |
|
transform: translateY(-5px); |
|
} |
|
|
|
.subject-card h4 { |
|
font-size: 1.5em; |
|
color: var(--primary-color); |
|
margin-bottom: 15px; |
|
} |
|
|
|
.subject-card p { |
|
font-size: 1em; |
|
color: var(--secondary-color); |
|
margin: 0; |
|
} |
|
|
|
.spinner { |
|
text-align: center; |
|
margin-top: 20px; |
|
} |
|
.spinner-border { |
|
width: 3rem; |
|
height: 3rem; |
|
border: 5px solid #f3f3f3; |
|
border-top: 5px solid #3498db; |
|
border-radius: 50%; |
|
animation: spin 1s linear infinite; |
|
} |
|
@keyframes spin { |
|
0% { transform: rotate(0deg); } |
|
100% { transform: rotate(360deg); } |
|
} |
|
|
|
.timetable-container { |
|
display: flex; |
|
flex-wrap: wrap; |
|
justify-content: space-around; |
|
gap: 20px; |
|
margin-top: 30px; |
|
} |
|
|
|
.day-table { |
|
background-color: #fff; |
|
border-radius: 10px; |
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
|
padding: 15px; |
|
width: calc(33.33% - 20px); |
|
margin-bottom: 20px; |
|
} |
|
|
|
.day-table h3 { |
|
color: var(--primary-color); |
|
margin-top: 0; |
|
margin-bottom: 15px; |
|
text-align: center; |
|
} |
|
|
|
.day-table table { |
|
width: 100%; |
|
border-collapse: collapse; |
|
} |
|
|
|
.day-table th, .day-table td { |
|
border: 1px solid #ddd; |
|
padding: 8px; |
|
text-align: left; |
|
} |
|
|
|
.day-table th { |
|
background-color: #f2f2f2; |
|
} |
|
|
|
@media (max-width: 768px) { |
|
.day-table { |
|
width: 100%; |
|
} |
|
} .timetable-container { |
|
display: flex; |
|
flex-wrap: wrap; |
|
justify-content: space-around; |
|
gap: 20px; |
|
margin-top: 30px; |
|
} |
|
|
|
.day-table { |
|
background-color: #fff; |
|
border-radius: 10px; |
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
|
padding: 15px; |
|
width: calc(33.33% - 20px); |
|
margin-bottom: 20px; |
|
} |
|
html { |
|
scroll-behavior: smooth; |
|
} |
|
|
|
.day-table h3 { |
|
color: var(--primary-color); |
|
margin-top: 0; |
|
margin-bottom: 15px; |
|
text-align: center; |
|
} |
|
|
|
.day-table table { |
|
width: 100%; |
|
border-collapse: collapse; |
|
} |
|
.loading-circle { |
|
display: none; |
|
width: 20px; |
|
height: 20px; |
|
border: 3px solid #f3f3f3; |
|
border-top: 3px solid #3498db; |
|
border-radius: 50%; |
|
animation: spin 1s linear infinite; |
|
margin-left: 10px; |
|
} |
|
|
|
@keyframes spin { |
|
0% { transform: rotate(0deg); } |
|
100% { transform: rotate(360deg); } |
|
} |
|
|
|
.day-table th, .day-table td { |
|
border: 1px solid #ddd; |
|
padding: 8px; |
|
text-align: left; |
|
} |
|
|
|
.day-table th { |
|
background-color: #f2f2f2; |
|
} |
|
|
|
@media (max-width: 768px) { |
|
.day-table { |
|
width: 100%; |
|
} |
|
} |
|
|
|
@media (max-width: 768px) { |
|
.feature-grid { |
|
grid-template-columns: 1fr; |
|
} |
|
} |
|
|
|
</style> |
|
</head> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"> |
|
<body> |
|
<header> |
|
<div class="container"> |
|
<div class="header-content"> |
|
<div class="logo">SmartLearn</div> |
|
<div class="search-bar"> |
|
<input type="text" placeholder="Search for anything"> |
|
<div class="ai-tools"> |
|
<i class="fas fa-camera" title="Photo Question Answering"></i> |
|
<i class="fas fa-brain" title="AI Tutor"></i> |
|
<i class="fas fa-robot" title="AI Assistant"></i> |
|
</div> |
|
</div> |
|
<div class="user-actions"> |
|
|
|
<div class="profile-icon" id="profile-icon">{{ teacher.name[0] }}</div> |
|
|
|
<div id="profile-sidebar" class="profile-sidebar"> |
|
<button id="close-profile" class="close-button">×</button> |
|
|
|
<div class="profile-header"> |
|
<img src="https://via.placeholder.com/150" alt="Teacher Avatar" class="avatar"> |
|
<h2>{{ teacher.name }}</h2> |
|
<p>Teacher ID: {{ teacher.id }}</p> |
|
</div> |
|
|
|
<div class="profile-info"> |
|
<p><strong>School:</strong> {{ teacher.school }}</p> |
|
<p><strong>Date of Birth:</strong> {{ teacher.dob }}</p> |
|
<p><strong>Email:</strong> {{ teacher.email }}</p> |
|
</div> |
|
|
|
<div class="subjects"> |
|
<h3>Subjects Taught</h3> |
|
<ul> |
|
{% for subject in teacher.subjects_taught %} |
|
<li>{{ subject }}</li> |
|
{% endfor %} |
|
</ul> |
|
|
|
<h3>Classes</h3> |
|
<ul> |
|
{% for class in teacher.classes %} |
|
<li>{{ class }}</li> |
|
{% endfor %} |
|
</ul> |
|
</div> |
|
|
|
<div class="performance-graph"> |
|
<h3>Weekly Class Performance</h3> |
|
<canvas id="performanceChart"></canvas> |
|
</div> |
|
|
|
<div class="additional-info"> |
|
<h3>Qualifications</h3> |
|
<ul> |
|
{% for qualification in teacher.qualifications %} |
|
<li>{{ qualification }}</li> |
|
{% endfor %} |
|
</ul> |
|
|
|
<h3>Years of Experience</h3> |
|
<p>{{ teacher.years_of_experience }}</p> |
|
</div> |
|
|
|
<a href="{{ url_for('index') }}" style="color: #ff4757; text-align: center;"><h2>Log out</h2></a> |
|
</div> |
|
|
|
</header> |
|
|
|
<nav class="nav-bar"> |
|
<ul> |
|
<li><a href="{{ url_for('teacher') }}"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li> |
|
<li><a href="{{ url_for('generate_paper') }}"><i class="fas fa-file-alt"></i> Generate Paper</a></li> |
|
<li><a href="{{ url_for('eval') }}"><i class="fas fa-check-circle"></i> Evaluate</a></li> |
|
<li><a href="#student-list"><i class="fas fa-chart-bar"></i> Generate Report</a></li> |
|
<li><a href="#timetable-generator"><i class="fas fa-calendar-alt"></i> Generate Timetable</a></li> |
|
<li><a href="{{ url_for('ai_timetable') }}"><i class="fas fa-calendar-alt"></i>Slow Learner</a></li> |
|
</ul> |
|
</nav> |
|
|
|
|
|
<div class="teacher-portal fade-in"> |
|
<div class="header"> |
|
<h1>Teacher Portal</h1> |
|
<p>Welcome, <span id="teacher-name-display"></span>!</p> |
|
</div> |
|
<div class="dashboard"> |
|
<div class="dashboard-card"> |
|
<i class="fas fa-user-graduate"></i> |
|
<h3>Total Students</h3> |
|
<p id="total-students"></p> |
|
</div> |
|
<div class="dashboard-card"> |
|
<i class="fas fa-chart-line"></i> |
|
<h3>Average CGPA</h3> |
|
<p id="average-cgpa"></p> |
|
</div> |
|
<div class="dashboard-card"> |
|
<i class="fas fa-clipboard-check"></i> |
|
<h3>Average AI Test Score</h3> |
|
<p id="average-ai-score"></p> |
|
</div> |
|
</div> |
|
<div id="student-list"> |
|
<h3>Student List</h3> |
|
<div class="student-grid" id="student-grid"></div> |
|
</div> |
|
<div id="student-details" class="modal"> |
|
<div class="modal-content"> |
|
<span class="close">×</span> |
|
<div id="student-expanded-info"></div> |
|
<button id="generate-ai-report">Generate AI Report</button> |
|
</div> |
|
</div> |
|
<div class="button-container"> |
|
<button onclick="window.location.href='index.html'">Back to Home</button> |
|
</div> |
|
<div id="timetable-generator"> |
|
<h3>Generate Timetable</h3> |
|
<form id="timetable-form"> |
|
<label for="hours-per-day">Hours per Day:</label> |
|
<input type="number" id="hours-per-day" name="hours_per_day" required> |
|
|
|
<label for="days-per-week">Days per Week:</label> |
|
<input type="number" id="days-per-week" name="days_per_week" required> |
|
|
|
<label for="semester-end-date">Semester End Date:</label> |
|
<input type="date" id="semester-end-date" name="semester_end_date" required> |
|
|
|
<label for="number-of-subjects">Number of Subjects:</label> |
|
<input type="number" id="number-of-subjects" name="number_of_subjects" required> |
|
|
|
<div id="subjects-container"> |
|
|
|
</div> |
|
<button type="submit">Generate Timetable</button> |
|
<div id="timetable-spinner" class="spinner"></div> |
|
</form> |
|
<div id="timetable-result"></div> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
document.addEventListener('DOMContentLoaded', function() { |
|
const teacherName = localStorage.getItem('teacherName'); |
|
document.getElementById('teacher-name-display').textContent = teacherName || 'Teacher'; |
|
|
|
const studentGrid = document.getElementById('student-grid'); |
|
const studentDetails = document.getElementById('student-details'); |
|
const studentExpandedInfo = document.getElementById('student-expanded-info'); |
|
const closeBtn = document.querySelector('.close'); |
|
const generateAIReportBtn = document.getElementById('generate-ai-report'); |
|
|
|
fetch('/get_students') |
|
.then(response => response.json()) |
|
.then(students => { |
|
let totalCGPA = 0; |
|
let totalAIScore = 0; |
|
|
|
students.forEach(student => { |
|
const studentCard = document.createElement('div'); |
|
studentCard.className = 'student-card'; |
|
studentCard.innerHTML = ` |
|
<h4>${student.name}</h4> |
|
<p>Age: ${student.age}</p> |
|
<p>CGPA: ${student.cgpa}</p> |
|
<p>Course: ${student.course_pursuing}</p> |
|
<p>Assigned Test Score: ${student.assigned_test_score}</p> |
|
`; |
|
studentCard.addEventListener('click', () => showStudentDetails(student)); |
|
studentGrid.appendChild(studentCard); |
|
|
|
totalCGPA += student.cgpa; |
|
totalAIScore += student.ai_test_score; |
|
}); |
|
|
|
const totalStudents = students.length; |
|
const averageCGPA = totalStudents > 0 ? totalCGPA / totalStudents : 0; |
|
const averageAIScore = totalStudents > 0 ? totalAIScore / totalStudents : 0; |
|
|
|
document.getElementById('total-students').textContent = totalStudents; |
|
document.getElementById('average-cgpa').textContent = averageCGPA.toFixed(2); |
|
document.getElementById('average-ai-score').textContent = averageAIScore.toFixed(2); |
|
}) |
|
.catch(error => { |
|
console.error('Error fetching student data:', error); |
|
}); |
|
|
|
function showStudentDetails(student) { |
|
studentExpandedInfo.innerHTML = ` |
|
<h2>${student.name}</h2> |
|
<p>Age: ${student.age}</p> |
|
<p>CGPA: ${student.cgpa}</p> |
|
<p>Course: ${student.course_pursuing}</p> |
|
<p>Assigned Test Score: ${student.assigned_test_score}</p> |
|
<p>AI Test Score: ${student.ai_test_score}</p> |
|
<p>Interests: ${student.interests}</p> |
|
<p>Difficulty in: ${student.difficulty_in}</p> |
|
<p>Courses Taken: ${student.courses_taken}</p> |
|
`; |
|
studentExpandedInfo.dataset.studentData = JSON.stringify(student); |
|
studentDetails.style.display = 'block'; |
|
} |
|
|
|
closeBtn.onclick = function() { |
|
studentDetails.style.display = 'none'; |
|
} |
|
|
|
generateAIReportBtn.onclick = function() { |
|
const studentData = JSON.parse(studentExpandedInfo.dataset.studentData); |
|
|
|
const loadingCircle = document.createElement('div'); |
|
loadingCircle.className = 'loading-circle'; |
|
this.appendChild(loadingCircle); |
|
|
|
loadingCircle.style.display = 'inline-block'; |
|
this.disabled = true; |
|
|
|
fetch('/generate_report', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
}, |
|
body: JSON.stringify(studentData), |
|
}) |
|
.then(response => response.json()) |
|
.then(data => { |
|
const reportDiv = document.createElement('div'); |
|
reportDiv.innerHTML = `<h3>AI Generated Report</h3><p>${data.report}</p>`; |
|
studentExpandedInfo.appendChild(reportDiv); |
|
}) |
|
.catch((error) => { |
|
console.error('Error:', error); |
|
alert('Error generating AI report'); |
|
}) |
|
.finally(() => { |
|
loadingCircle.style.display = 'none'; |
|
this.disabled = false; |
|
this.removeChild(loadingCircle); |
|
}); |
|
}; |
|
|
|
window.onclick = function(event) { |
|
if (event.target == studentDetails) { |
|
studentDetails.style.display = 'none'; |
|
} |
|
} |
|
const numberOfSubjectsInput = document.getElementById('number-of-subjects'); |
|
numberOfSubjectsInput.addEventListener('change', function() { |
|
const subjectsContainer = document.getElementById('subjects-container'); |
|
subjectsContainer.innerHTML = ''; |
|
|
|
const numberOfSubjects = parseInt(this.value); |
|
for (let i = 0; i < numberOfSubjects; i++) { |
|
const subjectLabel = document.createElement('label'); |
|
subjectLabel.textContent = `Subject ${i + 1}:`; |
|
|
|
const subjectInput = document.createElement('input'); |
|
subjectInput.type = 'text'; |
|
subjectInput.name = `subject_${i + 1}`; |
|
subjectInput.required = true; |
|
|
|
subjectsContainer.appendChild(subjectLabel); |
|
subjectsContainer.appendChild(subjectInput); |
|
} |
|
}); |
|
|
|
|
|
const timetableForm = document.getElementById('timetable-form'); |
|
const timetableResult = document.getElementById('timetable-result'); |
|
|
|
timetableForm.addEventListener('submit', function(e) { |
|
e.preventDefault(); |
|
|
|
const formData = new FormData(timetableForm); |
|
const subjects = []; |
|
for (let [key, value] of formData.entries()) { |
|
if (key.startsWith('subject_')) { |
|
subjects.push(value); |
|
} |
|
} |
|
|
|
const timetableData = { |
|
hours_per_day: formData.get('hours_per_day'), |
|
days_per_week: formData.get('days_per_week'), |
|
semester_end_date: formData.get('semester_end_date'), |
|
subjects: subjects |
|
}; |
|
|
|
const spinner = document.getElementById('timetable-spinner'); |
|
const submitButton = timetableForm.querySelector('button[type="submit"]'); |
|
|
|
|
|
spinner.style.display = 'block'; |
|
submitButton.disabled = true; |
|
submitButton.style.opacity = '0.5'; |
|
|
|
fetch('/generate_timetable', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json' |
|
}, |
|
body: JSON.stringify(timetableData) |
|
}) |
|
.then(response => { |
|
if (!response.ok) { |
|
throw new Error('Failed to generate timetable'); |
|
} |
|
return response.json(); |
|
}) |
|
.then(data => { |
|
if (data.error) { |
|
timetableResult.textContent = 'Error: ' + data.error; |
|
} else { |
|
timetableResult.textContent = data.timetable; |
|
} |
|
}) |
|
.catch(error => { |
|
timetableResult.textContent = 'Error: ' + error.message; |
|
}) |
|
.finally(() => { |
|
|
|
spinner.style.display = 'none'; |
|
submitButton.disabled = false; |
|
submitButton.style.opacity = '1'; |
|
}); |
|
}); |
|
}); |
|
</script> |
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
|
<script src="static/profile.js"></script> |
|
<script> |
|
document.addEventListener('DOMContentLoaded', function() { |
|
const profileIcon = document.getElementById('profile-icon'); |
|
const profileSidebar = document.getElementById('profile-sidebar'); |
|
const closeProfile = document.getElementById('close-profile'); |
|
|
|
profileIcon.addEventListener('click', function() { |
|
profileSidebar.style.display = 'block'; |
|
}); |
|
|
|
closeProfile.addEventListener('click', function() { |
|
profileSidebar.style.display = 'none'; |
|
}); |
|
}); |
|
</script> |
|
<script> |
|
document.addEventListener('DOMContentLoaded', function() { |
|
const profileIcon = document.getElementById('profile-icon'); |
|
const profileSidebar = document.getElementById('profile-sidebar'); |
|
const closeProfile = document.getElementById('close-profile'); |
|
|
|
profileIcon.addEventListener('click', function() { |
|
profileSidebar.classList.add('active'); |
|
renderPerformanceChart(); |
|
}); |
|
|
|
closeProfile.addEventListener('click', function() { |
|
profileSidebar.classList.remove('active'); |
|
}); |
|
|
|
function renderPerformanceChart() { |
|
const ctx = document.getElementById('performanceChart').getContext('2d'); |
|
|
|
|
|
const data = { |
|
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'], |
|
datasets: [{ |
|
label: 'Performance Score', |
|
data: [65, 72, 68, 80, 75, 85], |
|
fill: false, |
|
borderColor: 'rgb(75, 192, 192)', |
|
tension: 0.1, |
|
pointBackgroundColor: 'rgb(75, 192, 192)', |
|
pointBorderColor: '#fff', |
|
pointHoverBackgroundColor: '#fff', |
|
pointHoverBorderColor: 'rgb(75, 192, 192)' |
|
}] |
|
}; |
|
|
|
const config = { |
|
type: 'line', |
|
data: data, |
|
options: { |
|
responsive: true, |
|
plugins: { |
|
title: { |
|
display: true, |
|
text: 'Weekly Performance' |
|
}, |
|
legend: { |
|
position: 'bottom', |
|
} |
|
}, |
|
scales: { |
|
y: { |
|
beginAtZero: true, |
|
max: 100, |
|
title: { |
|
display: true, |
|
text: 'Score' |
|
} |
|
}, |
|
x: { |
|
title: { |
|
display: true, |
|
text: 'Week' |
|
} |
|
} |
|
} |
|
} |
|
}; |
|
|
|
new Chart(ctx, config); |
|
} |
|
}); |
|
|
|
</script> |
|
|
|
|
|
<script> |
|
|
|
const weeklyPerformanceData = JSON.parse('{{ teacher.weekly_class_performance|tojson|safe }}'); |
|
|
|
|
|
const ctx = document.getElementById('performanceChart').getContext('2d'); |
|
const labels = Object.keys(weeklyPerformanceData); |
|
const datasets = labels.map(label => ({ |
|
label: label, |
|
data: weeklyPerformanceData[label], |
|
borderColor: getRandomColor(), |
|
fill: false |
|
})); |
|
|
|
const performanceChart = new Chart(ctx, { |
|
type: 'line', |
|
data: { |
|
labels: Array.from({length: 7}, (_, i) => `Week ${i + 1}`), |
|
datasets: datasets |
|
}, |
|
options: { |
|
responsive: true, |
|
scales: { |
|
x: { |
|
title: { |
|
display: true, |
|
text: 'Weeks' |
|
} |
|
}, |
|
y: { |
|
title: { |
|
display: true, |
|
text: 'Performance Score' |
|
}, |
|
beginAtZero: true |
|
} |
|
} |
|
} |
|
}); |
|
|
|
function getRandomColor() { |
|
const letters = '0123456789ABCDEF'; |
|
let color = '#'; |
|
for (let i = 0; i < 6; i++) { |
|
color += letters[Math.floor(Math.random() * 16)]; |
|
} |
|
return color; |
|
} |
|
</script> |
|
|
|
</body> |
|
</html> |
|
|
|
|
|
</body> |
|
</html> |