geethareddy commited on
Commit
cb49ced
·
verified ·
1 Parent(s): d83a695

Create index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +738 -994
templates/index.html CHANGED
@@ -3,945 +3,613 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Construction Supervisor AI Coach</title>
7
  <style>
8
- :root {
9
- --primary-blue: #2563EB;
10
- --secondary-orange: #F97316;
11
- --accent-yellow: #FBBF24;
12
- --success-green: #48BB78;
13
- --error-red: #F56565;
14
- --warning-yellow: #ECC94B;
15
- --background-light: #F7FAFC;
16
- --card-bg: #FFFFFF;
17
- --text-dark: #1A202C;
18
- --text-muted: #718096;
19
- }
20
-
21
  body {
22
  font-family: 'Roboto', Arial, sans-serif;
23
  margin: 0;
24
  padding: 0;
25
- background-color: #F5F7FA;
26
- color: var(--text-dark);
27
  line-height: 1.6;
28
- display: flex;
29
  }
30
-
31
- /* Sidebar */
32
- .sidebar {
33
- width: 200px;
34
- background-color: var(--card-bg);
35
- height: 100vh;
36
- position: fixed;
37
  top: 0;
38
- left: 0;
39
- padding: 20px;
40
- box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
41
- display: flex;
42
- flex-direction: column;
43
- gap: 10px;
44
  }
45
-
46
- .sidebar h1 {
47
- font-size: 18px;
48
- color: var(--primary-blue);
49
- margin: 0 0 20px 0;
 
 
50
  }
51
-
52
- .sidebar a {
53
  display: flex;
54
  align-items: center;
55
- gap: 10px;
56
- padding: 10px 15px;
57
- color: var(--text-muted);
58
- text-decoration: none;
59
- border-radius: 5px;
60
- transition: background 0.3s ease;
61
- }
62
-
63
- .sidebar a.active {
64
- background-color: #E6F0FA;
65
- color: var(--primary-blue);
66
- }
67
-
68
- .sidebar a:hover {
69
- background-color: #E6F0FA;
70
- }
71
-
72
- .sidebar img {
73
- width: 20px;
74
- height: 20px;
75
- }
76
-
77
- /* Main Content */
78
- .main-content {
79
- margin-left: 200px;
80
- padding: 20px;
81
- flex: 1;
82
- }
83
-
84
- .header {
85
- display: flex;
86
  justify-content: space-between;
87
- align-items: center;
88
- padding: 10px 20px;
89
- background-color: var(--card-bg);
90
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
91
  }
92
-
93
- .header .user-info {
 
 
 
 
94
  display: flex;
95
  align-items: center;
96
- gap: 10px;
 
 
 
 
 
97
  }
98
-
99
- .header .user-info img {
100
- width: 20px;
101
- height: 20px;
102
  }
103
-
104
- .header .user-info span {
105
- font-size: 14px;
106
- color: var(--text-muted);
 
 
 
 
 
 
 
107
  }
108
-
109
- .header .user-info .avatar {
110
- width: 30px;
111
- height: 30px;
112
- background-color: var(--primary-blue);
113
- color: #FFFFFF;
114
- border-radius: 50%;
115
- display: flex;
116
- align-items: center;
117
- justify-content: center;
118
- font-size: 16px;
119
  }
120
-
121
- /* Sections */
122
- .section {
123
- background-color: var(--card-bg);
124
- padding: 20px;
125
- border-radius: 8px;
126
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
127
- margin-bottom: 20px;
128
  }
129
-
130
- .section h2 {
131
- font-size: 24px;
132
- color: var(--text-dark);
133
- margin: 0 0 10px 0;
134
  }
135
-
136
- .section p {
137
- font-size: 14px;
138
- color: var(--text-muted);
139
- margin: 0 0 20px 0;
140
  }
141
-
142
- /* Dashboard Section */
143
- .dashboard-grid {
144
- display: grid;
145
- grid-template-columns: 1fr 1fr;
146
- gap: 20px;
 
 
 
 
 
 
 
 
147
  }
148
-
149
- .checklist-item {
150
- display: flex;
151
- align-items: center;
152
- gap: 10px;
153
- padding: 10px 0;
154
- font-size: 14px;
 
 
 
 
 
155
  }
156
-
157
- .checklist-item input {
158
- accent-color: var(--primary-blue);
159
  }
160
-
161
- .checklist-item label {
162
- flex: 1;
163
- color: var(--text-dark);
 
 
 
 
 
 
 
 
164
  }
165
-
166
- .checklist-item label.category-safety {
167
- color: var(--error-red);
168
  }
169
-
170
- .checklist-item label.category-materials {
171
- color: var(--primary-blue);
 
 
 
 
172
  }
173
-
174
- .checklist-item label.category-inspection {
175
- color: var(--warning-yellow);
176
  }
177
-
178
- .project-progress {
179
- display: flex;
180
- flex-direction: column;
181
- gap: 10px;
182
  }
183
-
184
- .project-progress .progress-bar {
185
- width: 100%;
186
- height: 10px;
187
- background-color: #E2E8F0;
188
- border-radius: 5px;
189
- overflow: hidden;
 
 
 
190
  }
191
-
192
- .project-progress .progress-fill {
193
- height: 100%;
194
- background-color: var(--primary-blue);
195
- transition: width 0.5s ease;
196
  }
197
-
198
- .metrics-grid {
199
  display: grid;
200
- grid-template-columns: repeat(3, 1fr);
201
- gap: 10px;
 
202
  }
203
-
204
- .metric-card {
205
- text-align: center;
206
- padding: 10px;
207
- border-radius: 5px;
208
- background-color: #F9FAFB;
 
209
  }
210
-
211
- .metric-card h4 {
212
- font-size: 14px;
213
- color: var(--text-muted);
214
- margin: 0 0 5px 0;
215
  }
216
-
217
- .metric-card .value {
218
- font-size: 24px;
219
- font-weight: 700;
220
- color: var(--primary-blue);
221
  }
222
-
223
- .metric-card .trend {
224
- font-size: 12px;
225
- color: var(--error-red);
 
 
 
 
226
  }
227
-
228
- .tips-card {
229
- padding: 15px;
230
- border-radius: 5px;
231
- margin-bottom: 10px;
232
- font-size: 14px;
233
  }
234
-
235
- .tips-card.warning {
236
- background-color: #FEF3C7;
237
- color: var(--warning-yellow);
 
238
  }
239
-
240
- .tips-card.info {
241
- background-color: #EBF5FF;
242
- color: var(--primary-blue);
 
 
 
 
 
 
 
 
243
  }
244
-
245
- .tips-card.medium {
246
- background-color: #F3F4F6;
247
- color: var(--text-muted);
 
 
 
248
  }
249
-
250
- /* Reflections Section */
251
- .mood-buttons {
 
 
252
  display: flex;
253
- gap: 10px;
254
  margin-bottom: 15px;
 
 
 
 
255
  }
256
-
257
- .mood-buttons button {
258
- padding: 8px 15px;
259
- border: 1px solid #E2E8F0;
260
- border-radius: 5px;
261
- background-color: var(--card-bg);
262
- color: var(--text-muted);
 
263
  cursor: pointer;
264
- transition: background 0.3s ease;
265
  }
266
-
267
- .mood-buttons button.active {
268
- background-color: var(--primary-blue);
269
- color: #FFFFFF;
270
- border-color: var(--primary-blue);
271
  }
272
-
273
- .reflection-input textarea {
274
- width: 100%;
275
- height: 100px;
276
- padding: 10px;
277
- border: 1px solid #E2E8F0;
278
- border-radius: 5px;
279
- resize: none;
280
- font-size: 14px;
281
- margin-bottom: 10px;
282
  }
283
-
284
- .reflection-history .entry {
285
- padding: 10px 0;
286
- border-bottom: 1px solid #E2E8F0;
287
- font-size: 14px;
 
 
288
  }
289
-
290
- .reflection-history .entry:last-child {
291
- border-bottom: none;
292
  }
293
-
294
- .reflection-history .entry .date {
 
 
295
  font-weight: 600;
296
- color: var(--text-dark);
297
  }
298
-
299
- .reflection-history .entry .mood {
300
- padding: 2px 8px;
301
- border-radius: 5px;
302
- font-size: 12px;
303
- margin-left: 10px;
304
  }
305
-
306
- .reflection-history .entry .mood.concerned {
307
- background-color: #FEF3C7;
308
- color: var(--warning-yellow);
309
  }
310
-
311
- .reflection-history .entry .mood.satisfied {
312
- background-color: #D1FAE5;
313
- color: var(--success-green);
 
 
 
 
 
 
314
  }
315
-
316
- .reflection-history .entry .mood.neutral {
317
- background-color: #F3F4F6;
318
- color: var(--text-muted);
319
  }
320
-
321
- /* Reports Section */
322
- .report-form {
323
  display: flex;
324
  flex-direction: column;
325
  gap: 15px;
326
  }
327
-
328
- .report-form input,
329
- .report-form select {
330
- padding: 10px;
331
- border: 1px solid #E2E8F0;
332
- border-radius: 5px;
333
- font-size: 14px;
 
 
 
 
334
  }
335
-
336
- .report-form .date-range {
337
- display: flex;
338
- gap: 10px;
339
  }
340
-
341
- .report-list .report-item {
342
- display: flex;
343
- justify-content: space-between;
344
- align-items: center;
345
- padding: 10px;
346
- border-bottom: 1px solid #E2E8F0;
 
 
 
 
 
347
  font-size: 14px;
 
348
  }
349
-
350
- .report-list .report-item:last-child {
351
  border-bottom: none;
 
352
  }
353
-
354
- .report-list .report-item .status {
355
- padding: 2px 8px;
356
- border-radius: 5px;
357
- font-size: 12px;
358
- background-color: #D1FAE5;
359
- color: var(--success-green);
360
  }
361
-
362
- /* Milestones Section */
363
- .milestones-header {
364
- display: flex;
365
- justify-content: space-between;
366
- align-items: center;
367
- margin-bottom: 15px;
 
368
  }
369
-
370
- .milestone-item {
371
- display: flex;
372
- justify-content: space-between;
373
- align-items: center;
374
- padding: 15px;
375
- border-radius: 5px;
376
- margin-bottom: 10px;
377
- font-size: 14px;
378
  }
379
-
380
- .milestone-item.completed {
381
- background-color: #D1FAE5;
382
  }
383
-
384
- .milestone-item.in-progress {
385
- background-color: #EBF5FF;
 
 
386
  }
387
-
388
- .milestone-item.not-started {
389
- background-color: #F3F4F6;
 
 
390
  }
391
-
392
- .milestone-item .progress-bar {
393
  width: 100%;
394
- height: 5px;
395
- background-color: #E2E8F0;
396
- border-radius: 5px;
397
  overflow: hidden;
398
- margin-top: 5px;
399
  }
400
-
401
- .milestone-item .progress-fill {
402
  height: 100%;
403
- background-color: var(--primary-blue);
404
  transition: width 0.5s ease;
405
  }
406
-
407
- .milestone-item .status {
408
- padding: 2px 8px;
 
 
 
 
 
409
  border-radius: 5px;
410
  font-size: 12px;
 
 
411
  }
412
-
413
- .milestone-item .status.completed {
414
- background-color: var(--success-green);
415
- color: #FFFFFF;
416
- }
417
-
418
- .milestone-item .status.in-progress {
419
- background-color: var(--primary-blue);
420
- color: #FFFFFF;
421
- }
422
-
423
- .milestone-item .status.not-started {
424
- background-color: var(--text-muted);
425
- color: #FFFFFF;
426
- }
427
-
428
- /* Profile Section */
429
- .profile-grid {
430
- display: grid;
431
- grid-template-columns: 1fr 2fr;
432
- gap: 20px;
433
- align-items: center;
434
- margin-bottom: 20px;
435
- }
436
-
437
- .profile-grid .avatar {
438
- width: 80px;
439
- height: 80px;
440
- background-color: var(--primary-blue);
441
- color: #FFFFFF;
442
- border-radius: 50%;
443
- display: flex;
444
- align-items: center;
445
- justify-content: center;
446
- font-size: 40px;
447
- }
448
-
449
- .profile-details p {
450
- margin: 5px 0;
451
- font-size: 14px;
452
- }
453
-
454
- .preferences-form {
455
- display: flex;
456
- flex-direction: column;
457
- gap: 15px;
458
- }
459
-
460
- .preferences-form .toggle {
461
- display: flex;
462
- align-items: center;
463
- gap: 10px;
464
- }
465
-
466
- .preferences-form .toggle input {
467
- width: 40px;
468
- height: 20px;
469
- appearance: none;
470
- background-color: #E2E8F0;
471
- border-radius: 20px;
472
- position: relative;
473
- cursor: pointer;
474
- outline: none;
475
- }
476
-
477
- .preferences-form .toggle input:checked {
478
- background-color: var(--primary-blue);
479
- }
480
-
481
- .preferences-form .toggle input::before {
482
- content: '';
483
- width: 16px;
484
- height: 16px;
485
- background-color: #FFFFFF;
486
- border-radius: 50%;
487
- position: absolute;
488
- top: 2px;
489
- left: 2px;
490
- transition: transform 0.3s ease;
491
  }
492
-
493
- .preferences-form .toggle input:checked::before {
494
- transform: translateX(20px);
495
  }
496
-
497
- .preferences-form select {
498
- padding: 10px;
499
- border: 1px solid #E2E8F0;
500
- border-radius: 5px;
501
- font-size: 14px;
502
- }
503
-
504
- /* Buttons */
505
  button {
506
- padding: 10px 20px;
507
- background-color: var(--primary-blue);
508
- color: #FFFFFF;
509
  border: none;
510
- border-radius: 5px;
511
  cursor: pointer;
512
- font-size: 14px;
513
- transition: background 0.3s ease;
 
514
  }
515
-
516
  button:hover {
517
- background-color: #1E4DB7;
 
518
  }
519
-
520
- button.secondary {
521
- background-color: #E2E8F0;
522
- color: var(--text-dark);
523
  }
524
-
525
- button.secondary:hover {
526
- background-color: #D1D5DB;
527
  }
528
-
529
- /* Toast Notifications */
530
  .toast {
531
  position: fixed;
532
  top: 20px;
533
  right: 20px;
534
- padding: 10px 20px;
535
- border-radius: 5px;
536
- z-index: 1000;
537
  display: none;
538
- font-size: 14px;
539
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
 
540
  }
541
-
542
  .toast.error {
543
- background-color: var(--error-red);
544
- color: #FFFFFF;
545
  }
546
-
547
  .toast.success {
548
- background-color: var(--success-green);
549
- color: #FFFFFF;
550
  }
551
-
552
  .toast.visible {
553
  display: block;
554
  }
555
-
556
- /* Responsive Design */
557
- @media (max-width: 768px) {
558
- .sidebar {
559
- width: 60px;
560
- padding: 10px;
561
  }
562
-
563
- .sidebar h1 {
564
- font-size: 14px;
565
  }
566
-
567
- .sidebar a {
568
- padding: 5px;
569
- justify-content: center;
570
  }
571
-
572
- .sidebar a span {
573
- display: none;
 
574
  }
575
-
576
- .main-content {
577
- margin-left: 60px;
578
- padding: 10px;
579
  }
580
-
581
- .dashboard-grid {
582
- grid-template-columns: 1fr;
583
  }
584
-
585
- .metrics-grid {
586
- grid-template-columns: 1fr;
587
  }
588
-
589
- .profile-grid {
590
- grid-template-columns: 1fr;
591
- text-align: center;
592
  }
593
-
594
- .profile-grid .avatar {
595
- margin: 0 auto;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
596
  }
597
  }
598
  </style>
599
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
600
  </head>
601
  <body>
602
- <!-- Sidebar -->
603
- <div class="sidebar">
604
- <h1>STPL Coach</h1>
605
- <a href="#dashboard" class="active" onclick="showSection('dashboard')"><img src="https://img.icons8.com/ios-filled/50/dashboard.png" alt="Dashboard"> <span>Dashboard</span></a>
606
- <a href="#reflections" onclick="showSection('reflections')"><img src="https://img.icons8.com/ios-filled/50/book.png" alt="Reflections"> <span>Reflections</span></a>
607
- <a href="#reports" onclick="showSection('reports')"><img src="https://img.icons8.com/ios-filled/50/report-card.png" alt="Reports"> <span>Reports</span></a>
608
- <a href="#milestones" onclick="showSection('milestones')"><img src="https://img.icons8.com/ios-filled/50/milestone.png" alt="Milestones"> <span>Milestones</span></a>
609
- <a href="#profile" onclick="showSection('profile')"><img src="https://img.icons8.com/ios-filled/50/user.png" alt="Profile"> <span>Profile</span></a>
610
- </div>
611
-
612
- <!-- Main Content -->
613
- <div class="main-content">
614
- <div class="header">
615
- <div></div>
616
- <div class="user-info">
617
- <img src="https://img.icons8.com/ios-filled/50/bell.png" alt="Notifications">
618
- <span>Senior Construction Supervisor</span>
619
- <div class="avatar">A</div>
620
  </div>
621
  </div>
 
622
 
623
- <!-- Dashboard Section -->
624
- <div class="section dashboard-section" id="dashboard-section">
625
- <h2>Good morning, Alex</h2>
626
- <p>Here's your checklist summary for today</p>
627
- <div class="dashboard-grid">
628
- <div>
629
- <h3>Today's Checklist</h3>
630
- <p>1 of 5 complete</p>
631
- <div id="checklist-items">
632
- <div class="checklist-item">
633
- <input type="checkbox" id="checklist-0" onchange="markComplete(0, this)">
634
- <label for="checklist-0" class="category-safety">Review safety equipment status for concrete pouring team</label>
635
- </div>
636
- <div class="checklist-item">
637
- <input type="checkbox" id="checklist-1" onchange="markComplete(1, this)">
638
- <label for="checklist-1" class="category-materials">Verify delivery of steel reinforcement for floor 3</label>
639
- </div>
640
- <div class="checklist-item">
641
- <input type="checkbox" id="checklist-2" onchange="markComplete(2, this)">
642
- <label for="checklist-2">Coordinate with electrical contractor on conduit installation</label>
643
- </div>
644
- <div class="checklist-item">
645
- <input type="checkbox" id="checklist-3" onchange="markComplete(3, this)">
646
- <label for="checklist-3" class="category-inspection">Inspect temporary weather protection measures</label>
647
- </div>
648
- <div class="checklist-item">
649
- <input type="checkbox" id="checklist-4" onchange="markComplete(4, this)">
650
- <label for="checklist-4">Update project timeline based on foundation completion</label>
651
- </div>
652
- </div>
653
-
654
- <h3>Today's Coaching Tips</h3>
655
- <div class="tips-card warning">
656
- <strong>Focus on Weather Preparedness:</strong> Weather forecasts show rain in the next 48 hours. Ensure all open areas are properly covered and drainage systems are clear.
657
- </div>
658
- <div class="tips-card info">
659
- <strong>Team Motivation:</strong> The concrete team has been exceeding expectations. Consider acknowledging their performance in the next team meeting to boost morale.
660
- </div>
661
- <div class="tips-card medium">
662
- <strong>Schedule Optimization:</strong> Based on current pace, electrical work can begin 2 days earlier than planned. Consider adjusting the schedule to improve overall timeline.
663
- </div>
664
- </div>
665
- <div>
666
- <h3>Project Progress</h3>
667
- <div class="project-progress">
668
- <p>Riverfront Commercial Complex<br>Aug 15, 2023 - Feb 28, 2025</p>
669
- <p><strong>Overall Progress:</strong> 35%</p>
670
- <div class="progress-bar">
671
- <div class="progress-fill" style="width: 35%"></div>
672
- </div>
673
- <p><strong>Current Milestone:</strong> Structural Steel Erection (65% Complete)<br>Due: Dec 15, 2023</p>
674
- </div>
675
 
676
- <h3>Performance Metrics</h3>
677
- <div class="metrics-grid">
678
- <div class="metric-card">
679
- <h4>Engagement</h4>
680
- <div class="value">87%</div>
681
- <p class="trend">Weekly Engagement Trend: High</p>
682
- </div>
683
- <div class="metric-card">
684
- <h4>Completion</h4>
685
- <div class="value">92%</div>
686
- </div>
687
- <div class="metric-card">
688
- <h4>Stress</h4>
689
- <div class="value">7 days</div>
690
- </div>
691
- </div>
692
- <p>2 KPI Flags</p>
693
  </div>
 
694
  </div>
695
- </div>
696
 
697
- <!-- Reflections Section -->
698
- <div class="section reflections-section" id="reflections-section" style="display: none;">
699
- <h2>Reflection Journal</h2>
700
- <p>Record daily reflections and insights to improve your leadership</p>
701
- <h3>Add Daily Reflection</h3>
702
- <div class="reflection-input">
703
- <p>How are you feeling today?</p>
704
- <div class="mood-buttons">
705
- <button onclick="selectMood('Satisfied')">Satisfied</button>
706
- <button onclick="selectMood('Motivated')">Motivated</button>
707
- <button onclick="selectMood('Neutral')">Neutral</button>
708
- <button onclick="selectMood('Concerned')">Concerned</button>
709
- <button onclick="selectMood('Frustrated')">Frustrated</button>
710
- </div>
711
- <textarea id="reflection-input" placeholder="Share your thoughts on today’s progress, challenges, or learnings..."></textarea>
712
- <button class="secondary" onclick="submitReflection()">Submit Reflection</button>
713
- </div>
714
- <h3>Reflection History</h3>
715
- <div class="reflection-history" id="reflection-history">
716
- <div class="entry">
717
- <span class="date">Nov 15, 2023</span><span class="mood concerned">Concerned</span>
718
- <p>Faced challenges with the concrete supplier today. Need to improve communication channels and possibly consider backup suppliers for critical phases.</p>
719
- <p><strong>Learned:</strong> Always have contingency plans for key materials.</p>
720
- </div>
721
- <div class="entry">
722
- <span class="date">Nov 14, 2023</span><span class="mood satisfied">Satisfied</span>
723
- <p>Team excelled during the steel installation. The morning huddle approach is working well, setting daily priorities.</p>
724
- <p><strong>Learned:</strong> Regular brief check-ins improve team alignment.</p>
725
- </div>
726
- <div class="entry">
727
- <span class="date">Nov 13, 2023</span><span class="mood neutral">Neutral</span>
728
- <p>Safety inspection identified several minor issues that were quickly addressed. Need to remind the team about proper ladder protocols.</p>
729
- <p><strong>Learned:</strong> Regular safety reminders are necessary even for experienced workers.</p>
730
- </div>
731
  </div>
732
- </div>
733
 
734
- <!-- Reports Section -->
735
- <div class="section reports-section" id="reports-section" style="display: none;">
736
- <h2>Reports & Analytics</h2>
737
- <p>Generate and download reports for your performance and project status</p>
738
- <h3>Generate New Report</h3>
739
- <div class="report-form">
740
- <input type="text" placeholder="Enter report title" id="report-title">
741
- <select id="report-type">
742
- <option value="Weekly Summary">Weekly Summary</option>
743
- <option value="Monthly Review">Monthly Review</option>
744
- </select>
745
- <div class="date-range">
746
- <input type="date" id="start-date" value="2025-04-30">
747
- <input type="date" id="end-date" value="2025-05-07">
748
- </div>
749
- <div>
750
- <input type="checkbox" id="include-metrics" checked>
751
- <label for="include-metrics">Performance metrics & KPIs</label>
752
- </div>
753
- <div>
754
- <input type="checkbox" id="include-reflections" checked>
755
- <label for="include-reflections">Daily reflections & learnings</label>
756
- </div>
757
- <button class="secondary" onclick="generateReport()">Generate Report</button>
758
- </div>
759
- <h3>Your Reports</h3>
760
- <div class="report-list" id="report-list">
761
- <div class="report-item">
762
- <div>
763
- <p>Weekly Performance Summary</p>
764
- <p>Nov 12, 2023 • Weekly Summary</p>
765
- <p>Completion: 92% • Milestones: 2 • Improvements: 3</p>
766
- </div>
767
- <div>
768
- <span class="status">Generated</span>
769
- <button onclick="downloadReport('weekly')">Download</button>
770
- </div>
771
- </div>
772
- <div class="report-item">
773
- <div>
774
- <p>October Monthly Review</p>
775
- <p>Nov 1, 2023 • Monthly Performance</p>
776
- <p>Completion: 88% • Milestones: 4 • Improvements: 5</p>
777
- </div>
778
- <div>
779
- <span class="status">Generated</span>
780
- <button onclick="downloadReport('monthly')">Download</button>
781
- </div>
782
- </div>
783
  </div>
784
- </div>
785
 
786
- <!-- Milestones Section -->
787
- <div class="section milestones-section" id="milestones-section" style="display: none;">
788
- <div class="milestones-header">
789
- <div>
790
- <h2>Project Milestones</h2>
791
- <p>Track and update project milestones for Riverfront Commercial Complex</p>
792
- </div>
793
- <div>
794
- <button class="secondary" onclick="syncSalesforce()">Sync with Salesforce</button>
795
- <button onclick="addMilestone()">Add Milestone</button>
796
- </div>
797
- </div>
798
- <div id="milestones-list">
799
- <div class="milestone-item completed">
800
- <div>
801
- <p><strong>Foundation Completion</strong></p>
802
- <p>Due: Oct 30, 2023</p>
803
- <p>Complete site foundation work including footings, piers, and foundation walls</p>
804
- <div class="progress-bar">
805
- <div class="progress-fill" style="width: 100%"></div>
806
- </div>
807
- </div>
808
- <span class="status completed">Completed</span>
809
- </div>
810
- <div class="milestone-item in-progress">
811
- <div>
812
- <p><strong>Structural Steel Erection</strong></p>
813
- <p>Due: Dec 15, 2023</p>
814
- <p>Erect the structural steel components for the main building frame</p>
815
- <div class="progress-bar">
816
- <div class="progress-fill" style="width: 65%"></div>
817
- </div>
818
- </div>
819
- <span class="status in-progress">In Progress</span>
820
- </div>
821
- <div class="milestone-item not-started">
822
- <div>
823
- <p><strong>Building Envelope</strong></p>
824
- <p>Due: Mar 1, 2024</p>
825
- <p>Complete exterior walls, roofing, and weatherproofing</p>
826
- <div class="progress-bar">
827
- <div class="progress-fill" style="width: 0%"></div>
828
- </div>
829
- </div>
830
- <span class="status not-started">Not Started</span>
831
- </div>
832
- <div class="milestone-item not-started">
833
- <div>
834
- <p><strong>MEP Rough-in</strong></p>
835
- <p>Due: May 15, 2024</p>
836
- <p>Complete mechanical, electrical, and plumbing rough-in work</p>
837
- <div class="progress-bar">
838
- <div class="progress-fill" style="width: 0%"></div>
839
- </div>
840
- </div>
841
- <span class="status not-started">Not Started</span>
842
  </div>
843
- <div class="milestone-item not-started">
844
- <div>
845
- <p><strong>Interior Finishing</strong></p>
846
- <p>Due: Oct 30, 2024</p>
847
- <p>Complete all interior finishes including drywall, flooring, and fixtures</p>
848
- <div class="progress-bar">
849
- <div class="progress-fill" style="width: 0%"></div>
850
- </div>
851
- </div>
852
- <span class="status not-started">Not Started</span>
853
  </div>
854
  </div>
855
- </div>
856
 
857
- <!-- Profile Section -->
858
- <div class="section profile-section" id="profile-section" style="display: none;">
859
- <h2>Profile & Settings</h2>
860
- <p>Manage your profile and AI coaching preferences</p>
861
- <h3>Supervisor Profile</h3>
862
- <div class="profile-grid">
863
- <div class="avatar">A</div>
864
- <div class="profile-details">
865
- <p><strong>Name:</strong> Alex Rivera</p>
866
- <p><strong>Email:</strong> [email protected]</p>
867
- <p><strong>Phone:</strong> (555) 123-4567</p>
868
- <p><strong>Role:</strong> Senior Construction Supervisor</p>
869
- <p><strong>Company:</strong> STPL Construction</p>
870
- <p><strong>Experience:</strong> 12 years</p>
871
- </div>
872
- </div>
873
- <h3>Coaching Preferences</h3>
874
- <div class="preferences-form">
875
- <div class="toggle">
876
- <label>AI Coaching Notifications</label>
877
- <input type="checkbox" id="notifications-toggle" checked>
878
- </div>
879
- <p>Receive push notifications for new coaching tips and checklist reminders</p>
880
- <div>
881
- <label>Coaching Frequency</label>
882
- <select id="coaching-frequency">
883
- <option value="Daily">Daily</option>
884
- <option value="Weekly">Weekly</option>
885
- </select>
886
- </div>
887
- <div>
888
- <label>Preferred Time</label>
889
- <select id="preferred-time">
890
- <option value="Morning 6:00 AM">Morning 6:00 AM</option>
891
- <option value="Evening 6:00 PM">Evening 6:00 PM</option>
892
- </select>
893
- </div>
894
- <button onclick="savePreferences()">Save Preferences</button>
895
  </div>
896
  </div>
897
  </div>
898
 
899
- <!-- Toast Notifications -->
900
  <div id="error" class="toast error"></div>
901
  <div id="success" class="toast success"></div>
902
 
903
  <script>
904
- let supervisorData = {
905
- supervisor_id: 'SUP_001',
906
- role: 'Senior Construction Supervisor',
907
- project_id: 'Riverfront_001',
908
- milestones: [
909
- { name: 'Foundation Completion', status: 'Completed', progress: 100, due: '2023-10-30' },
910
- { name: 'Structural Steel Erection', status: 'In Progress', progress: 65, due: '2023-12-15' },
911
- { name: 'Building Envelope', status: 'Not Started', progress: 0, due: '2024-03-01' },
912
- { name: 'MEP Rough-in', status: 'Not Started', progress: 0, due: '2024-05-15' },
913
- { name: 'Interior Finishing', status: 'Not Started', progress: 0, due: '2024-10-30' }
914
- ],
915
- reflection_log: '',
916
- engagement_score: 87,
917
- completion_rate: 92,
918
- stress_days: 7
919
- };
920
- let coachingOutput = {
921
- checklist: [
922
- 'Review safety equipment status for concrete pouring team',
923
- 'Verify delivery of steel reinforcement for floor 3',
924
- 'Coordinate with electrical contractor on conduit installation',
925
- 'Inspect temporary weather protection measures',
926
- 'Update project timeline based on foundation completion'
927
- ],
928
- tips: [
929
- 'Focus on Weather Preparedness: Weather forecasts show rain in the next 48 hours. Ensure all open areas are properly covered and drainage systems are clear.',
930
- 'Team Motivation: The concrete team has been exceeding expectations. Consider acknowledging their performance in the next team meeting to boost morale.',
931
- 'Schedule Optimization: Based on current pace, electrical work can begin 2 days earlier than planned. Consider adjusting the schedule to improve overall timeline.'
932
- ],
933
- quote: 'Success is the sum of small efforts, repeated day in and day out.'
934
- };
935
- let reflectionHistory = [
936
- { date: 'Nov 15, 2023', mood: 'Concerned', text: 'Faced challenges with the concrete supplier today. Need to improve communication channels and possibly consider backup suppliers for critical phases.', learned: 'Always have contingency plans for key materials.' },
937
- { date: 'Nov 14, 2023', mood: 'Satisfied', text: 'Team excelled during the steel installation. The morning huddle approach is working well, setting daily priorities.', learned: 'Regular brief check-ins improve team alignment.' },
938
- { date: 'Nov 13, 2023', mood: 'Neutral', text: 'Safety inspection identified several minor issues that were quickly addressed. Need to remind the team about proper ladder protocols.', learned: 'Regular safety reminders are necessary even for experienced workers.' }
939
- ];
940
  let checklistProgress = 0;
941
- let totalChecklistItems = coachingOutput.checklist.length;
942
- let selectedMood = '';
943
 
944
- // Toast Notification Function
945
  function showToast(id, message) {
946
  const toast = document.getElementById(id);
947
  toast.textContent = message;
@@ -951,251 +619,327 @@
951
  }, 3000);
952
  }
953
 
954
- // Navigation
955
- function showSection(section) {
956
- document.querySelectorAll('.section').forEach(s => s.style.display = 'none');
957
- document.getElementById(`${section}-section`).style.display = 'block';
958
- document.querySelectorAll('.sidebar a').forEach(a => a.classList.remove('active'));
959
- document.querySelector(`.sidebar a[href="#${section}"]`).classList.add('active');
960
- }
961
-
962
- // Checklist
963
- function markComplete(index, checkbox) {
964
- const itemDiv = checkbox.parentElement;
965
- if (checkbox.checked) {
966
- itemDiv.classList.add('completed');
967
- } else {
968
- itemDiv.classList.remove('completed');
969
  }
970
- updateChecklistProgress();
971
- showToast('success', `Checklist item ${index + 1} marked as ${checkbox.checked ? 'complete' : 'incomplete'}.`);
972
  }
973
 
974
- function updateChecklistProgress() {
975
- const completedItems = document.querySelectorAll('#checklist-items input:checked').length;
976
- checklistProgress = totalChecklistItems > 0 ? (completedItems / totalChecklistItems) * 100 : 0;
977
  }
978
 
979
- // Reflections
980
- function selectMood(mood) {
981
- selectedMood = mood;
982
- document.querySelectorAll('.mood-buttons button').forEach(btn => btn.classList.remove('active'));
983
- document.querySelector(`.mood-buttons button[onclick="selectMood('${mood}')"]`).classList.add('active');
984
  }
985
 
986
- async function submitReflection() {
987
- const reflectionInput = document.getElementById('reflection-input').value.trim();
988
-
989
- if (!reflectionInput) {
990
- showToast('error', 'Please enter a reflection before submitting.');
991
- return;
992
- }
993
-
994
- if (!selectedMood) {
995
- showToast('error', 'Please select a mood before submitting.');
996
- return;
997
- }
998
-
999
  try {
1000
- const response = await fetch('/submit_reflection', {
1001
  method: 'POST',
1002
- headers: { 'Content-Type': 'application/json' },
1003
- body: JSON.stringify({ reflection: reflectionInput, mood: selectedMood })
1004
  });
1005
  const result = await response.json();
1006
-
1007
  if (result.status === 'success') {
1008
- supervisorData.reflection_log = reflectionInput;
1009
- reflectionHistory.unshift({
1010
- date: new Date().toLocaleString(),
1011
- mood: selectedMood,
1012
- text: reflectionInput,
1013
- learned: 'To be analyzed by AI...'
1014
- });
1015
- updateReflectionHistory();
1016
- document.getElementById('reflection-input').value = '';
1017
- selectedMood = '';
1018
- document.querySelectorAll('.mood-buttons button').forEach(btn => btn.classList.remove('active'));
1019
- showToast('success', 'Reflection submitted successfully.');
1020
  } else {
1021
  showToast('error', result.message);
1022
  }
1023
  } catch (error) {
1024
- showToast('error', 'Error submitting reflection: ' + error.message);
1025
  }
1026
  }
1027
 
1028
- function updateReflectionHistory() {
1029
- const historyDiv = document.getElementById('reflection-history');
1030
- historyDiv.innerHTML = '';
1031
- if (reflectionHistory.length > 0) {
1032
- reflectionHistory.forEach(ref => {
1033
- const entryDiv = document.createElement('div');
1034
- entryDiv.className = 'entry';
1035
- entryDiv.innerHTML = `
1036
- <span class="date">${ref.date}</span><span class="mood ${ref.mood.toLowerCase()}">${ref.mood}</span>
1037
- <p>${ref.text}</p>
1038
- <p><strong>Learned:</strong> ${ref.learned}</p>
1039
- `;
1040
- historyDiv.appendChild(entryDiv);
1041
- });
1042
- } else {
1043
- historyDiv.innerHTML = '<p>No reflections yet. Start logging your thoughts!</p>';
1044
  }
1045
- }
1046
 
1047
- // Reports
1048
- async function generateReport() {
1049
- const title = document.getElementById('report-title').value.trim();
1050
- const type = document.getElementById('report-type').value;
1051
- const startDate = document.getElementById('start-date').value;
1052
- const endDate = document.getElementById('end-date').value;
1053
- const includeMetrics = document.getElementById('include-metrics').checked;
1054
- const includeReflections = document.getElementById('include-reflections').checked;
1055
 
1056
- if (!title) {
1057
- showToast('error', 'Please enter a report title.');
1058
- return;
1059
  }
1060
 
1061
- try {
1062
- const response = await fetch('/generate_pdf', {
1063
- method: 'POST',
1064
- headers: { 'Content-Type': 'application/json' },
1065
- body: JSON.stringify({
1066
- title,
1067
- type,
1068
- startDate,
1069
- endDate,
1070
- includeMetrics,
1071
- includeReflections,
1072
- checklist: coachingOutput?.checklist || [],
1073
- tips: coachingOutput?.tips || [],
1074
- milestones: supervisorData?.milestones || [],
1075
- reflections: reflectionHistory
1076
- })
1077
  });
1078
- const result = await response.json();
1079
- if (result.status === 'success') {
1080
- const reportList = document.getElementById('report-list');
1081
- const reportItem = document.createElement('div');
1082
- reportItem.className = 'report-item';
1083
- reportItem.innerHTML = `
1084
- <div>
1085
- <p>${title}</p>
1086
- <p>${new Date().toLocaleDateString()} • ${type}</p>
1087
- <p>Completion: ${supervisorData.completion_rate}% • Milestones: ${supervisorData.milestones.length} • Improvements: ${reflectionHistory.length}</p>
1088
- </div>
1089
- <div>
1090
- <span class="status">Generated</span>
1091
- <button onclick="downloadReport('${title}')">Download</button>
1092
- </div>
1093
- `;
1094
- reportList.prepend(reportItem);
1095
- showToast('success', 'Report generated successfully.');
1096
- } else {
1097
- showToast('error', result.message || 'Failed to generate report.');
1098
- }
1099
- } catch (error) {
1100
- showToast('error', 'Error generating report: ' + error.message);
1101
  }
1102
  }
1103
 
1104
- async function downloadReport(title) {
1105
- showToast('success', `Downloading report: ${title}`);
1106
  }
1107
 
1108
- // Milestones
1109
- async function syncSalesforce() {
1110
- try {
1111
- const response = await fetch('/sync_salesforce', {
1112
- method: 'POST',
1113
- headers: { 'Content-Type': 'application/json' }
1114
- });
1115
- const result = await response.json();
1116
- if (result.status === 'success') {
1117
- supervisorData.milestones = result.data.milestones;
1118
- updateMilestones();
1119
- showToast('success', 'Milestones synced with Salesforce.');
1120
- } else {
1121
- showToast('error', result.message);
1122
- }
1123
- } catch (error) {
1124
- showToast('error', 'Error syncing with Salesforce: ' + error.message);
1125
- }
1126
  }
1127
 
1128
- async function addMilestone() {
1129
- const name = prompt('Enter milestone name:');
1130
- const due = prompt('Enter due date (YYYY-MM-DD):');
1131
- if (name && due) {
1132
- supervisorData.milestones.push({
1133
- name,
1134
- status: 'Not Started',
1135
- progress: 0,
1136
- due
1137
- });
1138
- updateMilestones();
1139
- showToast('success', 'Milestone added successfully.');
1140
  } else {
1141
- showToast('error', 'Please provide both name and due date.');
1142
  }
 
1143
  }
1144
 
1145
- function updateMilestones() {
1146
- const milestonesDiv = document.getElementById('milestones-list');
1147
- milestonesDiv.innerHTML = '';
1148
- if (supervisorData.milestones?.length > 0) {
1149
- supervisorData.milestones.forEach(milestone => {
1150
- const milestoneDiv = document.createElement('div');
1151
- milestoneDiv.className = `milestone-item ${milestone.status.toLowerCase().replace(' ', '-')}`;
1152
- milestoneDiv.innerHTML = `
1153
- <div>
1154
- <p><strong>${milestone.name}</strong></p>
1155
- <p>Due: ${milestone.due}</p>
1156
- <p>${milestone.description || ''}</p>
1157
- <div class="progress-bar">
1158
- <div class="progress-fill" style="width: ${milestone.progress}%"></div>
1159
- </div>
1160
- </div>
1161
- <span class="status ${milestone.status.toLowerCase().replace(' ', '-')}">${milestone.status}</span>
1162
- `;
1163
- milestonesDiv.appendChild(milestoneDiv);
 
 
 
 
 
1164
  });
 
1165
  } else {
1166
- milestonesDiv.innerHTML = '<p>No milestones available.</p>';
1167
  }
1168
- }
1169
 
1170
- // Profile
1171
- async function savePreferences() {
1172
- const notifications = document.getElementById('notifications-toggle').checked;
1173
- const frequency = document.getElementById('coaching-frequency').value;
1174
- const time = document.getElementById('preferred-time').value;
 
 
 
 
 
 
 
 
 
 
 
1175
 
1176
- try {
1177
- const response = await fetch('/save_preferences', {
1178
- method: 'POST',
1179
- headers: { 'Content-Type': 'application/json' },
1180
- body: JSON.stringify({ notifications, frequency, time })
1181
  });
1182
- const result = await response.json();
1183
- if (result.status === 'success') {
1184
- showToast('success', 'Preferences saved successfully.');
1185
- } else {
1186
- showToast('error', result.message);
1187
- }
1188
- } catch (error) {
1189
- showToast('error', 'Error saving preferences: ' + error.message);
1190
  }
1191
- }
1192
 
1193
- // Initialize
1194
- window.onload = () => {
1195
- updateChecklistProgress();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1196
  updateReflectionHistory();
1197
- updateMilestones();
1198
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1199
  </script>
1200
  </body>
1201
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Coach Dashboard</title>
7
  <style>
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  body {
9
  font-family: 'Roboto', Arial, sans-serif;
10
  margin: 0;
11
  padding: 0;
12
+ background: linear-gradient(135deg, #f0f2f5 0%, #e9ecef 100%);
13
+ color: #2d3748;
14
  line-height: 1.6;
 
15
  }
16
+ .header {
17
+ background: linear-gradient(to right, #1a3c7a, #2957a4);
18
+ padding: 15px 25px;
19
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
20
+ position: sticky;
 
 
21
  top: 0;
22
+ z-index: 100;
 
 
 
 
 
23
  }
24
+ .header-title {
25
+ color: #fff;
26
+ margin: 0;
27
+ font-size: 26px;
28
+ font-weight: 700;
29
+ text-align: center;
30
+ padding-bottom: 10px;
31
  }
32
+ .header-actions {
 
33
  display: flex;
34
  align-items: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  justify-content: space-between;
36
+ gap: 20px;
 
 
 
37
  }
38
+ .avatar {
39
+ width: 42px;
40
+ height: 42px;
41
+ background: linear-gradient(to right, #f6ad55, #ed8936);
42
+ color: #fff;
43
+ border-radius: 50%;
44
  display: flex;
45
  align-items: center;
46
+ justify-content: center;
47
+ font-size: 20px;
48
+ font-weight: 600;
49
+ cursor: pointer;
50
+ position: relative;
51
+ transition: transform 0.2s ease;
52
  }
53
+ .avatar:hover {
54
+ transform: scale(1.05);
55
+ background: linear-gradient(to right, #ed8936, #dd6b20);
 
56
  }
57
+ .dropdown {
58
+ display: none;
59
+ position: absolute;
60
+ top: 50px;
61
+ right: 0;
62
+ background-color: #fff;
63
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
64
+ border-radius: 10px;
65
+ min-width: 160px;
66
+ z-index: 101;
67
+ overflow: hidden;
68
  }
69
+ .dropdown.active {
70
+ display: block;
 
 
 
 
 
 
 
 
 
71
  }
72
+ .dropdown a {
73
+ display: block;
74
+ padding: 12px 20px;
75
+ color: #2d3748;
76
+ text-decoration: none;
77
+ font-size: 15px;
78
+ transition: background 0.3s ease;
 
79
  }
80
+ .dropdown a:hover {
81
+ background-color: #f7fafc;
 
 
 
82
  }
83
+ .search-container {
84
+ position: relative;
85
+ flex: 1;
86
+ max-width: 500px;
 
87
  }
88
+ .search-bar {
89
+ width: 100%;
90
+ padding: 12px 45px 12px 20px;
91
+ border: 2px solid #e2e8f0;
92
+ border-radius: 25px;
93
+ font-size: 15px;
94
+ box-sizing: border-box;
95
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
96
+ background-color: #fff;
97
+ }
98
+ .search-bar:focus {
99
+ border-color: #ed8936;
100
+ outline: none;
101
+ box-shadow: 0 0 8px rgba(237, 137, 54, 0.3);
102
  }
103
+ .mic-icon {
104
+ position: absolute;
105
+ right: 15px;
106
+ top: 50%;
107
+ transform: translateY(-50%);
108
+ width: 22px;
109
+ height: 22px;
110
+ background: url('https://img.icons8.com/ios-filled/50/000000/microphone.png') no-repeat center;
111
+ background-size: contain;
112
+ cursor: pointer;
113
+ opacity: 0.6;
114
+ transition: opacity 0.3s ease;
115
  }
116
+ .mic-icon:hover {
117
+ opacity: 1;
 
118
  }
119
+ .search-results {
120
+ position: absolute;
121
+ top: 50px;
122
+ left: 0;
123
+ right: 0;
124
+ background-color: #fff;
125
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
126
+ border-radius: 10px;
127
+ max-height: 220px;
128
+ overflow-y: auto;
129
+ z-index: 100;
130
+ display: none;
131
  }
132
+ .search-results.active {
133
+ display: block;
 
134
  }
135
+ .search-results p {
136
+ padding: 10px 15px;
137
+ margin: 0;
138
+ font-size: 14px;
139
+ color: #4a5568;
140
+ border-bottom: 1px solid #edf2f7;
141
+ transition: background 0.2s ease;
142
  }
143
+ .search-results p:hover {
144
+ background-color: #f7fafc;
 
145
  }
146
+ .search-results p:last-child {
147
+ border-bottom: none;
 
 
 
148
  }
149
+ .action-bar {
150
+ background-color: #fff;
151
+ padding: 15px 25px;
152
+ display: flex;
153
+ justify-content: center;
154
+ gap: 20px;
155
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
156
+ position: sticky;
157
+ top: 90px;
158
+ z-index: 99;
159
  }
160
+ .container {
161
+ max-width: 1200px;
162
+ margin: 40px auto;
163
+ padding: 0 25px;
 
164
  }
165
+ .content-grid {
 
166
  display: grid;
167
+ grid-template-columns: 1fr 1fr;
168
+ gap: 30px;
169
+ margin-bottom: 40px;
170
  }
171
+ .section {
172
+ padding: 25px;
173
+ background-color: #fff;
174
+ border-radius: 12px;
175
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
176
+ border-left: 5px solid #ed8936;
177
+ transition: transform 0.2s ease, box-shadow 0.3s ease;
178
  }
179
+ .section:hover {
180
+ transform: translateY(-5px);
181
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
 
 
182
  }
183
+ .section.full-width {
184
+ grid-column: span 2;
 
 
 
185
  }
186
+ h3 {
187
+ margin: 0 0 20px 0;
188
+ color: #1a3c7a;
189
+ font-size: 22px;
190
+ font-weight: 600;
191
+ display: flex;
192
+ align-items: center;
193
+ gap: 10px;
194
  }
195
+ h3 i {
196
+ font-size: 20px;
197
+ color: #ed8936;
 
 
 
198
  }
199
+ .checklist-header {
200
+ display: flex;
201
+ justify-content: space-between;
202
+ align-items: center;
203
+ margin-bottom: 20px;
204
  }
205
+ .progress-circle {
206
+ width: 50px;
207
+ height: 50px;
208
+ background: conic-gradient(#ed8936 var(--progress), #e2e8f0 0);
209
+ border-radius: 50%;
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: center;
213
+ font-size: 14px;
214
+ font-weight: 600;
215
+ color: #2d3748;
216
+ position: relative;
217
  }
218
+ .progress-circle::before {
219
+ content: '';
220
+ position: absolute;
221
+ width: 40px;
222
+ height: 40px;
223
+ background-color: #fff;
224
+ border-radius: 50%;
225
  }
226
+ .progress-circle span {
227
+ position: relative;
228
+ z-index: 1;
229
+ }
230
+ .checklist-item {
231
  display: flex;
232
+ align-items: center;
233
  margin-bottom: 15px;
234
+ font-size: 16px;
235
+ padding: 10px;
236
+ border-radius: 8px;
237
+ transition: background 0.2s ease;
238
  }
239
+ .checklist-item:hover {
240
+ background-color: #f7fafc;
241
+ }
242
+ .checklist-item input {
243
+ width: 20px;
244
+ height: 20px;
245
+ margin-right: 15px;
246
+ accent-color: #ed8936;
247
  cursor: pointer;
 
248
  }
249
+ .checklist-item label {
250
+ flex: 1;
251
+ color: #4a5568;
252
+ cursor: pointer;
 
253
  }
254
+ .checklist-item.completed label {
255
+ text-decoration: line-through;
256
+ color: #a0aec0;
 
 
 
 
 
 
 
257
  }
258
+ .tip-card {
259
+ background: linear-gradient(145deg, #e6f0fa, #d1e3ff);
260
+ padding: 20px;
261
+ border-radius: 10px;
262
+ margin-bottom: 15px;
263
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
264
+ transition: transform 0.2s ease;
265
  }
266
+ .tip-card:hover {
267
+ transform: translateY(-3px);
 
268
  }
269
+ .tip-card h4 {
270
+ margin: 0 0 15px 0;
271
+ color: #1a3c7a;
272
+ font-size: 18px;
273
  font-weight: 600;
 
274
  }
275
+ .tip-card ul {
276
+ padding-left: 20px;
277
+ margin: 0;
278
+ list-style-type: disc;
 
 
279
  }
280
+ .tip-card li {
281
+ margin-bottom: 10px;
282
+ font-size: 15px;
283
+ color: #4a5568;
284
  }
285
+ pre {
286
+ background-color: #f7fafc;
287
+ padding: 15px;
288
+ border: 1px solid #e2e8f0;
289
+ border-radius: 8px;
290
+ white-space: pre-wrap;
291
+ font-size: 15px;
292
+ max-height: 250px;
293
+ overflow-y: auto;
294
+ color: #4a5568;
295
  }
296
+ .reflection-journal {
297
+ display: flex;
298
+ flex-direction: column;
299
+ gap: 20px;
300
  }
301
+ .reflection-input-area {
 
 
302
  display: flex;
303
  flex-direction: column;
304
  gap: 15px;
305
  }
306
+ .reflection-journal textarea {
307
+ width: 100%;
308
+ height: 120px;
309
+ padding: 15px;
310
+ border: 2px solid #e2e8f0;
311
+ border-radius: 10px;
312
+ resize: none;
313
+ font-size: 15px;
314
+ box-sizing: border-box;
315
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
316
+ background-color: #f7fafc;
317
  }
318
+ .reflection-journal textarea:focus {
319
+ border-color: #ed8936;
320
+ outline: none;
321
+ box-shadow: 0 0 8px rgba(237, 137, 54, 0.3);
322
  }
323
+ .reflection-history {
324
+ max-height: 200px;
325
+ overflow-y: auto;
326
+ padding: 15px;
327
+ background-color: #f7fafc;
328
+ border-radius: 10px;
329
+ border: 1px solid #e2e8f0;
330
+ }
331
+ .reflection-entry {
332
+ margin-bottom: 15px;
333
+ padding-bottom: 10px;
334
+ border-bottom: 1px solid #e2e8f0;
335
  font-size: 14px;
336
+ color: #4a5568;
337
  }
338
+ .reflection-entry:last-child {
 
339
  border-bottom: none;
340
+ margin-bottom: 0;
341
  }
342
+ .reflection-entry span {
343
+ font-weight: 600;
344
+ color: #2d3748;
 
 
 
 
345
  }
346
+ .kpi-dashboard {
347
+ display: grid;
348
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
349
+ gap: 20px;
350
+ padding: 20px;
351
+ background: linear-gradient(145deg, #fff, #f7fafc);
352
+ border-radius: 12px;
353
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
354
  }
355
+ .kpi-card {
356
+ padding: 20px;
357
+ border-radius: 10px;
358
+ background-color: #fff;
359
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
360
+ text-align: center;
361
+ transition: transform 0.2s ease;
 
 
362
  }
363
+ .kpi-card:hover {
364
+ transform: translateY(-3px);
 
365
  }
366
+ .kpi-card h4 {
367
+ margin: 0 0 10px 0;
368
+ font-size: 16px;
369
+ color: #1a3c7a;
370
+ font-weight: 600;
371
  }
372
+ .kpi-value {
373
+ font-size: 24px;
374
+ font-weight: 700;
375
+ color: #ed8936;
376
+ margin-bottom: 10px;
377
  }
378
+ .progress-bar {
 
379
  width: 100%;
380
+ height: 8px;
381
+ background-color: #e2e8f0;
382
+ border-radius: 4px;
383
  overflow: hidden;
 
384
  }
385
+ .progress-fill {
 
386
  height: 100%;
387
+ background: linear-gradient(to right, #ed8936, #f6ad55);
388
  transition: width 0.5s ease;
389
  }
390
+ .kpi-trend {
391
+ font-size: 13px;
392
+ color: #718096;
393
+ margin-top: 8px;
394
+ }
395
+ .kpi-flag {
396
+ display: inline-block;
397
+ padding: 5px 10px;
398
  border-radius: 5px;
399
  font-size: 12px;
400
+ font-weight: 600;
401
+ margin-top: 8px;
402
  }
403
+ .kpi-flag.active {
404
+ background-color: #48bb78;
405
+ color: #fff;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  }
407
+ .kpi-flag.inactive {
408
+ background-color: #f56565;
409
+ color: #fff;
410
  }
 
 
 
 
 
 
 
 
 
411
  button {
412
+ padding: 12px 25px;
413
+ background: linear-gradient(to right, #f6ad55, #ed8936);
414
+ color: #fff;
415
  border: none;
416
+ border-radius: 8px;
417
  cursor: pointer;
418
+ font-size: 15px;
419
+ font-weight: 600;
420
+ transition: transform 0.1s ease, background 0.3s ease;
421
  }
 
422
  button:hover {
423
+ background: linear-gradient(to right, #ed8936, #dd6b20);
424
+ transform: scale(1.02);
425
  }
426
+ .download-btn {
427
+ background: linear-gradient(to right, #38a169, #48bb78);
 
 
428
  }
429
+ .download-btn:hover {
430
+ background: linear-gradient(to right, #2f855a, #38a169);
 
431
  }
 
 
432
  .toast {
433
  position: fixed;
434
  top: 20px;
435
  right: 20px;
436
+ padding: 15px 25px;
437
+ border-radius: 8px;
438
+ z-index: 102;
439
  display: none;
440
+ font-size: 15px;
441
+ font-weight: 500;
442
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
443
  }
 
444
  .toast.error {
445
+ background-color: #f56565;
446
+ color: #fff;
447
  }
 
448
  .toast.success {
449
+ background-color: #48bb78;
450
+ color: #fff;
451
  }
 
452
  .toast.visible {
453
  display: block;
454
  }
455
+ @media (max-width: 900px) {
456
+ .content-grid {
457
+ grid-template-columns: 1fr;
 
 
 
458
  }
459
+ .section.full-width {
460
+ grid-column: span 1;
 
461
  }
462
+ .kpi-dashboard {
463
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
 
 
464
  }
465
+ }
466
+ @media (max-width: 700px) {
467
+ body {
468
+ padding: 0;
469
  }
470
+ .header {
471
+ padding: 10px 15px;
 
 
472
  }
473
+ .header-title {
474
+ font-size: 22px;
475
+ padding-bottom: 8px;
476
  }
477
+ .header-actions {
478
+ flex-wrap: wrap;
479
+ gap: 10px;
480
  }
481
+ .search-container {
482
+ flex: 100%;
483
+ max-width: 100%;
 
484
  }
485
+ .avatar {
486
+ width: 38px;
487
+ height: 38px;
488
+ font-size: 18px;
489
+ }
490
+ .dropdown {
491
+ top: 48px;
492
+ min-width: 140px;
493
+ }
494
+ .action-bar {
495
+ top: 70px;
496
+ flex-direction: column;
497
+ gap: 10px;
498
+ padding: 10px 15px;
499
+ }
500
+ .container {
501
+ padding: 20px 15px;
502
+ margin: 15px 0;
503
+ }
504
+ h3 {
505
+ font-size: 20px;
506
+ }
507
+ .section {
508
+ padding: 20px;
509
+ }
510
+ .progress-circle {
511
+ width: 40px;
512
+ height: 40px;
513
+ font-size: 12px;
514
+ }
515
+ .progress-circle::before {
516
+ width: 32px;
517
+ height: 32px;
518
+ }
519
+ .checklist-item, .tip-card li, .reflection-journal textarea, pre {
520
+ font-size: 14px;
521
+ }
522
+ .kpi-value {
523
+ font-size: 20px;
524
+ }
525
+ .kpi-card h4 {
526
+ font-size: 14px;
527
+ }
528
+ button {
529
+ width: 100%;
530
+ padding: 10px;
531
+ font-size: 14px;
532
+ }
533
+ .toast {
534
+ top: 10px;
535
+ right: 10px;
536
+ padding: 10px 15px;
537
+ font-size: 14px;
538
  }
539
  }
540
  </style>
541
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
542
  </head>
543
  <body>
544
+ <div class="header">
545
+ <h2 class="header-title">AI Coach Dashboard</h2>
546
+ <div class="header-actions">
547
+ <div class="search-container">
548
+ <input type="text" class="search-bar" id="search-bar" placeholder="Search checklists, tips, reflections...">
549
+ <div class="mic-icon" onclick="simulateVoiceSearch()"></div>
550
+ <div class="search-results" id="search-results"></div>
551
+ </div>
552
+ <div class="avatar" id="avatar" onclick="toggleDropdown()">?</div>
553
+ <div class="dropdown" id="dropdown">
554
+ <a href="#" onclick="viewProfile()">View Profile</a>
555
+ <a href="#" onclick="logout()">Logout</a>
 
 
 
 
 
 
556
  </div>
557
  </div>
558
+ </div>
559
 
560
+ <div class="action-bar">
561
+ <button onclick="generateCoaching()">Generate Coaching Output</button>
562
+ <button class="download-btn" onclick="downloadPDF()" id="download-btn">Download PDF Summary</button>
563
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
564
 
565
+ <div class="container">
566
+ <div class="content-grid">
567
+ <div class="section checklist-section">
568
+ <div class="checklist-header">
569
+ <h3><i>📋</i> Daily Checklist</h3>
570
+ <div class="progress-circle" id="checklist-progress"><span>0%</span></div>
 
 
 
 
 
 
 
 
 
 
 
571
  </div>
572
+ <div id="checklist-items"></div>
573
  </div>
 
574
 
575
+ <div class="section tips-section">
576
+ <h3><i>💡</i> Today's Top 3 Focus Areas</h3>
577
+ <div id="focus-tips"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  </div>
 
579
 
580
+ <div class="section full-width">
581
+ <h3><i>📊</i> Supervisor Data</h3>
582
+ <pre id="supervisor-data">Loading supervisor data...</pre>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
  </div>
 
584
 
585
+ <div class="section full-width reflection-journal">
586
+ <h3><i>📝</i> Reflection Journal</h3>
587
+ <div class="reflection-input-area">
588
+ <textarea id="reflection-input" placeholder="Log your reflections for today..."></textarea>
589
+ <button onclick="submitReflection()">Submit Reflection</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
590
  </div>
591
+ <div class="reflection-history" id="reflection-history">
592
+ <p>No reflections yet. Start logging your thoughts!</p>
 
 
 
 
 
 
 
 
593
  </div>
594
  </div>
 
595
 
596
+ <div class="section full-width kpi-section">
597
+ <h3><i>📈</i> KPI Summary Dashboard</h3>
598
+ <div class="kpi-dashboard" id="kpi-dashboard"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
599
  </div>
600
  </div>
601
  </div>
602
 
 
603
  <div id="error" class="toast error"></div>
604
  <div id="success" class="toast success"></div>
605
 
606
  <script>
607
+ let supervisorData = null;
608
+ let coachingOutput = null;
609
+ let reflectionHistory = [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
610
  let checklistProgress = 0;
611
+ let totalChecklistItems = 0;
 
612
 
 
613
  function showToast(id, message) {
614
  const toast = document.getElementById(id);
615
  toast.textContent = message;
 
619
  }, 3000);
620
  }
621
 
622
+ async function setAvatar() {
623
+ const avatar = document.getElementById('avatar');
624
+ try {
625
+ const response = await fetch('/get_supervisor_data');
626
+ const result = await response.json();
627
+ if (result.status === 'success' && result.data.supervisor_name !== 'GUEST') {
628
+ avatar.textContent = result.data.supervisor_name.charAt(0).toUpperCase();
629
+ } else {
630
+ avatar.textContent = 'G';
631
+ }
632
+ } catch (error) {
633
+ avatar.textContent = 'U';
 
 
 
634
  }
 
 
635
  }
636
 
637
+ function toggleDropdown() {
638
+ const dropdown = document.getElementById('dropdown');
639
+ dropdown.classList.toggle('active');
640
  }
641
 
642
+ function viewProfile() {
643
+ showToast('error', 'Profile view not implemented yet.');
 
 
 
644
  }
645
 
646
+ async function logout() {
 
 
 
 
 
 
 
 
 
 
 
 
647
  try {
648
+ const response = await fetch('/logout', {
649
  method: 'POST',
650
+ headers: { 'Content-Type': 'application/json' }
 
651
  });
652
  const result = await response.json();
 
653
  if (result.status === 'success') {
654
+ window.location.href = '/login';
 
 
 
 
 
 
 
 
 
 
 
655
  } else {
656
  showToast('error', result.message);
657
  }
658
  } catch (error) {
659
+ showToast('error', 'Error during logout: ' + error.message);
660
  }
661
  }
662
 
663
+ function searchData() {
664
+ const query = document.getElementById('search-bar').value.toLowerCase().trim();
665
+ const resultsDiv = document.getElementById('search-results');
666
+ resultsDiv.innerHTML = '';
667
+ resultsDiv.classList.remove('active');
668
+
669
+ if (!query) return;
670
+
671
+ const searchableContent = [];
672
+
673
+ if (coachingOutput && coachingOutput.checklist) {
674
+ coachingOutput.checklist.forEach(item => searchableContent.push(`Checklist: ${item}`));
 
 
 
 
675
  }
 
676
 
677
+ if (coachingOutput && coachingOutput.tips) {
678
+ coachingOutput.tips.forEach(tip => searchableContent.push(`Tip: ${tip}`));
679
+ }
 
 
 
 
 
680
 
681
+ if (supervisorData && supervisorData.reflection_log) {
682
+ searchableContent.push(`Reflection: ${supervisorData.reflection_log}`);
 
683
  }
684
 
685
+ if (reflectionHistory.length > 0) {
686
+ reflectionHistory.forEach(ref => searchableContent.push(`Past Reflection: ${ref.text}`));
687
+ }
688
+
689
+ const results = searchableContent.filter(item => item.toLowerCase().includes(query));
690
+
691
+ if (results.length > 0) {
692
+ results.forEach(result => {
693
+ const p = document.createElement('p');
694
+ p.textContent = result;
695
+ resultsDiv.appendChild(p);
 
 
 
 
 
696
  });
697
+ resultsDiv.classList.add('active');
698
+ } else {
699
+ const p = document.createElement('p');
700
+ p.textContent = 'No results found.';
701
+ resultsDiv.appendChild(p);
702
+ resultsDiv.classList.add('active');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
703
  }
704
  }
705
 
706
+ function simulateVoiceSearch() {
707
+ showToast('error', 'Voice search not implemented yet.');
708
  }
709
 
710
+ function updateChecklistProgress() {
711
+ const completedItems = document.querySelectorAll('.checklist-item.completed').length;
712
+ checklistProgress = totalChecklistItems > 0 ? (completedItems / totalChecklistItems) * 100 : 0;
713
+ const progressCircle = document.getElementById('checklist-progress');
714
+ progressCircle.style.setProperty('--progress', `${checklistProgress}%`);
715
+ progressCircle.querySelector('span').textContent = `${Math.round(checklistProgress)}%`;
 
 
 
 
 
 
 
 
 
 
 
 
716
  }
717
 
718
+ function markComplete(index, checkbox) {
719
+ const itemDiv = checkbox.parentElement;
720
+ if (checkbox.checked) {
721
+ itemDiv.classList.add('completed');
 
 
 
 
 
 
 
 
722
  } else {
723
+ itemDiv.classList.remove('completed');
724
  }
725
+ updateChecklistProgress();
726
  }
727
 
728
+ async function fetchSupervisorData() {
729
+ try {
730
+ const response = await fetch('/get_supervisor_data');
731
+ const result = await response.json();
732
+
733
+ if (result.status === 'success') {
734
+ supervisorData = result.data;
735
+ document.getElementById('supervisor-data').textContent = JSON.stringify(supervisorData, null, 2);
736
+
737
+ const checklistDiv = document.getElementById('checklist-items');
738
+ if (supervisorData.daily_checklist) {
739
+ const checklistItems = supervisorData.daily_checklist.split('\n').filter(item => item.trim());
740
+ totalChecklistItems = checklistItems.length;
741
+ checklistDiv.innerHTML = '';
742
+ checklistItems.forEach((item, index) => {
743
+ const itemDiv = document.createElement('div');
744
+ itemDiv.className = 'checklist-item';
745
+ itemDiv.innerHTML = `
746
+ <input type="checkbox" id="checklist-${index}" onchange="markComplete(${index}, this)">
747
+ <label for="checklist-${index}">${item}</label>
748
+ `;
749
+ checklistDiv.appendChild(itemDiv);
750
+ actic: read
751
+ checklistDiv.appendChild(itemDiv);
752
  });
753
+ updateChecklistProgress();
754
  } else {
755
+ checklistDiv.innerHTML = '<p>No checklist items available.</p>';
756
  }
 
757
 
758
+ const tipsDiv = document.getElementById('focus-tips');
759
+ if (supervisorData.suggested_tips) {
760
+ const tips = supervisorData.suggested_tips.split('\n').filter(tip => tip.trim());
761
+ tipsDiv.innerHTML = '';
762
+ const tipCard = document.createElement('div');
763
+ tipCard.className = 'tip-card';
764
+ tipCard.innerHTML = `
765
+ <h4>Today's Top 3 Focus Areas</h4>
766
+ <ul>
767
+ ${tips.map(tip => `<li>${tip}</li>`).join('')}
768
+ </ul>
769
+ `;
770
+ tipsDiv.appendChild(tipCard);
771
+ } else {
772
+ tipsDiv.innerHTML = '<p>No focus tips available.</p>';
773
+ }
774
 
775
+ if (supervisorData.reflection_log) {
776
+ reflectionHistory.push({
777
+ date: new Date().toLocaleString(),
778
+ text: supervisorData.reflection_log
 
779
  });
780
+ updateReflectionHistory();
 
 
 
 
 
 
 
781
  }
 
782
 
783
+ const downloadBtn = document.getElementById('download-btn');
784
+ if (supervisorData.download_link) {
785
+ downloadBtn.onclick = () => window.open(supervisorData.download_link, '_blank');
786
+ downloadBtn.textContent = 'Download Report';
787
+ } else {
788
+ downloadBtn.onclick = downloadPDF;
789
+ downloadBtn.textContent = 'Download PDF Summary';
790
+ }
791
+
792
+ updateKPIDashboard();
793
+ } else {
794
+ showToast('error', result.message);
795
+ document.getElementById('supervisor-data').textContent = 'Failed to load supervisor data.';
796
+ }
797
+ } catch (error) {
798
+ showToast('error', 'Error fetching supervisor data: ' + error.message);
799
+ document.getElementById('supervisor-data').textContent = 'Failed to load supervisor data.';
800
+ }
801
+ }
802
+
803
+ async function generateCoaching() {
804
+ if (!supervisorData) {
805
+ showToast('error', 'Supervisor data not loaded. Please refresh the page.');
806
+ return;
807
+ }
808
+
809
+ try {
810
+ const response = await fetch('/generate', {
811
+ method: 'POST',
812
+ headers: { 'Content-Type': 'application/json' },
813
+ body: JSON.stringify(supervisorData)
814
+ });
815
+ const result = await response.json();
816
+
817
+ if (result.status === 'success') {
818
+ coachingOutput = result.output;
819
+ showToast('success', 'Coaching output generated successfully!');
820
+ await fetchSupervisorData();
821
+ } else {
822
+ showToast('error', result.message);
823
+ }
824
+ } catch (error) {
825
+ showToast('error', 'Error generating coaching output: ' + error.message);
826
+ }
827
+ }
828
+
829
+ async function submitReflection() {
830
+ const reflectionInput = document.getElementById('reflection-input');
831
+ const reflection = reflectionInput.value.trim();
832
+
833
+ if (!reflection) {
834
+ showToast('error', 'Reflection cannot be empty.');
835
+ return;
836
+ }
837
+
838
+ try {
839
+ const response = await fetch('/submit_reflection', {
840
+ method: 'POST',
841
+ headers: { 'Content-Type': 'application/json' },
842
+ body: JSON.stringify({ reflection })
843
+ });
844
+ const result = await response.json();
845
+
846
+ if (result.status === 'success') {
847
+ showToast('success', result.message);
848
+ reflectionHistory.push({
849
+ date: new Date().toLocaleString(),
850
+ text: reflection
851
+ });
852
+ reflectionInput.value = '';
853
  updateReflectionHistory();
854
+ await fetchSupervisorData();
855
+ } else {
856
+ showToast('error', result.message);
857
+ }
858
+ } catch (error) {
859
+ showToast('error', 'Error submitting reflection: ' + error.message);
860
+ }
861
+ }
862
+
863
+ function updateReflectionHistory() {
864
+ const historyDiv = document.getElementById('reflection-history');
865
+ if (reflectionHistory.length > 0) {
866
+ historyDiv.innerHTML = reflectionHistory.map(ref => `
867
+ <div class="reflection-entry">
868
+ <span>${ref.date}</span>: ${ref.text}
869
+ </div>
870
+ `).join('');
871
+ } else {
872
+ historyDiv.innerHTML = '<p>No reflections yet. Start logging your thoughts!</p>';
873
+ }
874
+ }
875
+
876
+ function updateKPIDashboard() {
877
+ const kpiDashboard = document.getElementById('kpi-dashboard');
878
+ kpiDashboard.innerHTML = '';
879
+
880
+ if (supervisorData) {
881
+ const kpiData = [
882
+ {
883
+ title: 'Engagement Score',
884
+ value: `${supervisorData.engagement_score}%`,
885
+ progress: supervisorData.engagement_score,
886
+ trend: supervisorData.engagement_score > 80 ? 'Upward' : 'Stable'
887
+ },
888
+ {
889
+ title: 'KPI Flag',
890
+ value: supervisorData.kpi_flag ? 'Active' : 'Inactive',
891
+ class: supervisorData.kpi_flag ? 'active' : 'inactive'
892
+ }
893
+ ];
894
+
895
+ kpiData.forEach(kpi => {
896
+ const kpiCard = document.createElement('div');
897
+ kpiCard.className = 'kpi-card';
898
+ kpiCard.innerHTML = `
899
+ <h4>${kpi.title}</h4>
900
+ <div class="kpi-value ${kpi.class || ''}">${kpi.value}</div>
901
+ ${kpi.progress !== undefined ? `
902
+ <div class="progress-bar">
903
+ <div class="progress-fill" style="width: ${kpi.progress}%"></div>
904
+ </div>
905
+ <div class="kpi-trend">Trend: ${kpi.trend}</div>
906
+ ` : ''}
907
+ `;
908
+ kpiDashboard.appendChild(kpiCard);
909
+ });
910
+ } else {
911
+ kpiDashboard.innerHTML = '<p>No KPI data available.</p>';
912
+ }
913
+ }
914
+
915
+ async function downloadPDF() {
916
+ try {
917
+ const response = await fetch('/download_pdf');
918
+ if (response.ok && response.headers.get('content-type').includes('application/pdf')) {
919
+ const blob = await response.blob();
920
+ const url = window.URL.createObjectURL(blob);
921
+ const a = document.createElement('a');
922
+ a.href = url;
923
+ a.download = `supervisor_report_${supervisorData?.supervisor_name || 'report'}.pdf`;
924
+ document.body.appendChild(a);
925
+ a.click();
926
+ document.body.removeChild(a);
927
+ window.URL.revokeObjectURL(url);
928
+ showToast('success', 'PDF downloaded successfully!');
929
+ } else {
930
+ const result = await response.json();
931
+ showToast('error', result.message);
932
+ }
933
+ } catch (error) {
934
+ showToast('error', 'Error downloading PDF: ' + error.message);
935
+ }
936
+ }
937
+
938
+ document.getElementById('search-bar').addEventListener('input', searchData);
939
+ document.addEventListener('DOMContentLoaded', () => {
940
+ setAvatar();
941
+ fetchSupervisorData();
942
+ });
943
  </script>
944
  </body>
945
  </html>