geethareddy commited on
Commit
7a8b34d
·
verified ·
1 Parent(s): f3e2bd0

templates/templates/dashboard.html

Browse files
Files changed (1) hide show
  1. templates/templates/dashboard.html +0 -983
templates/templates/dashboard.html DELETED
@@ -1,983 +0,0 @@
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>