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

Create templates/dashboard.html

Browse files
Files changed (1) hide show
  1. templates/templates/dashboard.html +983 -0
templates/templates/dashboard.html ADDED
@@ -0,0 +1,983 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>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
+ /* Daily Checklist Section */
200
+ .checklist-header {
201
+ display: flex;
202
+ justify-content: space-between;
203
+ align-items: center;
204
+ margin-bottom: 20px;
205
+ }
206
+ .progress-circle {
207
+ width: 50px;
208
+ height: 50px;
209
+ background: conic-gradient(#ed8936 var(--progress), #e2e8f0 0);
210
+ border-radius: 50%;
211
+ display: flex;
212
+ align-items: center;
213
+ justify-content: center;
214
+ font-size: 14px;
215
+ font-weight: 600;
216
+ color: #2d3748;
217
+ position: relative;
218
+ }
219
+ .progress-circle::before {
220
+ content: '';
221
+ position: absolute;
222
+ width: 40px;
223
+ height: 40px;
224
+ background-color: #fff;
225
+ border-radius: 50%;
226
+ }
227
+ .progress-circle span {
228
+ position: relative;
229
+ z-index: 1;
230
+ }
231
+ .checklist-item {
232
+ display: flex;
233
+ align-items: center;
234
+ margin-bottom: 15px;
235
+ font-size: 16px;
236
+ padding: 10px;
237
+ border-radius: 8px;
238
+ transition: background 0.2s ease;
239
+ }
240
+ .checklist-item:hover {
241
+ background-color: #f7fafc;
242
+ }
243
+ .checklist-item input {
244
+ width: 20px;
245
+ height: 20px;
246
+ margin-right: 15px;
247
+ accent-color: #ed8936;
248
+ cursor: pointer;
249
+ }
250
+ .checklist-item label {
251
+ flex: 1;
252
+ color: #4a5568;
253
+ cursor: pointer;
254
+ }
255
+ .checklist-item.completed label {
256
+ text-decoration: line-through;
257
+ color: #a0aec0;
258
+ }
259
+ /* Focus Tips Section */
260
+ .tip-card {
261
+ background: linear-gradient(145deg, #e6f0fa, #d1e3ff);
262
+ padding: 20px;
263
+ border-radius: 10px;
264
+ margin-bottom: 15px;
265
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
266
+ transition: transform 0.2s ease;
267
+ }
268
+ .tip-card:hover {
269
+ transform: translateY(-3px);
270
+ }
271
+ .tip-card h4 {
272
+ margin: 0 0 15px 0;
273
+ color: #1a3c7a;
274
+ font-size: 18px;
275
+ font-weight: 600;
276
+ }
277
+ .tip-card ul {
278
+ padding-left: 20px;
279
+ margin: 0;
280
+ list-style-type: disc;
281
+ }
282
+ .tip-card li {
283
+ margin-bottom: 10px;
284
+ font-size: 15px;
285
+ color: #4a5568;
286
+ }
287
+ /* Supervisor Data Section */
288
+ pre {
289
+ background-color: #f7fafc;
290
+ padding: 15px;
291
+ border: 1px solid #e2e8f0;
292
+ border-radius: 8px;
293
+ white-space: pre-wrap;
294
+ font-size: 15px;
295
+ max-height: 250px;
296
+ overflow-y: auto;
297
+ color: #4a5568;
298
+ }
299
+ /* Reflection Journal Section */
300
+ .reflection-journal {
301
+ display: flex;
302
+ flex-direction: column;
303
+ gap: 20px;
304
+ }
305
+ .reflection-input-area {
306
+ display: flex;
307
+ flex-direction: column;
308
+ gap: 15px;
309
+ }
310
+ .reflection-journal textarea {
311
+ width: 100%;
312
+ height: 120px;
313
+ padding: 15px;
314
+ border: 2px solid #e2e8f0;
315
+ border-radius: 10px;
316
+ resize: none;
317
+ font-size: 15px;
318
+ box-sizing: border-box;
319
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
320
+ background-color: #f7fafc;
321
+ }
322
+ .reflection-journal textarea:focus {
323
+ border-color: #ed8936;
324
+ outline: none;
325
+ box-shadow: 0 0 8px rgba(237, 137, 54, 0.3);
326
+ }
327
+ .reflection-history {
328
+ max-height: 200px;
329
+ overflow-y: auto;
330
+ padding: 15px;
331
+ background-color: #f7fafc;
332
+ border-radius: 10px;
333
+ border: 1px solid #e2e8f0;
334
+ }
335
+ .reflection-entry {
336
+ margin-bottom: 15px;
337
+ padding-bottom: 10px;
338
+ border-bottom: 1px solid #e2e8f0;
339
+ font-size: 14px;
340
+ color: #4a5568;
341
+ }
342
+ .reflection-entry:last-child {
343
+ border-bottom: none;
344
+ margin-bottom: 0;
345
+ }
346
+ .reflection-entry span {
347
+ font-weight: 600;
348
+ color: #2d3748;
349
+ }
350
+ /* KPI Summary Dashboard Section */
351
+ .kpi-dashboard {
352
+ display: grid;
353
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
354
+ gap: 20px;
355
+ padding: 20px;
356
+ background: linear-gradient(145deg, #fff, #f7fafc);
357
+ border-radius: 12px;
358
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
359
+ }
360
+ .kpi-card {
361
+ padding: 20px;
362
+ border-radius: 10px;
363
+ background-color: #fff;
364
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
365
+ text-align: center;
366
+ transition: transform 0.2s ease;
367
+ }
368
+ .kpi-card:hover {
369
+ transform: translateY(-3px);
370
+ }
371
+ .kpi-card h4 {
372
+ margin: 0 0 10px 0;
373
+ font-size: 16px;
374
+ color: #1a3c7a;
375
+ font-weight: 600;
376
+ }
377
+ .kpi-value {
378
+ font-size: 24px;
379
+ font-weight: 700;
380
+ color: #ed8936;
381
+ margin-bottom: 10px;
382
+ }
383
+ .progress-bar {
384
+ width: 100%;
385
+ height: 8px;
386
+ background-color: #e2e8f0;
387
+ border-radius: 4px;
388
+ overflow: hidden;
389
+ }
390
+ .progress-fill {
391
+ height: 100%;
392
+ background: linear-gradient(to right, #ed8936, #f6ad55);
393
+ transition: width 0.5s ease;
394
+ }
395
+ .kpi-trend {
396
+ font-size: 13px;
397
+ color: #718096;
398
+ margin-top: 8px;
399
+ }
400
+ .kpi-flag {
401
+ display: inline-block;
402
+ padding: 5px 10px;
403
+ border-radius: 5px;
404
+ font-size: 12px;
405
+ font-weight: 600;
406
+ margin-top: 8px;
407
+ }
408
+ .kpi-flag.active {
409
+ background-color: #48bb78;
410
+ color: #fff;
411
+ }
412
+ .kpi-flag.inactive {
413
+ background-color: #f56565;
414
+ color: #fff;
415
+ }
416
+ /* Buttons */
417
+ button {
418
+ padding: 12px 25px;
419
+ background: linear-gradient(to right, #f6ad55, #ed8936);
420
+ color: #fff;
421
+ border: none;
422
+ border-radius: 8px;
423
+ cursor: pointer;
424
+ font-size: 15px;
425
+ font-weight: 600;
426
+ transition: transform 0.1s ease, background 0.3s ease;
427
+ }
428
+ button:hover {
429
+ background: linear-gradient(to right, #ed8936, #dd6b20);
430
+ transform: scale(1.02);
431
+ }
432
+ .download-btn {
433
+ background: linear-gradient(to right, #38a169, #48bb78);
434
+ }
435
+ .download-btn:hover {
436
+ background: linear-gradient(to right, #2f855a, #38a169);
437
+ }
438
+ /* Toast Notifications */
439
+ .toast {
440
+ position: fixed;
441
+ top: 20px;
442
+ right: 20px;
443
+ padding: 15px 25px;
444
+ border-radius: 8px;
445
+ z-index: 102;
446
+ display: none;
447
+ font-size: 15px;
448
+ font-weight: 500;
449
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
450
+ }
451
+ .toast.error {
452
+ background-color: #f56565;
453
+ color: #fff;
454
+ }
455
+ .toast.success {
456
+ background-color: #48bb78;
457
+ color: #fff;
458
+ }
459
+ .toast.visible {
460
+ display: block;
461
+ }
462
+ /* Responsive Design */
463
+ @media (max-width: 900px) {
464
+ .content-grid {
465
+ grid-template-columns: 1fr;
466
+ }
467
+ .section.full-width {
468
+ grid-column: span 1;
469
+ }
470
+ .kpi-dashboard {
471
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
472
+ }
473
+ }
474
+ @media (max-width: 700px) {
475
+ body {
476
+ padding: 0;
477
+ }
478
+ .header {
479
+ padding: 10px 15px;
480
+ }
481
+ .header-title {
482
+ font-size: 22px;
483
+ padding-bottom: 8px;
484
+ }
485
+ .header-actions {
486
+ flex-wrap: wrap;
487
+ gap: 10px;
488
+ }
489
+ .search-container {
490
+ flex: 100%;
491
+ max-width: 100%;
492
+ }
493
+ .avatar {
494
+ width: 38px;
495
+ height: 38px;
496
+ font-size: 18px;
497
+ }
498
+ .dropdown {
499
+ top: 48px;
500
+ min-width: 140px;
501
+ }
502
+ .action-bar {
503
+ top: 70px;
504
+ flex-direction: column;
505
+ gap: 10px;
506
+ padding: 10px 15px;
507
+ }
508
+ .container {
509
+ padding: 20px 15px;
510
+ margin: 15px 0;
511
+ }
512
+ h3 {
513
+ font-size: 20px;
514
+ }
515
+ .section {
516
+ padding: 20px;
517
+ }
518
+ .progress-circle {
519
+ width: 40px;
520
+ height: 40px;
521
+ font-size: 12px;
522
+ }
523
+ .progress-circle::before {
524
+ width: 32px;
525
+ height: 32px;
526
+ }
527
+ .checklist-item, .tip-card li, .reflection-journal textarea, pre {
528
+ font-size: 14px;
529
+ }
530
+ .kpi-value {
531
+ font-size: 20px;
532
+ }
533
+ .kpi-card h4 {
534
+ font-size: 14px;
535
+ }
536
+ button {
537
+ width: 100%;
538
+ padding: 10px;
539
+ font-size: 14px;
540
+ }
541
+ .toast {
542
+ top: 10px;
543
+ right: 10px;
544
+ padding: 10px 15px;
545
+ font-size: 14px;
546
+ }
547
+ }
548
+ </style>
549
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
550
+ </head>
551
+ <body>
552
+ <div class="header">
553
+ <h2 class="header-title">AI Coach Dashboard</h2>
554
+ <div class="header-actions">
555
+ <div class="search-container">
556
+ <input type="text" class="search-bar" id="search-bar" placeholder="Search checklists, tips, reflections...">
557
+ <div class="mic-icon" onclick="simulateVoiceSearch()"></div>
558
+ <div class="search-results" id="search-results"></div>
559
+ </div>
560
+ <div class="avatar" id="avatar" onclick="toggleDropdown()">?</div>
561
+ <div class="dropdown" id="dropdown">
562
+ <a href="#" onclick="viewProfile()">View Profile</a>
563
+ <a href="#" onclick="logout()">Logout</a>
564
+ </div>
565
+ </div>
566
+ </div>
567
+
568
+ <div class="action-bar">
569
+ <button onclick="generateCoaching()">Generate Coaching Output</button>
570
+ <button class="download-btn" onclick="downloadPDF()" id="download-btn">Download PDF Summary</button>
571
+ </div>
572
+
573
+ <div class="container">
574
+ <div class="content-grid">
575
+ <!-- Daily Checklist Section -->
576
+ <div class="section checklist-section">
577
+ <div class="checklist-header">
578
+ <h3><i>📋</i> Daily Checklist</h3>
579
+ <div class="progress-circle" id="checklist-progress"><span>0%</span></div>
580
+ </div>
581
+ <div id="checklist-items"></div>
582
+ </div>
583
+
584
+ <!-- Focus Tips Section -->
585
+ <div class="section tips-section">
586
+ <h3><i>💡</i> Today's Top 3 Focus Areas</h3>
587
+ <div id="focus-tips"></div>
588
+ </div>
589
+
590
+ <!-- Supervisor Data Section -->
591
+ <div class="section full-width">
592
+ <h3><i>📊</i> Supervisor Data</h3>
593
+ <pre id="supervisor-data">Loading supervisor data...</pre>
594
+ </div>
595
+
596
+ <!-- Reflection Journal Section -->
597
+ <div class="section full-width reflection-journal">
598
+ <h3><i>📝</i> Reflection Journal</h3>
599
+ <div class="reflection-input-area">
600
+ <textarea id="reflection-input" placeholder="Log your reflections for today..."></textarea>
601
+ <button onclick="submitReflection()">Submit Reflection</button>
602
+ </div>
603
+ <div class="reflection-history" id="reflection-history">
604
+ <p>No reflections yet. Start logging your thoughts!</p>
605
+ </div>
606
+ </div>
607
+
608
+ <!-- KPI Summary Dashboard Section -->
609
+ <div class="section full-width kpi-section">
610
+ <h3><i>📈</i> KPI Summary Dashboard</h3>
611
+ <div class="kpi-dashboard" id="kpi-dashboard">
612
+ <!-- KPIs will be populated dynamically -->
613
+ </div>
614
+ </div>
615
+ </div>
616
+ </div>
617
+
618
+ <!-- Toast Notifications -->
619
+ <div id="error" class="toast error"></div>
620
+ <div id="success" class="toast success"></div>
621
+
622
+ <script>
623
+ let supervisorData = null;
624
+ let coachingOutput = null;
625
+ let reflectionHistory = [];
626
+ let checklistProgress = 0;
627
+ let totalChecklistItems = 0;
628
+ // Toast Notification Function
629
+ function showToast(id, message) {
630
+ const toast = document.getElementById(id);
631
+ toast.textContent = message;
632
+ toast.classList.add('visible');
633
+ setTimeout(() => {
634
+ toast.classList.remove('visible');
635
+ }, 3000);
636
+ }
637
+ // Set Avatar Initial
638
+ async function setAvatar() {
639
+ const avatar = document.getElementById('avatar');
640
+ try {
641
+ const response = await fetch('/get_supervisor_data');
642
+ const result = await response.json();
643
+ if (result.status === 'success' && result.data.supervisor_id !== 'GUEST') {
644
+ const username = result.data.supervisor_id.split('_')[1] || 'User';
645
+ avatar.textContent = username.charAt(0).toUpperCase();
646
+ } else {
647
+ avatar.textContent = 'G';
648
+ }
649
+ } catch (error) {
650
+ avatar.textContent = 'U';
651
+ }
652
+ }
653
+ // Dropdown Toggle
654
+ function toggleDropdown() {
655
+ const dropdown = document.getElementById('dropdown');
656
+ dropdown.classList.toggle('active');
657
+ }
658
+ function viewProfile() {
659
+ showToast('error', 'Profile view not implemented yet.');
660
+ }
661
+ async function logout() {
662
+ try {
663
+ const response = await fetch('/logout', {
664
+ method: 'POST',
665
+ headers: { 'Content-Type': 'application/json' }
666
+ });
667
+ const result = await response.json();
668
+ if (result.status === 'success') {
669
+ window.location.href = '/login';
670
+ } else {
671
+ showToast('error', result.message);
672
+ }
673
+ } catch (error) {
674
+ showToast('error', 'Error during logout: ' + error.message);
675
+ }
676
+ }
677
+ // Search Functionality
678
+ function searchData() {
679
+ const query = document.getElementById('search-bar').value.toLowerCase().trim();
680
+ const resultsDiv = document.getElementById('search-results');
681
+ resultsDiv.innerHTML = '';
682
+ resultsDiv.classList.remove('active');
683
+ if (!query) return;
684
+ const searchableContent = [];
685
+ if (coachingOutput && coachingOutput.checklist) {
686
+ coachingOutput.checklist.forEach(item => searchableContent.push(`Checklist: ${item}`));
687
+ }
688
+ if (coachingOutput && coachingOutput.tips) {
689
+ coachingOutput.tips.forEach(tip => searchableContent.push(`Tip: ${tip}`));
690
+ }
691
+ if (supervisorData && supervisorData.reflection_log) {
692
+ searchableContent.push(`Reflection: ${supervisorData.reflection_log}`);
693
+ }
694
+ if (reflectionHistory.length > 0) {
695
+ reflectionHistory.forEach(ref => searchableContent.push(`Past Reflection: ${ref.text}`));
696
+ }
697
+ const results = searchableContent.filter(item => item.toLowerCase().includes(query));
698
+ if (results.length > 0) {
699
+ results.forEach(result => {
700
+ const p = document.createElement('p');
701
+ p.textContent = result;
702
+ resultsDiv.appendChild(p);
703
+ });
704
+ resultsDiv.classList.add('active');
705
+ } else {
706
+ const p = document.createElement('p');
707
+ p.textContent = 'No results found.';
708
+ resultsDiv.appendChild(p);
709
+ resultsDiv.classList.add('active');
710
+ }
711
+ }
712
+ function simulateVoiceSearch() {
713
+ showToast('error', 'Voice search not implemented yet.');
714
+ }
715
+ // Update Checklist Progress
716
+ function updateChecklistProgress() {
717
+ const completedItems = document.querySelectorAll('.checklist-item.completed').length;
718
+ checklistProgress = totalChecklistItems > 0 ? (completedItems / totalChecklistItems) * 100 : 0;
719
+ const progressCircle = document.getElementById('checklist-progress');
720
+ progressCircle.style.setProperty('--progress', `${checklistProgress}%`);
721
+ progressCircle.querySelector('span').textContent = `${Math.round(checklistProgress)}%`;
722
+ }
723
+ async function fetchSupervisorData() {
724
+ try {
725
+ const response = await fetch('/get_supervisor_data');
726
+ const result = await response.json();
727
+ if (result.status === 'success') {
728
+ supervisorData = result.data;
729
+ document.getElementById('supervisor-data').textContent = JSON.stringify(supervisorData, null, 2);
730
+ // Populate Daily Checklist from Salesforce
731
+ const checklistDiv = document.getElementById('checklist-items');
732
+ if (supervisorData.daily_checklist) {
733
+ const checklistItems = supervisorData.daily_checklist.split('\n').filter(item => item.trim());
734
+ totalChecklistItems = checklistItems.length;
735
+ checklistDiv.innerHTML = '';
736
+ checklistItems.forEach((item, index) => {
737
+ const itemDiv = document.createElement('div');
738
+ itemDiv.className = 'checklist-item';
739
+ itemDiv.innerHTML = `
740
+ <input type="checkbox" id="checklist-${index}" onchange="markComplete(${index}, this)">
741
+ <label for="checklist-${index}">${item}</label>
742
+ `;
743
+ checklistDiv.appendChild(itemDiv);
744
+ });
745
+ updateChecklistProgress();
746
+ } else {
747
+ checklistDiv.innerHTML = '<p>No checklist items available.</p>';
748
+ }
749
+ // Populate Focus Tips from Salesforce
750
+ const tipsDiv = document.getElementById('focus-tips');
751
+ if (supervisorData.suggested_tips) {
752
+ const tips = supervisorData.suggested_tips.split('\n').filter(tip => tip.trim());
753
+ tipsDiv.innerHTML = '';
754
+ const tipCard = document.createElement('div');
755
+ tipCard.className = 'tip-card';
756
+ tipCard.innerHTML = `
757
+ <h4>Today's Top 3 Focus Areas</h4>
758
+ <ul>
759
+ ${tips.map(tip => `<li>${tip}</li>`).join('')}
760
+ </ul>
761
+ `;
762
+ tipsDiv.appendChild(tipCard);
763
+ } else {
764
+ tipsDiv.innerHTML = '<p>No focus tips available.</p>';
765
+ }
766
+ // Populate Reflection History
767
+ if (supervisorData.reflection_log) {
768
+ reflectionHistory.push({
769
+ date: new Date().toLocaleString(),
770
+ text: supervisorData.reflection_log
771
+ });
772
+ updateReflectionHistory();
773
+ }
774
+ // Update Download Link
775
+ const downloadBtn = document.getElementById('download-btn');
776
+ if (supervisorData.download_link) {
777
+ downloadBtn.onclick = () => window.open(supervisorData.download_link, '_blank');
778
+ downloadBtn.textContent = 'Download Report';
779
+ } else {
780
+ downloadBtn.onclick = downloadPDF;
781
+ downloadBtn.textContent = 'Download PDF Summary';
782
+ }
783
+ updateKPIDashboard();
784
+ } else {
785
+ showToast('error', result.message);
786
+ document.getElementById('supervisor-data').textContent = 'Failed to load supervisor data.';
787
+ }
788
+ } catch (error) {
789
+ showToast('error', 'Error fetching supervisor data: ' + error.message);
790
+ document.getElementById('supervisor-data').textContent = 'Failed to load supervisor data.';
791
+ }
792
+ }
793
+ async function generateCoaching() {
794
+ if (!supervisorData) {
795
+ showToast('error', 'Supervisor data not loaded. Please refresh the page.');
796
+ return;
797
+ }
798
+ try {
799
+ const response = await fetch('/generate', {
800
+ method: 'POST',
801
+ headers: { 'Content-Type': 'application/json' },
802
+ body: JSON.stringify(supervisorData)
803
+ });
804
+ const result = await response.json();
805
+ if (result.status === 'success') {
806
+ coachingOutput = result.output;
807
+ showToast('success', 'Coaching output generated successfully!');
808
+ // Populate Daily Checklist
809
+ const checklistDiv = document.getElementById('checklist-items');
810
+ checklistDiv.innerHTML = '';
811
+ if (coachingOutput.checklist && coachingOutput.checklist.length > 0) {
812
+ totalChecklistItems = coachingOutput.checklist.length;
813
+ coachingOutput.checklist.forEach((item, index) => {
814
+ const itemDiv = document.createElement('div');
815
+ itemDiv.className = 'checklist-item';
816
+ itemDiv.innerHTML = `
817
+ <input type="checkbox" id="checklist-${index}" onchange="markComplete(${index}, this)">
818
+ <label for="checklist-${index}">${item}</label>
819
+ `;
820
+ checklistDiv.appendChild(itemDiv);
821
+ });
822
+ updateChecklistProgress();
823
+ } else {
824
+ checklistDiv.innerHTML = '<p>No checklist items available.</p>';
825
+ }
826
+ // Populate Focus Tips
827
+ const tipsDiv = document.getElementById('focus-tips');
828
+ tipsDiv.innerHTML = '';
829
+ if (coachingOutput.tips && coachingOutput.tips.length > 0) {
830
+ const tipCard = document.createElement('div');
831
+ tipCard.className = 'tip-card';
832
+ tipCard.innerHTML = `
833
+ <h4>Today's Top 3 Focus Areas</h4>
834
+ <ul>
835
+ ${coachingOutput.tips.map(tip => `<li>${tip}</li>`).join('')}
836
+ </ul>
837
+ `;
838
+ tipsDiv.appendChild(tipCard);
839
+ } else {
840
+ tipsDiv.innerHTML = '<p>No focus tips available.</p>';
841
+ }
842
+ updateKPIDashboard();
843
+ } else {
844
+ showToast('error', result.message);
845
+ document.getElementById('checklist-items').innerHTML = '<p>Failed to generate checklist.</p>';
846
+ document.getElementById('focus-tips').innerHTML = '<p>Failed to generate focus tips.</p>';
847
+ }
848
+ } catch (error) {
849
+ showToast('error', 'Error generating coaching output: ' + error.message);
850
+ document.getElementById('checklist-items').innerHTML = '<p>Failed to generate checklist.</p>';
851
+ document.getElementById('focus-tips').innerHTML = '<p>Failed to generate focus tips.</p>';
852
+ }
853
+ }
854
+ function markComplete(index, checkbox) {
855
+ const itemDiv = checkbox.parentElement;
856
+ if (checkbox.checked) {
857
+ itemDiv.classList.add('completed');
858
+ } else {
859
+ itemDiv.classList.remove('completed');
860
+ }
861
+ updateChecklistProgress();
862
+ showToast('success', `Checklist item ${index + 1} marked as ${checkbox.checked ? 'complete' : 'incomplete'} (simulated).`);
863
+ }
864
+ function updateReflectionHistory() {
865
+ const historyDiv = document.getElementById('reflection-history');
866
+ historyDiv.innerHTML = '';
867
+ if (reflectionHistory.length > 0) {
868
+ reflectionHistory.forEach(ref => {
869
+ const entryDiv = document.createElement('div');
870
+ entryDiv.className = 'reflection-entry';
871
+ entryDiv.innerHTML = `<span>${ref.date}:</span> ${ref.text}`;
872
+ historyDiv.appendChild(entryDiv);
873
+ });
874
+ } else {
875
+ historyDiv.innerHTML = '<p>No reflections yet. Start logging your thoughts!</p>';
876
+ }
877
+ }
878
+ async function submitReflection() {
879
+ const reflectionInput = document.getElementById('reflection-input').value.trim();
880
+ if (!reflectionInput) {
881
+ showToast('error', 'Please enter a reflection before submitting.');
882
+ return;
883
+ }
884
+ if (!supervisorData) {
885
+ showToast('error', 'Supervisor data not loaded. Please refresh the page.');
886
+ return;
887
+ }
888
+ try {
889
+ const response = await fetch('/submit_reflection', {
890
+ method: 'POST',
891
+ headers: { 'Content-Type': 'application/json' },
892
+ body: JSON.stringify({ reflection: reflectionInput })
893
+ });
894
+ const result = await response.json();
895
+ if (result.status === 'success') {
896
+ supervisorData.reflection_log = reflectionInput;
897
+ document.getElementById('supervisor-data').textContent = JSON.stringify(supervisorData, null, 2);
898
+ reflectionHistory.push({
899
+ date: new Date().toLocaleString(),
900
+ text: reflectionInput
901
+ });
902
+ updateReflectionHistory();
903
+ document.getElementById('reflection-input').value = '';
904
+ showToast('success', result.message);
905
+ generateCoaching();
906
+ } else {
907
+ showToast('error', result.message);
908
+ }
909
+ } catch (error) {
910
+ showToast('error', 'Error submitting reflection: ' + error.message);
911
+ }
912
+ }
913
+ function updateKPIDashboard() {
914
+ const kpiDashboard = document.getElementById('kpi-dashboard');
915
+ kpiDashboard.innerHTML = '';
916
+ // KPI 1: Engagement Score
917
+ const engagementScore = supervisorData && supervisorData.engagement_score ? supervisorData.engagement_score : 85;
918
+ const engagementCard = document.createElement('div');
919
+ engagementCard.className = 'kpi-card';
920
+ engagementCard.innerHTML = `
921
+ <h4>Engagement Score</h4>
922
+ <div class="kpi-value">${engagementScore}%</div>
923
+ <div class="progress-bar">
924
+ <div class="progress-fill" style="width: ${engagementScore}%"></div>
925
+ </div>
926
+ <p class="kpi-trend">Target: 90%</p>
927
+ `;
928
+ kpiDashboard.appendChild(engagementCard);
929
+ // KPI 2: Task Completion Rate
930
+ const taskCompletionRate = checklistProgress;
931
+ const taskCard = document.createElement('div');
932
+ taskCard.className = 'kpi-card';
933
+ taskCard.innerHTML = `
934
+ <h4>Task Completion Rate</h4>
935
+ <div class="kpi-value">${Math.round(taskCompletionRate)}%</div>
936
+ <div class="progress-bar">
937
+ <div class="progress-fill" style="width: ${taskCompletionRate}%"></div>
938
+ </div>
939
+ <p class="kpi-trend">Based on Daily Checklist</p>
940
+ `;
941
+ kpiDashboard.appendChild(taskCard);
942
+ // KPI 3: Reflection Frequency
943
+ const reflectionFrequency = reflectionHistory.length;
944
+ const reflectionCard = document.createElement('div');
945
+ reflectionCard.className = 'kpi-card';
946
+ reflectionCard.innerHTML = `
947
+ <h4>Reflection Frequency</h4>
948
+ <div class="kpi-value">${reflectionFrequency}</div>
949
+ <div class="progress-bar">
950
+ <div class="progress-fill" style="width: ${(reflectionFrequency / 5) * 100}%"></div>
951
+ </div>
952
+ <p class="kpi-trend">Goal: 5 per week</p>
953
+ `;
954
+ kpiDashboard.appendChild(reflectionCard);
955
+ // KPI 4: KPI Flag
956
+ const kpiFlag = supervisorData && supervisorData.kpi_flag !== undefined ? supervisorData.kpi_flag : false;
957
+ const flagCard = document.createElement('div');
958
+ flagCard.className = 'kpi-card';
959
+ flagCard.innerHTML = `
960
+ <h4>KPI Flag Status</h4>
961
+ <div class="kpi-value">
962
+ <span class="kpi-flag ${kpiFlag ? 'active' : 'inactive'}">${kpiFlag ? 'Active' : 'Inactive'}</span>
963
+ </div>
964
+ <p class="kpi-trend">Performance Indicator</p>
965
+ `;
966
+ kpiDashboard.appendChild(flagCard);
967
+ }
968
+ function downloadPDF() {
969
+ if (!supervisorData || !supervisorData.download_link) {
970
+ showToast('error', 'No download link available.');
971
+ return;
972
+ }
973
+ window.open(supervisorData.download_link, '_blank');
974
+ }
975
+ // Event Listeners
976
+ document.getElementById('search-bar').addEventListener('input', searchData);
977
+ window.onload = () => {
978
+ fetchSupervisorData();
979
+ setAvatar();
980
+ };
981
+ </script>
982
+ </body>
983
+ </html>