Neurolingua commited on
Commit
1606e9c
1 Parent(s): f28a184

Update templates/teacher.html

Browse files
Files changed (1) hide show
  1. templates/teacher.html +1261 -1319
templates/teacher.html CHANGED
@@ -1,1319 +1,1261 @@
1
-
2
- <!DOCTYPE html>
3
- <html lang="en">
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Teacher Portal - ABC Group of Schools</title>
8
- <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
9
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
10
- <style>
11
- :root {
12
- --primary-color: #3498db;
13
- --secondary-color: #2c3e50;
14
- --background-color: rgba(236, 240, 241, 0.8);
15
- --text-color: #333;
16
- --card-background: #fff;
17
- }
18
-
19
- body {
20
- font-family: 'Roboto', sans-serif;
21
- margin: 0;
22
- padding: 0;
23
- background-color: var(--background-color);
24
- color: var(--text-color);
25
- line-height: 1.6;
26
- background-image: url('https://i.pinimg.com/736x/d0/b1/39/d0b1395ab921f995d3340b4a45007dd2.jpg');
27
- background-size: cover;
28
- background-position: center;
29
- background-attachment: fixed;
30
- }
31
-
32
- .teacher-portal {
33
- max-width: 1200px;
34
- margin: 40px auto;
35
- padding: 30px;
36
- background: var(--card-background);
37
- border-radius: 15px;
38
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
39
- }
40
-
41
- .header {
42
- text-align: center;
43
- margin-bottom: 40px;
44
- position: relative;
45
- }
46
-
47
- .header h1 {
48
- font-size: 3em;
49
- margin-bottom: 10px;
50
- color: var(--primary-color);
51
- letter-spacing: 1px;
52
- text-transform: uppercase;
53
- }
54
-
55
- .header p {
56
- font-size: 1.2em;
57
- color: var(--secondary-color);
58
- }
59
-
60
- .dashboard {
61
- display: grid;
62
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
63
- gap: 30px;
64
- margin-bottom: 40px;
65
- }
66
-
67
- .dashboard-card {
68
- background: var(--card-background);
69
- border-radius: 10px;
70
- padding: 20px;
71
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
72
- transition: transform 0.3s ease;
73
- text-align: center;
74
- }
75
-
76
- .dashboard-card:hover {
77
- transform: translateY(-5px);
78
- }
79
-
80
- .dashboard-card h3 {
81
- font-size: 1.5em;
82
- color: var(--primary-color);
83
- margin-bottom: 15px;
84
- }
85
-
86
- .dashboard-card p {
87
- font-size: 2em;
88
- font-weight: bold;
89
- color: var(--secondary-color);
90
- margin: 0;
91
- }
92
-
93
- .dashboard-card i {
94
- font-size: 3em;
95
- color: var(--primary-color);
96
- margin-bottom: 15px;
97
- }
98
-
99
- #student-list {
100
- background: var(--card-background);
101
- border-radius: 10px;
102
- padding: 20px;
103
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
104
- }
105
-
106
- #student-list h3 {
107
- font-size: 1.8em;
108
- color: var(--primary-color);
109
- margin-bottom: 20px;
110
- text-align: center;
111
- }
112
-
113
- .student-grid {
114
- display: grid;
115
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
116
- gap: 20px;
117
- }
118
-
119
- .student-card {
120
- background: var(--background-color);
121
- border-radius: 8px;
122
- padding: 15px;
123
- text-align: center;
124
- transition: transform 0.3s ease, box-shadow 0.3s ease;
125
- }
126
-
127
- .student-card:hover {
128
- transform: translateY(-5px);
129
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
130
- }
131
-
132
- .student-card h4 {
133
- margin: 0 0 10px;
134
- color: var(--secondary-color);
135
- }
136
-
137
- .student-card p {
138
- margin: 5px 0;
139
- font-size: 0.9em;
140
- color: var(--text-color);
141
- }
142
-
143
- .button-container {
144
- text-align: center;
145
- margin-top: 30px;
146
- }
147
-
148
- button {
149
- background: var(--primary-color);
150
- color: white;
151
- border: none;
152
- padding: 12px 25px;
153
- font-size: 1em;
154
- border-radius: 5px;
155
- cursor: pointer;
156
- transition: background 0.3s, transform 0.3s;
157
- text-transform: uppercase;
158
- letter-spacing: 1px;
159
- }
160
-
161
- button:hover {
162
- background: #2980b9;
163
- transform: translateY(-2px);
164
- }
165
-
166
- #timetable-generator {
167
- margin-top: 40px;
168
- background: var(--card-background);
169
- border-radius: 10px;
170
- padding: 20px;
171
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
172
- }
173
-
174
- #timetable-generator h3 {
175
- font-size: 1.8em;
176
- color: var(--primary-color);
177
- margin-bottom: 20px;
178
- text-align: center;
179
- }
180
-
181
- #timetable-generator form {
182
- display: grid;
183
- gap: 10px;
184
- max-width: 500px;
185
- margin: 0 auto;
186
- }
187
-
188
- #timetable-generator label {
189
- font-size: 1em;
190
- font-weight: bold;
191
- }
192
-
193
- #timetable-generator input {
194
- padding: 10px;
195
- border: 1px solid #ccc;
196
- border-radius: 5px;
197
- font-size: 1em;
198
- }
199
-
200
- #timetable-generator button {
201
- background: var(--primary-color);
202
- color: white;
203
- border: none;
204
- padding: 12px;
205
- font-size: 1em;
206
- border-radius: 5px;
207
- cursor: pointer;
208
- transition: background 0.3s, transform 0.3s;
209
- margin-top: 20px;
210
- }
211
-
212
- #timetable-generator button:hover {
213
- background: #2980b9;
214
- transform: translateY(-2px);
215
- }
216
-
217
- #timetable-result {
218
- margin-top: 20px;
219
- padding: 15px;
220
- background: #fff;
221
- border-radius: 5px;
222
- box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
223
- white-space: pre-wrap;
224
- }
225
-
226
- .fade-in {
227
- animation: fadeIn 0.5s ease-in;
228
- }
229
-
230
- @keyframes fadeIn {
231
- from { opacity: 0; }
232
- to { opacity: 1; }
233
- }
234
- .navbar {
235
- background-color: var(--primary-color);
236
- padding: 10px 0;
237
- position: sticky;
238
- top: 0;
239
- z-index: 1000;
240
- }
241
-
242
- .navbar ul {
243
- list-style-type: none;
244
- margin: 0;
245
- padding: 0;
246
- display: flex;
247
- justify-content: center;
248
- }
249
-
250
- .navbar li {
251
- margin: 0 15px;
252
- }
253
-
254
- .navbar a {
255
- color: white;
256
- text-decoration: none;
257
- font-size: 1.1em;
258
- transition: color 0.3s;
259
- }
260
-
261
- .navbar a:hover {
262
- color: var(--secondary-color);
263
- }
264
- .modal {
265
- display: none;
266
- position: fixed;
267
- z-index: 1;
268
- left: 0;
269
- top: 0;
270
- width: 100%;
271
- height: 100%;
272
- overflow: auto;
273
- background-color: rgba(0,0,0,0.4);
274
- }
275
-
276
- .modal-content {
277
- background-color: #fefefe;
278
- margin: 15% auto;
279
- padding: 20px;
280
- border: 1px solid #888;
281
- width: 80%;
282
- max-width: 600px;
283
- border-radius: 10px;
284
- }
285
-
286
- .close {
287
- color: #aaa;
288
- float: right;
289
- font-size: 28px;
290
- font-weight: bold;
291
- }
292
-
293
- .close:hover,
294
- .close:focus {
295
- color: black;
296
- text-decoration: none;
297
- cursor: pointer;
298
- }
299
-
300
- #generate-ai-report {
301
- background-color: var(--primary-color);
302
- color: white;
303
- border: none;
304
- padding: 10px 20px;
305
- margin-top: 20px;
306
- cursor: pointer;
307
- border-radius: 5px;
308
- }
309
-
310
- #generate-ai-report:hover {
311
- background-color: #2980b9;
312
- }
313
- @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap');
314
-
315
- :root {
316
- --primary-color: #4e54c8;
317
- --secondary-color: #8f94fb;
318
- --accent-color: #ff6b6b;
319
- --text-color: #333;
320
- --bg-color: #f9f9f9;
321
- }
322
-
323
- body {
324
- font-family: 'Poppins', sans-serif;
325
- margin: 0;
326
- padding: 0;
327
- background-color: var(--bg-color);
328
- color: var(--text-color);
329
- line-height: 1.6;
330
- }
331
-
332
- .container {
333
- max-width: 1340px;
334
- margin: 0 auto;
335
- padding: 0 20px;
336
- }
337
-
338
- header {
339
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
340
- padding: 15px 0;
341
- position: sticky;
342
- top: 0;
343
- z-index: 1000;
344
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
345
- }
346
-
347
- .header-content {
348
- display: flex;
349
- justify-content: space-between;
350
- align-items: center;
351
- }
352
-
353
- .logo {
354
- font-size: 28px;
355
- font-weight: 700;
356
- color: #fff;
357
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
358
- }
359
-
360
- .search-bar {
361
- flex-grow: 1;
362
- margin: 0 20px;
363
- position: relative;
364
- }
365
-
366
- .search-bar input {
367
- width: 100%;
368
- padding: 12px 20px;
369
- border: none;
370
- border-radius: 30px;
371
- font-size: 16px;
372
- background-color: rgba(255,255,255,0.2);
373
- color: #fff;
374
- transition: all 0.3s ease;
375
- }
376
-
377
- .search-bar input::placeholder {
378
- color: rgba(255,255,255,0.7);
379
- }
380
-
381
- .search-bar input:focus {
382
- background-color: rgba(255,255,255,0.3);
383
- outline: none;
384
- }
385
-
386
- .ai-tools {
387
- position: absolute;
388
- right: 10px;
389
- top: 50%;
390
- transform: translateY(-50%);
391
- }
392
-
393
- .ai-tools i {
394
- font-size: 20px;
395
- margin-left: 15px;
396
- cursor: pointer;
397
- color: #fff;
398
- transition: all 0.3s ease;
399
- }
400
-
401
- .ai-tools i:hover {
402
- color: var(--accent-color);
403
- transform: scale(1.1);
404
- }
405
-
406
- .user-actions {
407
- display: flex;
408
- align-items: center;
409
- }
410
-
411
- .points-display {
412
- font-size: 18px;
413
- font-weight: bold;
414
- color: #fff;
415
- margin-right: 20px;
416
- background-color: rgba(255,255,255,0.2);
417
- padding: 5px 15px;
418
- border-radius: 20px;
419
- }
420
-
421
- .profile-icon {
422
- width: 40px;
423
- height: 40px;
424
- border-radius: 50%;
425
- background-color: var(--accent-color);
426
- display: flex;
427
- align-items: center;
428
- justify-content: center;
429
- font-weight: bold;
430
- color: #fff;
431
- cursor: pointer;
432
- transition: all 0.3s ease;
433
- }
434
-
435
- .profile-icon:hover {
436
- transform: scale(1.1);
437
- }
438
-
439
- .nav-bar {
440
- background-color: #fff;
441
- padding: 10px 0;
442
- box-shadow: 0 2px 5px rgba(0,0,0,0.1);
443
- }
444
-
445
- .nav-bar ul {
446
- list-style-type: none;
447
- margin: 0;
448
- padding: 0;
449
- display: flex;
450
- justify-content: center;
451
- }
452
-
453
- .nav-bar li {
454
- margin: 0 15px;
455
- }
456
-
457
- .nav-bar a {
458
- text-decoration: none;
459
- color: var(--text-color);
460
- font-weight: 600;
461
- transition: all 0.3s ease;
462
- }
463
-
464
- .nav-bar a:hover {
465
- color: var(--primary-color);
466
- }
467
-
468
- .hero {
469
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
470
- padding: 25px 0;
471
- text-align: center;
472
- color: #fff;
473
- position: relative;
474
- overflow: hidden;
475
- }
476
-
477
- .hero::before {
478
- content: '';
479
- position: absolute;
480
- top: 0;
481
- left: 0;
482
- right: 0;
483
- bottom: 0;
484
- background: url('https://source.unsplash.com/random/1600x900?education') no-repeat center center;
485
- background-size: cover;
486
- opacity: 0.1;
487
- z-index: 0;
488
- }
489
-
490
- .hero-content {
491
- position: relative;
492
- z-index: 1;
493
- }
494
-
495
- .hero h1 {
496
- font-size: 48px;
497
- margin-bottom: 20px;
498
- text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
499
- }
500
-
501
- .hero p {
502
- font-size: 20px;
503
- margin-bottom: 30px;
504
- text-shadow: 1px 1px 2px rgba(0,0,0,0.2);
505
- }
506
-
507
- .btn {
508
- display: inline-block;
509
- background-color: var(--accent-color);
510
- color: #fff;
511
- padding: 12px 30px;
512
- text-decoration: none;
513
- font-weight: 600;
514
- border-radius: 30px;
515
- transition: all 0.3s ease;
516
- box-shadow: 0 4px 15px rgba(0,0,0,0.2);
517
- }
518
-
519
- .btn:hover {
520
- background-color: #ff4757;
521
- transform: translateY(-3px);
522
- }
523
-
524
- .categories, .features, .learning-section {
525
- padding: 60px 0;
526
- background-color: #fff;
527
- margin: 40px 0;
528
- border-radius: 10px;
529
- box-shadow: 0 5px 15px rgba(0,0,0,0.1);
530
- }
531
-
532
- .section-title {
533
- font-size: 32px;
534
- text-align: center;
535
- margin-bottom: 40px;
536
- color: var(--primary-color);
537
- }
538
-
539
- .category-list, .feature-grid, .learning-grid {
540
- display: grid;
541
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
542
- gap: 30px;
543
- }
544
-
545
- .category-item, .feature-card, .learning-item {
546
- background-color: #fff;
547
- border-radius: 10px;
548
- padding: 20px;
549
- text-align: center;
550
- transition: all 0.3s ease;
551
- box-shadow: 0 5px 15px rgba(0,0,0,0.1);
552
- }
553
-
554
- .category-item:hover, .feature-card:hover, .learning-item:hover {
555
- transform: translateY(-10px);
556
- box-shadow: 0 15px 30px rgba(0,0,0,0.2);
557
- }
558
-
559
- .feature-grid {
560
- display: grid;
561
- grid-template-columns: repeat(3, 1fr);
562
- grid-gap: 20px;
563
- }
564
-
565
- .feature-card {
566
- background: #fff;
567
- border: 1px solid #ddd;
568
- border-radius: 8px;
569
- padding: 20px;
570
- text-align: center;
571
- }
572
-
573
- .feature-card img {
574
- max-width: 100%;
575
- border-radius: 8px;
576
- margin-bottom: 15px;
577
- }
578
- .search-bar {
579
- flex-grow: 1;
580
- margin: 0 20px;
581
- position: relative;
582
- max-width: 900px;
583
- }
584
- .profile-sidebar {
585
- display: none;
586
- position: fixed;
587
- top: 0;
588
- right: 0;
589
- width: 300px;
590
- height: 100%;
591
- background-color: #fff;
592
- box-shadow: -2px 0 5px rgba(0,0,0,0.1);
593
- padding: 20px;
594
- overflow-y: auto;
595
- }
596
-
597
- .feature-card h3 {
598
- margin: 10px 0;
599
- }
600
-
601
- .feature-card p {
602
- margin: 10px 0 20px;
603
- }
604
-
605
- .feature-card .btn {
606
- display: inline-block;
607
- padding: 10px 20px;
608
- background-color: #007BFF;
609
- color: #fff;
610
- text-decoration: none;
611
- border-radius: 4px;
612
- }
613
- #subjects-container {
614
- max-width: 600px;
615
- margin: 0 auto; /* Center the container horizontally */
616
- padding: 30px;
617
- background: var(--card-background);
618
- border-radius: 15px;
619
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
620
- display: flex;
621
- flex-direction: column;
622
- align-items: center; /* Center the items horizontally */
623
- gap: 30px; /* Add space between the items */
624
- }
625
-
626
- #subjects-container h3 {
627
- font-size: 1.8em;
628
- color: var(--primary-color);
629
- margin-bottom: 20px;
630
- text-align: center;
631
- }
632
-
633
- .subject-card {
634
- background: var(--card-background);
635
- border-radius: 10px;
636
- padding: 20px;
637
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
638
- transition: transform 0.3s ease;
639
- text-align: center;
640
- width: 100%;
641
- }
642
-
643
- .subject-card:hover {
644
- transform: translateY(-5px);
645
- }
646
-
647
- .subject-card h4 {
648
- font-size: 1.5em;
649
- color: var(--primary-color);
650
- margin-bottom: 15px;
651
- }
652
-
653
- .subject-card p {
654
- font-size: 1em;
655
- color: var(--secondary-color);
656
- margin: 0;
657
- }
658
-
659
- .spinner {
660
- text-align: center;
661
- margin-top: 20px;
662
- }
663
- .spinner-border {
664
- width: 3rem;
665
- height: 3rem;
666
- border: 5px solid #f3f3f3;
667
- border-top: 5px solid #3498db;
668
- border-radius: 50%;
669
- animation: spin 1s linear infinite;
670
- }
671
- @keyframes spin {
672
- 0% { transform: rotate(0deg); }
673
- 100% { transform: rotate(360deg); }
674
- }
675
-
676
- .timetable-container {
677
- display: flex;
678
- flex-wrap: wrap;
679
- justify-content: space-around;
680
- gap: 20px;
681
- margin-top: 30px;
682
- }
683
-
684
- .day-table {
685
- background-color: #fff;
686
- border-radius: 10px;
687
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
688
- padding: 15px;
689
- width: calc(33.33% - 20px);
690
- margin-bottom: 20px;
691
- }
692
-
693
- .day-table h3 {
694
- color: var(--primary-color);
695
- margin-top: 0;
696
- margin-bottom: 15px;
697
- text-align: center;
698
- }
699
-
700
- .day-table table {
701
- width: 100%;
702
- border-collapse: collapse;
703
- }
704
-
705
- .day-table th, .day-table td {
706
- border: 1px solid #ddd;
707
- padding: 8px;
708
- text-align: left;
709
- }
710
-
711
- .day-table th {
712
- background-color: #f2f2f2;
713
- }
714
-
715
- @media (max-width: 768px) {
716
- .day-table {
717
- width: 100%;
718
- }
719
- } .timetable-container {
720
- display: flex;
721
- flex-wrap: wrap;
722
- justify-content: space-around;
723
- gap: 20px;
724
- margin-top: 30px;
725
- }
726
-
727
- .day-table {
728
- background-color: #fff;
729
- border-radius: 10px;
730
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
731
- padding: 15px;
732
- width: calc(33.33% - 20px);
733
- margin-bottom: 20px;
734
- }
735
- html {
736
- scroll-behavior: smooth;
737
- }
738
-
739
- .day-table h3 {
740
- color: var(--primary-color);
741
- margin-top: 0;
742
- margin-bottom: 15px;
743
- text-align: center;
744
- }
745
-
746
- .day-table table {
747
- width: 100%;
748
- border-collapse: collapse;
749
- }
750
- .loading-circle {
751
- display: none;
752
- width: 20px;
753
- height: 20px;
754
- border: 3px solid #f3f3f3;
755
- border-top: 3px solid #3498db;
756
- border-radius: 50%;
757
- animation: spin 1s linear infinite;
758
- margin-left: 10px;
759
- }
760
-
761
- @keyframes spin {
762
- 0% { transform: rotate(0deg); }
763
- 100% { transform: rotate(360deg); }
764
- }
765
-
766
- .day-table th, .day-table td {
767
- border: 1px solid #ddd;
768
- padding: 8px;
769
- text-align: left;
770
- }
771
-
772
- .day-table th {
773
- background-color: #f2f2f2;
774
- }
775
-
776
- @media (max-width: 768px) {
777
- .day-table {
778
- width: 100%;
779
- }
780
- }
781
-
782
- @media (max-width: 768px) {
783
- .feature-grid {
784
- grid-template-columns: 1fr;
785
- }
786
- }
787
-
788
- </style>
789
- </head>
790
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
791
- <body>
792
- <header>
793
- <div class="container">
794
- <div class="header-content">
795
- <div class="logo">SmartLearn</div>
796
- <div class="search-bar">
797
- <input type="text" placeholder="Search for anything">
798
- <div class="ai-tools">
799
- <i class="fas fa-camera" title="Photo Question Answering"></i>
800
- <i class="fas fa-brain" title="AI Tutor"></i>
801
- <i class="fas fa-robot" title="AI Assistant"></i>
802
- </div>
803
- </div>
804
- <div class="user-actions">
805
-
806
- <div class="profile-icon" id="profile-icon">{{ teacher.name[0] }}</div>
807
-
808
- <div id="profile-sidebar" class="profile-sidebar">
809
- <button id="close-profile" class="close-button">&times;</button>
810
-
811
- <div class="profile-header">
812
- <img src="https://via.placeholder.com/150" alt="Teacher Avatar" class="avatar">
813
- <h2>{{ teacher.name }}</h2>
814
- <p>Teacher ID: {{ teacher.id }}</p>
815
- </div>
816
-
817
- <div class="profile-info">
818
- <p><strong>School:</strong> {{ teacher.school }}</p>
819
- <p><strong>Date of Birth:</strong> {{ teacher.dob }}</p>
820
- <p><strong>Email:</strong> {{ teacher.email }}</p>
821
- </div>
822
-
823
- <div class="subjects">
824
- <h3>Subjects Taught</h3>
825
- <ul>
826
- {% for subject in teacher.subjects_taught %}
827
- <li>{{ subject }}</li>
828
- {% endfor %}
829
- </ul>
830
-
831
- <h3>Classes</h3>
832
- <ul>
833
- {% for class in teacher.classes %}
834
- <li>{{ class }}</li>
835
- {% endfor %}
836
- </ul>
837
- </div>
838
-
839
- <div class="performance-graph">
840
- <h3>Weekly Class Performance</h3>
841
- <canvas id="performanceChart"></canvas>
842
- </div>
843
-
844
- <div class="additional-info">
845
- <h3>Qualifications</h3>
846
- <ul>
847
- {% for qualification in teacher.qualifications %}
848
- <li>{{ qualification }}</li>
849
- {% endfor %}
850
- </ul>
851
-
852
- <h3>Years of Experience</h3>
853
- <p>{{ teacher.years_of_experience }}</p>
854
- </div>
855
-
856
- <a href="{{ url_for('index') }}" style="color: #ff4757; text-align: center;"><h2>Log out</h2></a>
857
- </div>
858
-
859
- </header>
860
-
861
- <nav class="nav-bar">
862
- <ul>
863
- <li><a href="{{ url_for('teacher') }}"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
864
- <li><a href="{{ url_for('generate_paper') }}"><i class="fas fa-file-alt"></i> Generate Paper</a></li>
865
- <li><a href="{{ url_for('eval') }}"><i class="fas fa-check-circle"></i> Evaluate</a></li>
866
- <li><a href="#student-list"><i class="fas fa-chart-bar"></i> Generate Report</a></li>
867
- <li><a href="#timetable-generator"><i class="fas fa-calendar-alt"></i> Generate Timetable</a></li>
868
- <li><a href="{{ url_for('ai_timetable') }}"><i class="fas fa-calendar-alt"></i>Slow Learner</a></li>
869
- </ul>
870
- </nav>
871
-
872
-
873
- <div class="teacher-portal fade-in">
874
- <div class="header">
875
- <h1>Teacher Portal</h1>
876
- <p>Welcome, <span id="teacher-name-display"></span>!</p>
877
- </div>
878
- <div class="dashboard">
879
- <div class="dashboard-card">
880
- <i class="fas fa-user-graduate"></i>
881
- <h3>Total Students</h3>
882
- <p id="total-students"></p>
883
- </div>
884
- <div class="dashboard-card">
885
- <i class="fas fa-chart-line"></i>
886
- <h3>Average CGPA</h3>
887
- <p id="average-cgpa"></p>
888
- </div>
889
- <div class="dashboard-card">
890
- <i class="fas fa-clipboard-check"></i>
891
- <h3>Average AI Test Score</h3>
892
- <p id="average-ai-score"></p>
893
- </div>
894
- </div>
895
- <div id="student-list">
896
- <h3>Student List</h3>
897
- <div class="student-grid" id="student-grid"></div>
898
- </div>
899
- <div id="student-details" class="modal">
900
- <div class="modal-content">
901
- <span class="close">&times;</span>
902
- <div id="student-expanded-info"></div>
903
- <button id="generate-ai-report">Generate AI Report</button>
904
- </div>
905
- </div>
906
- <div class="button-container">
907
- <button onclick="window.location.href='index.html'">Back to Home</button>
908
- </div>
909
- <div id="timetable-generator">
910
- <h3>Generate Timetable</h3>
911
- <form id="timetable-form">
912
- <label for="hours-per-day">Hours per Day:</label>
913
- <input type="number" id="hours-per-day" name="hours_per_day" required>
914
-
915
- <label for="days-per-week">Days per Week:</label>
916
- <input type="number" id="days-per-week" name="days_per_week" required>
917
-
918
- <label for="semester-end-date">Semester End Date:</label>
919
- <input type="date" id="semester-end-date" name="semester_end_date" required>
920
-
921
- <label for="number-of-subjects">Number of Subjects:</label>
922
- <input type="number" id="number-of-subjects" name="number_of_subjects" required>
923
-
924
- <div id="subjects-container">
925
- <!-- Subject inputs will be added here dynamically -->
926
- </div>
927
- <button type="submit">Generate Timetable</button>
928
- <div id="timetable-spinner" class="spinner"></div>
929
- </form>
930
- <div id="timetable-result"></div>
931
- </div>
932
- </div>
933
-
934
- <script>
935
- document.addEventListener('DOMContentLoaded', function() {
936
- const teacherName = localStorage.getItem('teacherName');
937
- document.getElementById('teacher-name-display').textContent = teacherName || 'Teacher';
938
-
939
- const studentGrid = document.getElementById('student-grid');
940
- const studentDetails = document.getElementById('student-details');
941
- const studentExpandedInfo = document.getElementById('student-expanded-info');
942
- const closeBtn = document.querySelector('.close');
943
- const generateAIReportBtn = document.getElementById('generate-ai-report');
944
-
945
- fetch('/get_students')
946
- .then(response => response.json())
947
- .then(students => {
948
- let totalCGPA = 0;
949
- let totalAIScore = 0;
950
-
951
- students.forEach(student => {
952
- const studentCard = document.createElement('div');
953
- studentCard.className = 'student-card';
954
- studentCard.innerHTML = `
955
- <h4>${student.name}</h4>
956
- <p>Age: ${student.age}</p>
957
- <p>CGPA: ${student.cgpa}</p>
958
- <p>Course: ${student.course_pursuing}</p>
959
- <p>Assigned Test Score: ${student.assigned_test_score}</p>
960
- `;
961
- studentCard.addEventListener('click', () => showStudentDetails(student));
962
- studentGrid.appendChild(studentCard);
963
-
964
- totalCGPA += student.cgpa;
965
- totalAIScore += student.ai_test_score;
966
- });
967
-
968
- const totalStudents = students.length;
969
- const averageCGPA = totalStudents > 0 ? totalCGPA / totalStudents : 0;
970
- const averageAIScore = totalStudents > 0 ? totalAIScore / totalStudents : 0;
971
-
972
- document.getElementById('total-students').textContent = totalStudents;
973
- document.getElementById('average-cgpa').textContent = averageCGPA.toFixed(2);
974
- document.getElementById('average-ai-score').textContent = averageAIScore.toFixed(2);
975
- })
976
- .catch(error => {
977
- console.error('Error fetching student data:', error);
978
- });
979
-
980
- function showStudentDetails(student) {
981
- studentExpandedInfo.innerHTML = `
982
- <h2>${student.name}</h2>
983
- <p>Age: ${student.age}</p>
984
- <p>CGPA: ${student.cgpa}</p>
985
- <p>Course: ${student.course_pursuing}</p>
986
- <p>Assigned Test Score: ${student.assigned_test_score}</p>
987
- <p>AI Test Score: ${student.ai_test_score}</p>
988
- <p>Interests: ${student.interests}</p>
989
- <p>Difficulty in: ${student.difficulty_in}</p>
990
- <p>Courses Taken: ${student.courses_taken}</p>
991
- `;
992
- studentExpandedInfo.dataset.studentData = JSON.stringify(student);
993
- studentDetails.style.display = 'block';
994
- }
995
-
996
- closeBtn.onclick = function() {
997
- studentDetails.style.display = 'none';
998
- }
999
-
1000
- generateAIReportBtn.onclick = function() {
1001
- const studentData = JSON.parse(studentExpandedInfo.dataset.studentData);
1002
-
1003
- // Create and append loading circle
1004
- const loadingCircle = document.createElement('div');
1005
- loadingCircle.className = 'loading-circle';
1006
- this.appendChild(loadingCircle);
1007
-
1008
- // Show loading circle
1009
- loadingCircle.style.display = 'inline-block';
1010
-
1011
- // Disable the button while loading
1012
- this.disabled = true;
1013
-
1014
- fetch('/generate_report', {
1015
- method: 'POST',
1016
- headers: {
1017
- 'Content-Type': 'application/json',
1018
- },
1019
- body: JSON.stringify(studentData),
1020
- })
1021
- .then(response => response.json())
1022
- .then(data => {
1023
- const reportDiv = document.createElement('div');
1024
- reportDiv.innerHTML = `<h3>AI Generated Report</h3><p>${data.report}</p>`;
1025
- studentExpandedInfo.appendChild(reportDiv);
1026
- })
1027
- .catch((error) => {
1028
- console.error('Error:', error);
1029
- alert('Error generating AI report');
1030
- })
1031
- .finally(() => {
1032
- // Hide loading circle
1033
- loadingCircle.style.display = 'none';
1034
-
1035
- // Re-enable the button
1036
- this.disabled = false;
1037
-
1038
- // Remove the loading circle from the DOM
1039
- this.removeChild(loadingCircle);
1040
- });
1041
- };
1042
- window.onclick = function(event) {
1043
- if (event.target == studentDetails) {
1044
- studentDetails.style.display = 'none';
1045
- }
1046
- }
1047
-
1048
- const timetableForm = document.getElementById('timetable-form');
1049
- const timetableResult = document.getElementById('timetable-result');
1050
-
1051
- const numberOfSubjectsInput = document.getElementById('number-of-subjects');
1052
- numberOfSubjectsInput.addEventListener('change', function() {
1053
- const subjectsContainer = document.getElementById('subjects-container');
1054
- subjectsContainer.innerHTML = '';
1055
-
1056
- const numberOfSubjects = parseInt(this.value);
1057
- for (let i = 0; i < numberOfSubjects; i++) {
1058
- const subjectLabel = document.createElement('label');
1059
- subjectLabel.textContent = `Subject ${i + 1}:`;
1060
- const subjectInput = document.createElement('input');
1061
- subjectInput.type = 'text';
1062
- subjectInput.name = `subject_${i + 1}`;
1063
- subjectInput.required = true;
1064
-
1065
- subjectsContainer.appendChild(subjectLabel);
1066
- subjectsContainer.appendChild(subjectInput);
1067
- }
1068
- });
1069
-
1070
- timetableForm.addEventListener('submit', function(e) {
1071
- e.preventDefault();
1072
- const formData = new FormData(timetableForm);
1073
- const subjects = [];
1074
- for (let [key, value] of formData.entries()) {
1075
- if (key.startsWith('subject_')) {
1076
- subjects.push(value);
1077
- }
1078
- }
1079
- const timetableData = {
1080
- hours_per_day: formData.get('hours_per_day'),
1081
- days_per_week: formData.get('days_per_week'),
1082
- semester_end_date: formData.get('semester_end_date'),
1083
- subjects: subjects
1084
- };
1085
-
1086
- // Show the loading spinner
1087
- document.getElementById('loading-spinner').style.display = 'block';
1088
- timetableResult.textContent = '';
1089
-
1090
- fetch('/generate-timetable', {
1091
- method: 'POST',
1092
- headers: {
1093
- 'Content-Type': 'application/json'
1094
- },
1095
- body: JSON.stringify(timetableData)
1096
- })
1097
- .then(response => response.json())
1098
- .then(data => {
1099
- // Hide the loading spinner
1100
- document.getElementById('loading-spinner').style.display = 'none';
1101
-
1102
- if (data.error) {
1103
- timetableResult.textContent = 'Error: ' + data.error;
1104
- } else {
1105
- timetableResult.textContent = data.timetable;
1106
- }
1107
- })
1108
- .catch(error => {
1109
- // Hide the loading spinner
1110
- document.getElementById('loading-spinner').style.display = 'none';
1111
- timetableResult.textContent = 'Error: ' + error.message;
1112
- });
1113
- });
1114
- });
1115
-
1116
- document.addEventListener('DOMContentLoaded', function() {
1117
- const timetableForm = document.getElementById('timetable-form');
1118
- const timetableResult = document.getElementById('timetable-result');
1119
- const generateButton = document.getElementById('generate-timetable-btn');
1120
- const loadingSpinner = document.getElementById('loading-spinner');
1121
-
1122
- timetableForm.addEventListener('submit', function(e) {
1123
- e.preventDefault();
1124
- const formData = new FormData(timetableForm);
1125
- const subjects = [];
1126
- for (let [key, value] of formData.entries()) {
1127
- if (key.startsWith('subject_')) {
1128
- subjects.push(value);
1129
- }
1130
- }
1131
- const timetableData = {
1132
- hours_per_day: formData.get('hours_per_day'),
1133
- days_per_week: formData.get('days_per_week'),
1134
- semester_end_date: formData.get('semester_end_date'),
1135
- subjects: subjects
1136
- };
1137
-
1138
- // Show the loading spinner
1139
- loadingSpinner.style.display = 'block';
1140
- timetableResult.textContent = '';
1141
-
1142
- // Scroll to the loading spinner
1143
- loadingSpinner.scrollIntoView({ behavior: 'smooth', block: 'center' });
1144
-
1145
- fetch('/generate-timetable', {
1146
- method: 'POST',
1147
- headers: {
1148
- 'Content-Type': 'application/json'
1149
- },
1150
- body: JSON.stringify(timetableData)
1151
- })
1152
- .then(response => response.json())
1153
- .then(data => {
1154
- // Hide the loading spinner
1155
- loadingSpinner.style.display = 'none';
1156
-
1157
- if (data.error) {
1158
- timetableResult.textContent = 'Error: ' + data.error;
1159
- } else {
1160
- timetableResult.textContent = data.timetable;
1161
- }
1162
-
1163
- // Scroll to the result
1164
- timetableResult.scrollIntoView({ behavior: 'smooth', block: 'start' });
1165
- })
1166
- .catch(error => {
1167
- // Hide the loading spinner
1168
- loadingSpinner.style.display = 'none';
1169
- timetableResult.textContent = 'Error: ' + error.message;
1170
-
1171
- // Scroll to the error message
1172
- timetableResult.scrollIntoView({ behavior: 'smooth', block: 'start' });
1173
- });
1174
- });
1175
- });
1176
-
1177
- </script>
1178
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
1179
- <script src="static/profile.js"></script>
1180
- <script>
1181
- document.addEventListener('DOMContentLoaded', function() {
1182
- const profileIcon = document.getElementById('profile-icon');
1183
- const profileSidebar = document.getElementById('profile-sidebar');
1184
- const closeProfile = document.getElementById('close-profile');
1185
-
1186
- profileIcon.addEventListener('click', function() {
1187
- profileSidebar.style.display = 'block';
1188
- });
1189
-
1190
- closeProfile.addEventListener('click', function() {
1191
- profileSidebar.style.display = 'none';
1192
- });
1193
- });
1194
- </script>
1195
- <script>
1196
- document.addEventListener('DOMContentLoaded', function() {
1197
- const profileIcon = document.getElementById('profile-icon');
1198
- const profileSidebar = document.getElementById('profile-sidebar');
1199
- const closeProfile = document.getElementById('close-profile');
1200
-
1201
- profileIcon.addEventListener('click', function() {
1202
- profileSidebar.classList.add('active');
1203
- renderPerformanceChart();
1204
- });
1205
-
1206
- closeProfile.addEventListener('click', function() {
1207
- profileSidebar.classList.remove('active');
1208
- });
1209
-
1210
- function renderPerformanceChart() {
1211
- const ctx = document.getElementById('performanceChart').getContext('2d');
1212
-
1213
- // Sample data
1214
- const data = {
1215
- labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'],
1216
- datasets: [{
1217
- label: 'Performance Score',
1218
- data: [65, 72, 68, 80, 75, 85],
1219
- fill: false,
1220
- borderColor: 'rgb(75, 192, 192)',
1221
- tension: 0.1,
1222
- pointBackgroundColor: 'rgb(75, 192, 192)',
1223
- pointBorderColor: '#fff',
1224
- pointHoverBackgroundColor: '#fff',
1225
- pointHoverBorderColor: 'rgb(75, 192, 192)'
1226
- }]
1227
- };
1228
-
1229
- const config = {
1230
- type: 'line',
1231
- data: data,
1232
- options: {
1233
- responsive: true,
1234
- plugins: {
1235
- title: {
1236
- display: true,
1237
- text: 'Weekly Performance'
1238
- },
1239
- legend: {
1240
- position: 'bottom',
1241
- }
1242
- },
1243
- scales: {
1244
- y: {
1245
- beginAtZero: true,
1246
- max: 100,
1247
- title: {
1248
- display: true,
1249
- text: 'Score'
1250
- }
1251
- },
1252
- x: {
1253
- title: {
1254
- display: true,
1255
- text: 'Week'
1256
- }
1257
- }
1258
- }
1259
- }
1260
- };
1261
-
1262
- new Chart(ctx, config);
1263
- }
1264
- });
1265
-
1266
- </script>
1267
- <script>
1268
- // Extract weekly performance data from the template
1269
- const weeklyPerformanceData = JSON.parse('{{ teacher.weekly_class_performance|tojson|safe }}');
1270
-
1271
- // Prepare data for Chart.js
1272
- const ctx = document.getElementById('performanceChart').getContext('2d');
1273
- const labels = Object.keys(weeklyPerformanceData);
1274
- const datasets = labels.map(label => ({
1275
- label: label,
1276
- data: weeklyPerformanceData[label],
1277
- borderColor: getRandomColor(),
1278
- fill: false
1279
- }));
1280
-
1281
- const performanceChart = new Chart(ctx, {
1282
- type: 'line',
1283
- data: {
1284
- labels: Array.from({length: 7}, (_, i) => `Week ${i + 1}`),
1285
- datasets: datasets
1286
- },
1287
- options: {
1288
- responsive: true,
1289
- scales: {
1290
- x: {
1291
- title: {
1292
- display: true,
1293
- text: 'Weeks'
1294
- }
1295
- },
1296
- y: {
1297
- title: {
1298
- display: true,
1299
- text: 'Performance Score'
1300
- },
1301
- beginAtZero: true
1302
- }
1303
- }
1304
- }
1305
- });
1306
-
1307
- function getRandomColor() {
1308
- const letters = '0123456789ABCDEF';
1309
- let color = '#';
1310
- for (let i = 0; i < 6; i++) {
1311
- color += letters[Math.floor(Math.random() * 16)];
1312
- }
1313
- return color;
1314
- }
1315
- </script>
1316
-
1317
- </body>
1318
- </html>
1319
-
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Teacher Portal - Smart Learn</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
9
+ <style>
10
+ :root {
11
+ --primary-color: #3498db;
12
+ --secondary-color: #2c3e50;
13
+ --background-color: rgba(236, 240, 241, 0.8);
14
+ --text-color: #333;
15
+ --card-background: #fff;
16
+ }
17
+
18
+ body {
19
+ font-family: 'Roboto', sans-serif;
20
+ margin: 0;
21
+ padding: 0;
22
+ background-color: var(--background-color);
23
+ color: var(--text-color);
24
+ line-height: 1.6;
25
+ background-image: url('https://i.pinimg.com/736x/d0/b1/39/d0b1395ab921f995d3340b4a45007dd2.jpg');
26
+ background-size: cover;
27
+ background-position: center;
28
+ background-attachment: fixed;
29
+ }
30
+
31
+ .teacher-portal {
32
+ max-width: 1200px;
33
+ margin: 40px auto;
34
+ padding: 30px;
35
+ background: var(--card-background);
36
+ border-radius: 15px;
37
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
38
+ }
39
+
40
+ .header {
41
+ text-align: center;
42
+ margin-bottom: 40px;
43
+ position: relative;
44
+ }
45
+
46
+ .header h1 {
47
+ font-size: 3em;
48
+ margin-bottom: 10px;
49
+ color: var(--primary-color);
50
+ letter-spacing: 1px;
51
+ text-transform: uppercase;
52
+ }
53
+
54
+ .header p {
55
+ font-size: 1.2em;
56
+ color: var(--secondary-color);
57
+ }
58
+
59
+ .dashboard {
60
+ display: grid;
61
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
62
+ gap: 30px;
63
+ margin-bottom: 40px;
64
+ }
65
+
66
+ .dashboard-card {
67
+ background: var(--card-background);
68
+ border-radius: 10px;
69
+ padding: 20px;
70
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
71
+ transition: transform 0.3s ease;
72
+ text-align: center;
73
+ }
74
+
75
+ .dashboard-card:hover {
76
+ transform: translateY(-5px);
77
+ }
78
+
79
+ .dashboard-card h3 {
80
+ font-size: 1.5em;
81
+ color: var(--primary-color);
82
+ margin-bottom: 15px;
83
+ }
84
+
85
+ .dashboard-card p {
86
+ font-size: 2em;
87
+ font-weight: bold;
88
+ color: var(--secondary-color);
89
+ margin: 0;
90
+ }
91
+
92
+ .dashboard-card i {
93
+ font-size: 3em;
94
+ color: var(--primary-color);
95
+ margin-bottom: 15px;
96
+ }
97
+
98
+ #student-list {
99
+ background: var(--card-background);
100
+ border-radius: 10px;
101
+ padding: 20px;
102
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
103
+ }
104
+
105
+ #student-list h3 {
106
+ font-size: 1.8em;
107
+ color: var(--primary-color);
108
+ margin-bottom: 20px;
109
+ text-align: center;
110
+ }
111
+
112
+ .student-grid {
113
+ display: grid;
114
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
115
+ gap: 20px;
116
+ }
117
+
118
+ .student-card {
119
+ background: var(--background-color);
120
+ border-radius: 8px;
121
+ padding: 15px;
122
+ text-align: center;
123
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
124
+ }
125
+
126
+ .student-card:hover {
127
+ transform: translateY(-5px);
128
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
129
+ }
130
+
131
+ .student-card h4 {
132
+ margin: 0 0 10px;
133
+ color: var(--secondary-color);
134
+ }
135
+
136
+ .student-card p {
137
+ margin: 5px 0;
138
+ font-size: 0.9em;
139
+ color: var(--text-color);
140
+ }
141
+
142
+ .button-container {
143
+ text-align: center;
144
+ margin-top: 30px;
145
+ }
146
+
147
+ button {
148
+ background: var(--primary-color);
149
+ color: white;
150
+ border: none;
151
+ padding: 12px 25px;
152
+ font-size: 1em;
153
+ border-radius: 5px;
154
+ cursor: pointer;
155
+ transition: background 0.3s, transform 0.3s;
156
+ text-transform: uppercase;
157
+ letter-spacing: 1px;
158
+ }
159
+
160
+ button:hover {
161
+ background: #2980b9;
162
+ transform: translateY(-2px);
163
+ }
164
+
165
+ #timetable-generator {
166
+ margin-top: 40px;
167
+ background: var(--card-background);
168
+ border-radius: 10px;
169
+ padding: 20px;
170
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
171
+ }
172
+
173
+ #timetable-generator h3 {
174
+ font-size: 1.8em;
175
+ color: var(--primary-color);
176
+ margin-bottom: 20px;
177
+ text-align: center;
178
+ }
179
+
180
+ #timetable-generator form {
181
+ display: grid;
182
+ gap: 10px;
183
+ max-width: 500px;
184
+ margin: 0 auto;
185
+ }
186
+
187
+ #timetable-generator label {
188
+ font-size: 1em;
189
+ font-weight: bold;
190
+ }
191
+
192
+ #timetable-generator input {
193
+ padding: 10px;
194
+ border: 1px solid #ccc;
195
+ border-radius: 5px;
196
+ font-size: 1em;
197
+ }
198
+
199
+ #timetable-generator button {
200
+ background: var(--primary-color);
201
+ color: white;
202
+ border: none;
203
+ padding: 12px;
204
+ font-size: 1em;
205
+ border-radius: 5px;
206
+ cursor: pointer;
207
+ transition: background 0.3s, transform 0.3s;
208
+ margin-top: 20px;
209
+ }
210
+
211
+ #timetable-generator button:hover {
212
+ background: #2980b9;
213
+ transform: translateY(-2px);
214
+ }
215
+
216
+ #timetable-result {
217
+ margin-top: 20px;
218
+ padding: 15px;
219
+ background: #fff;
220
+ border-radius: 5px;
221
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
222
+ white-space: pre-wrap;
223
+ }
224
+
225
+ .fade-in {
226
+ animation: fadeIn 0.5s ease-in;
227
+ }
228
+
229
+ @keyframes fadeIn {
230
+ from { opacity: 0; }
231
+ to { opacity: 1; }
232
+ }
233
+ .navbar {
234
+ background-color: var(--primary-color);
235
+ padding: 10px 0;
236
+ position: sticky;
237
+ top: 0;
238
+ z-index: 1000;
239
+ }
240
+
241
+ .navbar ul {
242
+ list-style-type: none;
243
+ margin: 0;
244
+ padding: 0;
245
+ display: flex;
246
+ justify-content: center;
247
+ }
248
+
249
+ .navbar li {
250
+ margin: 0 15px;
251
+ }
252
+
253
+ .navbar a {
254
+ color: white;
255
+ text-decoration: none;
256
+ font-size: 1.1em;
257
+ transition: color 0.3s;
258
+ }
259
+
260
+ .navbar a:hover {
261
+ color: var(--secondary-color);
262
+ }
263
+ .modal {
264
+ display: none;
265
+ position: fixed;
266
+ z-index: 1;
267
+ left: 0;
268
+ top: 0;
269
+ width: 100%;
270
+ height: 100%;
271
+ overflow: auto;
272
+ background-color: rgba(0,0,0,0.4);
273
+ }
274
+
275
+ .modal-content {
276
+ background-color: #fefefe;
277
+ margin: 15% auto;
278
+ padding: 20px;
279
+ border: 1px solid #888;
280
+ width: 80%;
281
+ max-width: 600px;
282
+ border-radius: 10px;
283
+ }
284
+
285
+ .close {
286
+ color: #aaa;
287
+ float: right;
288
+ font-size: 28px;
289
+ font-weight: bold;
290
+ }
291
+
292
+ .close:hover,
293
+ .close:focus {
294
+ color: black;
295
+ text-decoration: none;
296
+ cursor: pointer;
297
+ }
298
+
299
+ #generate-ai-report {
300
+ background-color: var(--primary-color);
301
+ color: white;
302
+ border: none;
303
+ padding: 10px 20px;
304
+ margin-top: 20px;
305
+ cursor: pointer;
306
+ border-radius: 5px;
307
+ }
308
+
309
+ #generate-ai-report:hover {
310
+ background-color: #2980b9;
311
+ }
312
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap');
313
+
314
+ :root {
315
+ --primary-color: #4e54c8;
316
+ --secondary-color: #8f94fb;
317
+ --accent-color: #ff6b6b;
318
+ --text-color: #333;
319
+ --bg-color: #f9f9f9;
320
+ }
321
+
322
+ body {
323
+ font-family: 'Poppins', sans-serif;
324
+ margin: 0;
325
+ padding: 0;
326
+ background-color: var(--bg-color);
327
+ color: var(--text-color);
328
+ line-height: 1.6;
329
+ }
330
+
331
+ .container {
332
+ max-width: 1340px;
333
+ margin: 0 auto;
334
+ padding: 0 20px;
335
+ }
336
+
337
+ header {
338
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
339
+ padding: 15px 0;
340
+ position: sticky;
341
+ top: 0;
342
+ z-index: 1000;
343
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
344
+ }
345
+
346
+ .header-content {
347
+ display: flex;
348
+ justify-content: space-between;
349
+ align-items: center;
350
+ }
351
+
352
+ .logo {
353
+ font-size: 28px;
354
+ font-weight: 700;
355
+ color: #fff;
356
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
357
+ }
358
+
359
+ .search-bar {
360
+ flex-grow: 1;
361
+ margin: 0 20px;
362
+ position: relative;
363
+ }
364
+
365
+ .search-bar input {
366
+ width: 100%;
367
+ padding: 12px 20px;
368
+ border: none;
369
+ border-radius: 30px;
370
+ font-size: 16px;
371
+ background-color: rgba(255,255,255,0.2);
372
+ color: #fff;
373
+ transition: all 0.3s ease;
374
+ }
375
+
376
+ .search-bar input::placeholder {
377
+ color: rgba(255,255,255,0.7);
378
+ }
379
+
380
+ .search-bar input:focus {
381
+ background-color: rgba(255,255,255,0.3);
382
+ outline: none;
383
+ }
384
+
385
+ .ai-tools {
386
+ position: absolute;
387
+ right: 10px;
388
+ top: 50%;
389
+ transform: translateY(-50%);
390
+ }
391
+
392
+ .ai-tools i {
393
+ font-size: 20px;
394
+ margin-left: 15px;
395
+ cursor: pointer;
396
+ color: #fff;
397
+ transition: all 0.3s ease;
398
+ }
399
+
400
+ .ai-tools i:hover {
401
+ color: var(--accent-color);
402
+ transform: scale(1.1);
403
+ }
404
+
405
+ .user-actions {
406
+ display: flex;
407
+ align-items: center;
408
+ }
409
+
410
+ .points-display {
411
+ font-size: 18px;
412
+ font-weight: bold;
413
+ color: #fff;
414
+ margin-right: 20px;
415
+ background-color: rgba(255,255,255,0.2);
416
+ padding: 5px 15px;
417
+ border-radius: 20px;
418
+ }
419
+
420
+ .profile-icon {
421
+ width: 40px;
422
+ height: 40px;
423
+ border-radius: 50%;
424
+ background-color: var(--accent-color);
425
+ display: flex;
426
+ align-items: center;
427
+ justify-content: center;
428
+ font-weight: bold;
429
+ color: #fff;
430
+ cursor: pointer;
431
+ transition: all 0.3s ease;
432
+ }
433
+
434
+ .profile-icon:hover {
435
+ transform: scale(1.1);
436
+ }
437
+
438
+ .nav-bar {
439
+ background-color: #fff;
440
+ padding: 10px 0;
441
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
442
+ }
443
+
444
+ .nav-bar ul {
445
+ list-style-type: none;
446
+ margin: 0;
447
+ padding: 0;
448
+ display: flex;
449
+ justify-content: center;
450
+ }
451
+
452
+ .nav-bar li {
453
+ margin: 0 15px;
454
+ }
455
+
456
+ .nav-bar a {
457
+ text-decoration: none;
458
+ color: var(--text-color);
459
+ font-weight: 600;
460
+ transition: all 0.3s ease;
461
+ }
462
+
463
+ .nav-bar a:hover {
464
+ color: var(--primary-color);
465
+ }
466
+
467
+ .hero {
468
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
469
+ padding: 25px 0;
470
+ text-align: center;
471
+ color: #fff;
472
+ position: relative;
473
+ overflow: hidden;
474
+ }
475
+
476
+ .hero::before {
477
+ content: '';
478
+ position: absolute;
479
+ top: 0;
480
+ left: 0;
481
+ right: 0;
482
+ bottom: 0;
483
+ background: url('https://source.unsplash.com/random/1600x900?education') no-repeat center center;
484
+ background-size: cover;
485
+ opacity: 0.1;
486
+ z-index: 0;
487
+ }
488
+
489
+ .hero-content {
490
+ position: relative;
491
+ z-index: 1;
492
+ }
493
+
494
+ .hero h1 {
495
+ font-size: 48px;
496
+ margin-bottom: 20px;
497
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
498
+ }
499
+
500
+ .hero p {
501
+ font-size: 20px;
502
+ margin-bottom: 30px;
503
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.2);
504
+ }
505
+
506
+ .btn {
507
+ display: inline-block;
508
+ background-color: var(--accent-color);
509
+ color: #fff;
510
+ padding: 12px 30px;
511
+ text-decoration: none;
512
+ font-weight: 600;
513
+ border-radius: 30px;
514
+ transition: all 0.3s ease;
515
+ box-shadow: 0 4px 15px rgba(0,0,0,0.2);
516
+ }
517
+
518
+ .btn:hover {
519
+ background-color: #ff4757;
520
+ transform: translateY(-3px);
521
+ }
522
+
523
+ .categories, .features, .learning-section {
524
+ padding: 60px 0;
525
+ background-color: #fff;
526
+ margin: 40px 0;
527
+ border-radius: 10px;
528
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
529
+ }
530
+
531
+ .section-title {
532
+ font-size: 32px;
533
+ text-align: center;
534
+ margin-bottom: 40px;
535
+ color: var(--primary-color);
536
+ }
537
+
538
+ .category-list, .feature-grid, .learning-grid {
539
+ display: grid;
540
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
541
+ gap: 30px;
542
+ }
543
+
544
+ .category-item, .feature-card, .learning-item {
545
+ background-color: #fff;
546
+ border-radius: 10px;
547
+ padding: 20px;
548
+ text-align: center;
549
+ transition: all 0.3s ease;
550
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
551
+ }
552
+
553
+ .category-item:hover, .feature-card:hover, .learning-item:hover {
554
+ transform: translateY(-10px);
555
+ box-shadow: 0 15px 30px rgba(0,0,0,0.2);
556
+ }
557
+
558
+ .feature-grid {
559
+ display: grid;
560
+ grid-template-columns: repeat(3, 1fr);
561
+ grid-gap: 20px;
562
+ }
563
+
564
+ .feature-card {
565
+ background: #fff;
566
+ border: 1px solid #ddd;
567
+ border-radius: 8px;
568
+ padding: 20px;
569
+ text-align: center;
570
+ }
571
+
572
+ .feature-card img {
573
+ max-width: 100%;
574
+ border-radius: 8px;
575
+ margin-bottom: 15px;
576
+ }
577
+ .search-bar {
578
+ flex-grow: 1;
579
+ margin: 0 20px;
580
+ position: relative;
581
+ max-width: 900px;
582
+ }
583
+ .profile-sidebar {
584
+ display: none;
585
+ position: fixed;
586
+ top: 0;
587
+ right: 0;
588
+ width: 300px;
589
+ height: 100%;
590
+ background-color: #fff;
591
+ box-shadow: -2px 0 5px rgba(0,0,0,0.1);
592
+ padding: 20px;
593
+ overflow-y: auto;
594
+ }
595
+
596
+ .feature-card h3 {
597
+ margin: 10px 0;
598
+ }
599
+
600
+ .feature-card p {
601
+ margin: 10px 0 20px;
602
+ }
603
+
604
+ .feature-card .btn {
605
+ display: inline-block;
606
+ padding: 10px 20px;
607
+ background-color: #007BFF;
608
+ color: #fff;
609
+ text-decoration: none;
610
+ border-radius: 4px;
611
+ }
612
+ #subjects-container {
613
+ max-width: 600px;
614
+ margin: 0 auto; /* Center the container horizontally */
615
+ padding: 30px;
616
+ background: var(--card-background);
617
+ border-radius: 15px;
618
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
619
+ display: flex;
620
+ flex-direction: column;
621
+ align-items: center; /* Center the items horizontally */
622
+ gap: 30px; /* Add space between the items */
623
+ }
624
+
625
+ #subjects-container h3 {
626
+ font-size: 1.8em;
627
+ color: var(--primary-color);
628
+ margin-bottom: 20px;
629
+ text-align: center;
630
+ }
631
+
632
+ .subject-card {
633
+ background: var(--card-background);
634
+ border-radius: 10px;
635
+ padding: 20px;
636
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
637
+ transition: transform 0.3s ease;
638
+ text-align: center;
639
+ width: 100%;
640
+ }
641
+
642
+ .subject-card:hover {
643
+ transform: translateY(-5px);
644
+ }
645
+
646
+ .subject-card h4 {
647
+ font-size: 1.5em;
648
+ color: var(--primary-color);
649
+ margin-bottom: 15px;
650
+ }
651
+
652
+ .subject-card p {
653
+ font-size: 1em;
654
+ color: var(--secondary-color);
655
+ margin: 0;
656
+ }
657
+
658
+ .spinner {
659
+ text-align: center;
660
+ margin-top: 20px;
661
+ }
662
+ .spinner-border {
663
+ width: 3rem;
664
+ height: 3rem;
665
+ border: 5px solid #f3f3f3;
666
+ border-top: 5px solid #3498db;
667
+ border-radius: 50%;
668
+ animation: spin 1s linear infinite;
669
+ }
670
+ @keyframes spin {
671
+ 0% { transform: rotate(0deg); }
672
+ 100% { transform: rotate(360deg); }
673
+ }
674
+
675
+ .timetable-container {
676
+ display: flex;
677
+ flex-wrap: wrap;
678
+ justify-content: space-around;
679
+ gap: 20px;
680
+ margin-top: 30px;
681
+ }
682
+
683
+ .day-table {
684
+ background-color: #fff;
685
+ border-radius: 10px;
686
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
687
+ padding: 15px;
688
+ width: calc(33.33% - 20px);
689
+ margin-bottom: 20px;
690
+ }
691
+
692
+ .day-table h3 {
693
+ color: var(--primary-color);
694
+ margin-top: 0;
695
+ margin-bottom: 15px;
696
+ text-align: center;
697
+ }
698
+
699
+ .day-table table {
700
+ width: 100%;
701
+ border-collapse: collapse;
702
+ }
703
+
704
+ .day-table th, .day-table td {
705
+ border: 1px solid #ddd;
706
+ padding: 8px;
707
+ text-align: left;
708
+ }
709
+
710
+ .day-table th {
711
+ background-color: #f2f2f2;
712
+ }
713
+
714
+ @media (max-width: 768px) {
715
+ .day-table {
716
+ width: 100%;
717
+ }
718
+ } .timetable-container {
719
+ display: flex;
720
+ flex-wrap: wrap;
721
+ justify-content: space-around;
722
+ gap: 20px;
723
+ margin-top: 30px;
724
+ }
725
+
726
+ .day-table {
727
+ background-color: #fff;
728
+ border-radius: 10px;
729
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
730
+ padding: 15px;
731
+ width: calc(33.33% - 20px);
732
+ margin-bottom: 20px;
733
+ }
734
+ html {
735
+ scroll-behavior: smooth;
736
+ }
737
+
738
+ .day-table h3 {
739
+ color: var(--primary-color);
740
+ margin-top: 0;
741
+ margin-bottom: 15px;
742
+ text-align: center;
743
+ }
744
+
745
+ .day-table table {
746
+ width: 100%;
747
+ border-collapse: collapse;
748
+ }
749
+ .loading-circle {
750
+ display: none;
751
+ width: 20px;
752
+ height: 20px;
753
+ border: 3px solid #f3f3f3;
754
+ border-top: 3px solid #3498db;
755
+ border-radius: 50%;
756
+ animation: spin 1s linear infinite;
757
+ margin-left: 10px;
758
+ }
759
+
760
+ @keyframes spin {
761
+ 0% { transform: rotate(0deg); }
762
+ 100% { transform: rotate(360deg); }
763
+ }
764
+
765
+ .day-table th, .day-table td {
766
+ border: 1px solid #ddd;
767
+ padding: 8px;
768
+ text-align: left;
769
+ }
770
+
771
+ .day-table th {
772
+ background-color: #f2f2f2;
773
+ }
774
+
775
+ @media (max-width: 768px) {
776
+ .day-table {
777
+ width: 100%;
778
+ }
779
+ }
780
+
781
+ @media (max-width: 768px) {
782
+ .feature-grid {
783
+ grid-template-columns: 1fr;
784
+ }
785
+ }
786
+
787
+ </style>
788
+ </head>
789
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
790
+ <body>
791
+ <header>
792
+ <div class="container">
793
+ <div class="header-content">
794
+ <div class="logo">SmartLearn</div>
795
+ <div class="search-bar">
796
+ <input type="text" placeholder="Search for anything">
797
+ <div class="ai-tools">
798
+ <i class="fas fa-camera" title="Photo Question Answering"></i>
799
+ <i class="fas fa-brain" title="AI Tutor"></i>
800
+ <i class="fas fa-robot" title="AI Assistant"></i>
801
+ </div>
802
+ </div>
803
+ <div class="user-actions">
804
+
805
+ <div class="profile-icon" id="profile-icon">{{ teacher.name[0] }}</div>
806
+
807
+ <div id="profile-sidebar" class="profile-sidebar">
808
+ <button id="close-profile" class="close-button">&times;</button>
809
+
810
+ <div class="profile-header">
811
+ <img src="https://via.placeholder.com/150" alt="Teacher Avatar" class="avatar">
812
+ <h2>{{ teacher.name }}</h2>
813
+ <p>Teacher ID: {{ teacher.id }}</p>
814
+ </div>
815
+
816
+ <div class="profile-info">
817
+ <p><strong>School:</strong> {{ teacher.school }}</p>
818
+ <p><strong>Date of Birth:</strong> {{ teacher.dob }}</p>
819
+ <p><strong>Email:</strong> {{ teacher.email }}</p>
820
+ </div>
821
+
822
+ <div class="subjects">
823
+ <h3>Subjects Taught</h3>
824
+ <ul>
825
+ {% for subject in teacher.subjects_taught %}
826
+ <li>{{ subject }}</li>
827
+ {% endfor %}
828
+ </ul>
829
+
830
+ <h3>Classes</h3>
831
+ <ul>
832
+ {% for class in teacher.classes %}
833
+ <li>{{ class }}</li>
834
+ {% endfor %}
835
+ </ul>
836
+ </div>
837
+
838
+ <div class="performance-graph">
839
+ <h3>Weekly Class Performance</h3>
840
+ <canvas id="performanceChart"></canvas>
841
+ </div>
842
+
843
+ <div class="additional-info">
844
+ <h3>Qualifications</h3>
845
+ <ul>
846
+ {% for qualification in teacher.qualifications %}
847
+ <li>{{ qualification }}</li>
848
+ {% endfor %}
849
+ </ul>
850
+
851
+ <h3>Years of Experience</h3>
852
+ <p>{{ teacher.years_of_experience }}</p>
853
+ </div>
854
+
855
+ <a href="{{ url_for('index') }}" style="color: #ff4757; text-align: center;"><h2>Log out</h2></a>
856
+ </div>
857
+
858
+ </header>
859
+
860
+ <nav class="nav-bar">
861
+ <ul>
862
+ <li><a href="{{ url_for('teacher') }}"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
863
+ <li><a href="{{ url_for('generate_paper') }}"><i class="fas fa-file-alt"></i> Generate Paper</a></li>
864
+ <li><a href="{{ url_for('eval') }}"><i class="fas fa-check-circle"></i> Evaluate</a></li>
865
+ <li><a href="#student-list"><i class="fas fa-chart-bar"></i> Generate Report</a></li>
866
+ <li><a href="#timetable-generator"><i class="fas fa-calendar-alt"></i> Generate Timetable</a></li>
867
+ <li><a href="{{ url_for('ai_timetable') }}"><i class="fas fa-calendar-alt"></i>Slow Learner</a></li>
868
+ </ul>
869
+ </nav>
870
+
871
+
872
+ <div class="teacher-portal fade-in">
873
+ <div class="header">
874
+ <h1>Teacher Portal</h1>
875
+ <p>Welcome, <span id="teacher-name-display"></span>!</p>
876
+ </div>
877
+ <div class="dashboard">
878
+ <div class="dashboard-card">
879
+ <i class="fas fa-user-graduate"></i>
880
+ <h3>Total Students</h3>
881
+ <p id="total-students"></p>
882
+ </div>
883
+ <div class="dashboard-card">
884
+ <i class="fas fa-chart-line"></i>
885
+ <h3>Average CGPA</h3>
886
+ <p id="average-cgpa"></p>
887
+ </div>
888
+ <div class="dashboard-card">
889
+ <i class="fas fa-clipboard-check"></i>
890
+ <h3>Average AI Test Score</h3>
891
+ <p id="average-ai-score"></p>
892
+ </div>
893
+ </div>
894
+ <div id="student-list">
895
+ <h3>Student List</h3>
896
+ <div class="student-grid" id="student-grid"></div>
897
+ </div>
898
+ <div id="student-details" class="modal">
899
+ <div class="modal-content">
900
+ <span class="close">&times;</span>
901
+ <div id="student-expanded-info"></div>
902
+ <button id="generate-ai-report">Generate AI Report</button>
903
+ </div>
904
+ </div>
905
+ <div class="button-container">
906
+ <button onclick="window.location.href='index.html'">Back to Home</button>
907
+ </div>
908
+ <div id="timetable-generator">
909
+ <h3>Generate Timetable</h3>
910
+ <form id="timetable-form">
911
+ <label for="hours-per-day">Hours per Day:</label>
912
+ <input type="number" id="hours-per-day" name="hours_per_day" required>
913
+
914
+ <label for="days-per-week">Days per Week:</label>
915
+ <input type="number" id="days-per-week" name="days_per_week" required>
916
+
917
+ <label for="semester-end-date">Semester End Date:</label>
918
+ <input type="date" id="semester-end-date" name="semester_end_date" required>
919
+
920
+ <label for="number-of-subjects">Number of Subjects:</label>
921
+ <input type="number" id="number-of-subjects" name="number_of_subjects" required>
922
+
923
+ <div id="subjects-container">
924
+ <!-- Subject inputs will be added here dynamically -->
925
+ </div>
926
+ <button type="submit">Generate Timetable</button>
927
+ <div id="timetable-spinner" class="spinner"></div>
928
+ </form>
929
+ <div id="timetable-result"></div>
930
+ </div>
931
+ </div>
932
+
933
+ <script>
934
+ document.addEventListener('DOMContentLoaded', function() {
935
+ const teacherName = localStorage.getItem('teacherName');
936
+ document.getElementById('teacher-name-display').textContent = teacherName || 'Teacher';
937
+
938
+ const studentGrid = document.getElementById('student-grid');
939
+ const studentDetails = document.getElementById('student-details');
940
+ const studentExpandedInfo = document.getElementById('student-expanded-info');
941
+ const closeBtn = document.querySelector('.close');
942
+ const generateAIReportBtn = document.getElementById('generate-ai-report');
943
+
944
+ fetch('/get_students')
945
+ .then(response => response.json())
946
+ .then(students => {
947
+ let totalCGPA = 0;
948
+ let totalAIScore = 0;
949
+
950
+ students.forEach(student => {
951
+ const studentCard = document.createElement('div');
952
+ studentCard.className = 'student-card';
953
+ studentCard.innerHTML = `
954
+ <h4>${student.name}</h4>
955
+ <p>Age: ${student.age}</p>
956
+ <p>CGPA: ${student.cgpa}</p>
957
+ <p>Course: ${student.course_pursuing}</p>
958
+ <p>Assigned Test Score: ${student.assigned_test_score}</p>
959
+ `;
960
+ studentCard.addEventListener('click', () => showStudentDetails(student));
961
+ studentGrid.appendChild(studentCard);
962
+
963
+ totalCGPA += student.cgpa;
964
+ totalAIScore += student.ai_test_score;
965
+ });
966
+
967
+ const totalStudents = students.length;
968
+ const averageCGPA = totalStudents > 0 ? totalCGPA / totalStudents : 0;
969
+ const averageAIScore = totalStudents > 0 ? totalAIScore / totalStudents : 0;
970
+
971
+ document.getElementById('total-students').textContent = totalStudents;
972
+ document.getElementById('average-cgpa').textContent = averageCGPA.toFixed(2);
973
+ document.getElementById('average-ai-score').textContent = averageAIScore.toFixed(2);
974
+ })
975
+ .catch(error => {
976
+ console.error('Error fetching student data:', error);
977
+ });
978
+
979
+ function showStudentDetails(student) {
980
+ studentExpandedInfo.innerHTML = `
981
+ <h2>${student.name}</h2>
982
+ <p>Age: ${student.age}</p>
983
+ <p>CGPA: ${student.cgpa}</p>
984
+ <p>Course: ${student.course_pursuing}</p>
985
+ <p>Assigned Test Score: ${student.assigned_test_score}</p>
986
+ <p>AI Test Score: ${student.ai_test_score}</p>
987
+ <p>Interests: ${student.interests}</p>
988
+ <p>Difficulty in: ${student.difficulty_in}</p>
989
+ <p>Courses Taken: ${student.courses_taken}</p>
990
+ `;
991
+ studentExpandedInfo.dataset.studentData = JSON.stringify(student);
992
+ studentDetails.style.display = 'block';
993
+ }
994
+
995
+ closeBtn.onclick = function() {
996
+ studentDetails.style.display = 'none';
997
+ }
998
+
999
+ generateAIReportBtn.onclick = function() {
1000
+ const studentData = JSON.parse(studentExpandedInfo.dataset.studentData);
1001
+
1002
+ const loadingCircle = document.createElement('div');
1003
+ loadingCircle.className = 'loading-circle';
1004
+ this.appendChild(loadingCircle);
1005
+
1006
+ loadingCircle.style.display = 'inline-block';
1007
+ this.disabled = true;
1008
+
1009
+ fetch('/generate_report', {
1010
+ method: 'POST',
1011
+ headers: {
1012
+ 'Content-Type': 'application/json',
1013
+ },
1014
+ body: JSON.stringify(studentData),
1015
+ })
1016
+ .then(response => response.json())
1017
+ .then(data => {
1018
+ const reportDiv = document.createElement('div');
1019
+ reportDiv.innerHTML = <h3>AI Generated Report</h3><p>${data.report}</p>;
1020
+ studentExpandedInfo.appendChild(reportDiv);
1021
+ })
1022
+ .catch((error) => {
1023
+ console.error('Error:', error);
1024
+ alert('Error generating AI report');
1025
+ })
1026
+ .finally(() => {
1027
+ loadingCircle.style.display = 'none';
1028
+ this.disabled = false;
1029
+ this.removeChild(loadingCircle);
1030
+ });
1031
+ };
1032
+
1033
+ window.onclick = function(event) {
1034
+ if (event.target == studentDetails) {
1035
+ studentDetails.style.display = 'none';
1036
+ }
1037
+ }
1038
+ const numberOfSubjectsInput = document.getElementById('number-of-subjects');
1039
+ numberOfSubjectsInput.addEventListener('change', function() {
1040
+ const subjectsContainer = document.getElementById('subjects-container');
1041
+ subjectsContainer.innerHTML = '';
1042
+
1043
+ const numberOfSubjects = parseInt(this.value);
1044
+ for (let i = 0; i < numberOfSubjects; i++) {
1045
+ const subjectLabel = document.createElement('label');
1046
+ subjectLabel.textContent = Subject ${i + 1}:;
1047
+
1048
+ const subjectInput = document.createElement('input');
1049
+ subjectInput.type = 'text';
1050
+ subjectInput.name = subject_${i + 1};
1051
+ subjectInput.required = true;
1052
+
1053
+ subjectsContainer.appendChild(subjectLabel);
1054
+ subjectsContainer.appendChild(subjectInput);
1055
+ }
1056
+ });
1057
+
1058
+ // Handle form submission for generating the timetable
1059
+ const timetableForm = document.getElementById('timetable-form');
1060
+ const timetableResult = document.getElementById('timetable-result');
1061
+
1062
+ timetableForm.addEventListener('submit', function(e) {
1063
+ e.preventDefault();
1064
+
1065
+ const formData = new FormData(timetableForm);
1066
+ const subjects = [];
1067
+ for (let [key, value] of formData.entries()) {
1068
+ if (key.startsWith('subject_')) {
1069
+ subjects.push(value);
1070
+ }
1071
+ }
1072
+
1073
+ const timetableData = {
1074
+ hours_per_day: formData.get('hours_per_day'),
1075
+ days_per_week: formData.get('days_per_week'),
1076
+ semester_end_date: formData.get('semester_end_date'),
1077
+ subjects: subjects
1078
+ };
1079
+
1080
+ const spinner = document.getElementById('timetable-spinner');
1081
+ const submitButton = timetableForm.querySelector('button[type="submit"]');
1082
+
1083
+ // Show spinner and disable submit button
1084
+ spinner.style.display = 'block';
1085
+ submitButton.disabled = true;
1086
+ submitButton.style.opacity = '0.5';
1087
+
1088
+ fetch('/generate_timetable', {
1089
+ method: 'POST',
1090
+ headers: {
1091
+ 'Content-Type': 'application/json'
1092
+ },
1093
+ body: JSON.stringify(timetableData)
1094
+ })
1095
+ .then(response => {
1096
+ if (!response.ok) {
1097
+ throw new Error('Failed to generate timetable');
1098
+ }
1099
+ return response.json();
1100
+ })
1101
+ .then(data => {
1102
+ if (data.error) {
1103
+ timetableResult.textContent = 'Error: ' + data.error;
1104
+ } else {
1105
+ timetableResult.textContent = data.timetable;
1106
+ }
1107
+ })
1108
+ .catch(error => {
1109
+ timetableResult.textContent = 'Error: ' + error.message;
1110
+ })
1111
+ .finally(() => {
1112
+ // Hide spinner and re-enable submit button
1113
+ spinner.style.display = 'none';
1114
+ submitButton.disabled = false;
1115
+ submitButton.style.opacity = '1';
1116
+ });
1117
+ });
1118
+ });
1119
+ </script>
1120
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
1121
+ <script src="static/profile.js"></script>
1122
+ <script>
1123
+ document.addEventListener('DOMContentLoaded', function() {
1124
+ const profileIcon = document.getElementById('profile-icon');
1125
+ const profileSidebar = document.getElementById('profile-sidebar');
1126
+ const closeProfile = document.getElementById('close-profile');
1127
+
1128
+ profileIcon.addEventListener('click', function() {
1129
+ profileSidebar.style.display = 'block';
1130
+ });
1131
+
1132
+ closeProfile.addEventListener('click', function() {
1133
+ profileSidebar.style.display = 'none';
1134
+ });
1135
+ });
1136
+ </script>
1137
+ <script>
1138
+ document.addEventListener('DOMContentLoaded', function() {
1139
+ const profileIcon = document.getElementById('profile-icon');
1140
+ const profileSidebar = document.getElementById('profile-sidebar');
1141
+ const closeProfile = document.getElementById('close-profile');
1142
+
1143
+ profileIcon.addEventListener('click', function() {
1144
+ profileSidebar.classList.add('active');
1145
+ renderPerformanceChart();
1146
+ });
1147
+
1148
+ closeProfile.addEventListener('click', function() {
1149
+ profileSidebar.classList.remove('active');
1150
+ });
1151
+
1152
+ function renderPerformanceChart() {
1153
+ const ctx = document.getElementById('performanceChart').getContext('2d');
1154
+
1155
+ // Sample data
1156
+ const data = {
1157
+ labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'],
1158
+ datasets: [{
1159
+ label: 'Performance Score',
1160
+ data: [65, 72, 68, 80, 75, 85],
1161
+ fill: false,
1162
+ borderColor: 'rgb(75, 192, 192)',
1163
+ tension: 0.1,
1164
+ pointBackgroundColor: 'rgb(75, 192, 192)',
1165
+ pointBorderColor: '#fff',
1166
+ pointHoverBackgroundColor: '#fff',
1167
+ pointHoverBorderColor: 'rgb(75, 192, 192)'
1168
+ }]
1169
+ };
1170
+
1171
+ const config = {
1172
+ type: 'line',
1173
+ data: data,
1174
+ options: {
1175
+ responsive: true,
1176
+ plugins: {
1177
+ title: {
1178
+ display: true,
1179
+ text: 'Weekly Performance'
1180
+ },
1181
+ legend: {
1182
+ position: 'bottom',
1183
+ }
1184
+ },
1185
+ scales: {
1186
+ y: {
1187
+ beginAtZero: true,
1188
+ max: 100,
1189
+ title: {
1190
+ display: true,
1191
+ text: 'Score'
1192
+ }
1193
+ },
1194
+ x: {
1195
+ title: {
1196
+ display: true,
1197
+ text: 'Week'
1198
+ }
1199
+ }
1200
+ }
1201
+ }
1202
+ };
1203
+
1204
+ new Chart(ctx, config);
1205
+ }
1206
+ });
1207
+
1208
+ </script>
1209
+ <script>
1210
+ // Extract weekly performance data from the template
1211
+ const weeklyPerformanceData = JSON.parse('{{ teacher.weekly_class_performance|tojson|safe }}');
1212
+
1213
+ // Prepare data for Chart.js
1214
+ const ctx = document.getElementById('performanceChart').getContext('2d');
1215
+ const labels = Object.keys(weeklyPerformanceData);
1216
+ const datasets = labels.map(label => ({
1217
+ label: label,
1218
+ data: weeklyPerformanceData[label],
1219
+ borderColor: getRandomColor(),
1220
+ fill: false
1221
+ }));
1222
+
1223
+ const performanceChart = new Chart(ctx, {
1224
+ type: 'line',
1225
+ data: {
1226
+ labels: Array.from({length: 7}, (_, i) => Week ${i + 1}),
1227
+ datasets: datasets
1228
+ },
1229
+ options: {
1230
+ responsive: true,
1231
+ scales: {
1232
+ x: {
1233
+ title: {
1234
+ display: true,
1235
+ text: 'Weeks'
1236
+ }
1237
+ },
1238
+ y: {
1239
+ title: {
1240
+ display: true,
1241
+ text: 'Performance Score'
1242
+ },
1243
+ beginAtZero: true
1244
+ }
1245
+ }
1246
+ }
1247
+ });
1248
+
1249
+ function getRandomColor() {
1250
+ const letters = '0123456789ABCDEF';
1251
+ let color = '#';
1252
+ for (let i = 0; i < 6; i++) {
1253
+ color += letters[Math.floor(Math.random() * 16)];
1254
+ }
1255
+ return color;
1256
+ }
1257
+ </script>
1258
+
1259
+
1260
+ </body>
1261
+ </html>