geethareddy commited on
Commit
6f978da
·
verified ·
1 Parent(s): bda7b1a

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +961 -787
templates/index.html CHANGED
@@ -3,614 +3,895 @@
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>
@@ -620,11 +901,45 @@
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
 
629
  // Toast Notification Function
630
  function showToast(id, message) {
@@ -636,391 +951,250 @@
636
  }, 3000);
637
  }
638
 
639
- // Set Avatar Initial
640
- async function setAvatar() {
641
- const avatar = document.getElementById('avatar');
642
- try {
643
- const response = await fetch('/get_supervisor_data');
644
- const result = await response.json();
645
- if (result.status === 'success' && result.data.supervisor_id !== 'GUEST') {
646
- const username = result.data.supervisor_id.split('_')[1] || 'User';
647
- avatar.textContent = username.charAt(0).toUpperCase();
648
- } else {
649
- avatar.textContent = 'G';
650
- }
651
- } catch (error) {
652
- avatar.textContent = 'U';
 
653
  }
 
 
654
  }
655
 
656
- // Dropdown Toggle
657
- function toggleDropdown() {
658
- const dropdown = document.getElementById('dropdown');
659
- dropdown.classList.toggle('active');
660
  }
661
 
662
- function viewProfile() {
663
- showToast('error', 'Profile view not implemented yet.');
 
 
 
664
  }
665
 
666
- async function logout() {
 
 
 
 
 
 
 
 
 
 
 
 
667
  try {
668
- const response = await fetch('/logout', {
669
  method: 'POST',
670
- headers: { 'Content-Type': 'application/json' }
 
671
  });
672
  const result = await response.json();
673
 
674
  if (result.status === 'success') {
675
- window.location.href = '/login';
 
 
 
 
 
 
 
 
 
 
 
676
  } else {
677
  showToast('error', result.message);
678
  }
679
  } catch (error) {
680
- showToast('error', 'Error during logout: ' + error.message);
681
  }
682
  }
683
 
684
- // Search Functionality
685
- function searchData() {
686
- const query = document.getElementById('search-bar').value.toLowerCase().trim();
687
- const resultsDiv = document.getElementById('search-results');
688
- resultsDiv.innerHTML = '';
689
- resultsDiv.classList.remove('active');
690
-
691
- if (!query) return;
692
-
693
- const searchableContent = [];
694
-
695
- if (coachingOutput && coachingOutput.checklist) {
696
- coachingOutput.checklist.forEach(item => searchableContent.push(`Checklist: ${item}`));
697
- }
698
-
699
- if (coachingOutput && coachingOutput.tips) {
700
- coachingOutput.tips.forEach(tip => searchableContent.push(`Tip: ${tip}`));
701
- }
702
-
703
- if (supervisorData && supervisorData.reflection_log) {
704
- searchableContent.push(`Reflection: ${supervisorData.reflection_log}`);
705
- }
706
-
707
  if (reflectionHistory.length > 0) {
708
- reflectionHistory.forEach(ref => searchableContent.push(`Past Reflection: ${ref.text}`));
709
- }
710
-
711
- const results = searchableContent.filter(item => item.toLowerCase().includes(query));
712
-
713
- if (results.length > 0) {
714
- results.forEach(result => {
715
- const p = document.createElement('p');
716
- p.textContent = result;
717
- resultsDiv.appendChild(p);
718
  });
719
- resultsDiv.classList.add('active');
720
  } else {
721
- const p = document.createElement('p');
722
- p.textContent = 'No results found.';
723
- resultsDiv.appendChild(p);
724
- resultsDiv.classList.add('active');
725
  }
726
  }
727
 
728
- function simulateVoiceSearch() {
729
- showToast('error', 'Voice search not implemented yet.');
730
- }
 
 
 
 
 
731
 
732
- // Update Checklist Progress
733
- function updateChecklistProgress() {
734
- const completedItems = document.querySelectorAll('.checklist-item.completed').length;
735
- checklistProgress = totalChecklistItems > 0 ? (completedItems / totalChecklistItems) * 100 : 0;
736
- const progressCircle = document.getElementById('checklist-progress');
737
- progressCircle.style.setProperty('--progress', `${checklistProgress}%`);
738
- progressCircle.querySelector('span').textContent = `${Math.round(checklistProgress)}%`;
739
- }
740
 
741
- async function fetchSupervisorData() {
742
  try {
743
- const response = await fetch('/get_supervisor_data');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
744
  const result = await response.json();
745
-
746
  if (result.status === 'success') {
747
- supervisorData = result.data;
748
- document.getElementById('supervisor-data').textContent = JSON.stringify(supervisorData, null, 2);
749
-
750
- // Populate Daily Checklist from Salesforce
751
- const checklistDiv = document.getElementById('checklist-items');
752
- if (supervisorData.daily_checklist) {
753
- const checklistItems = supervisorData.daily_checklist.split('\n').filter(item => item.trim());
754
- totalChecklistItems = checklistItems.length;
755
- checklistDiv.innerHTML = '';
756
- checklistItems.forEach((item, index) => {
757
- const itemDiv = document.createElement('div');
758
- itemDiv.className = 'checklist-item';
759
- itemDiv.innerHTML = `
760
- <input type="checkbox" id="checklist-${index}" onchange="markComplete(${index}, this)">
761
- <label for="checklist-${index}">${item}</label>
762
- `;
763
- checklistDiv.appendChild(itemDiv);
764
- });
765
- updateChecklistProgress();
766
- } else {
767
- checklistDiv.innerHTML = '<p>No checklist items available.</p>';
768
- }
769
-
770
- // Populate Focus Tips from Salesforce
771
- const tipsDiv = document.getElementById('focus-tips');
772
- if (supervisorData.suggested_tips) {
773
- const tips = supervisorData.suggested_tips.split('\n').filter(tip => tip.trim());
774
- tipsDiv.innerHTML = '';
775
- const tipCard = document.createElement('div');
776
- tipCard.className = 'tip-card';
777
- tipCard.innerHTML = `
778
- <h4>Today's Top 3 Focus Areas</h4>
779
- <ul>
780
- ${tips.map(tip => `<li>${tip}</li>`).join('')}
781
- </ul>
782
- `;
783
- tipsDiv.appendChild(tipCard);
784
- } else {
785
- tipsDiv.innerHTML = '<p>No focus tips available.</p>';
786
- }
787
-
788
- // Populate Reflection History
789
- if (supervisorData.reflection_log) {
790
- reflectionHistory.push({
791
- date: new Date().toLocaleString(),
792
- text: supervisorData.reflection_log
793
- });
794
- updateReflectionHistory();
795
- }
796
-
797
- // Update Download Link
798
- const downloadBtn = document.getElementById('download-btn');
799
- if (supervisorData.download_link) {
800
- downloadBtn.onclick = () => window.open(supervisorData.download_link, '_blank');
801
- downloadBtn.textContent = 'Download Report';
802
- } else {
803
- downloadBtn.onclick = downloadPDF;
804
- downloadBtn.textContent = 'Download PDF Summary';
805
- }
806
-
807
- updateKPIDashboard();
808
  } else {
809
- showToast('error', result.message);
810
- document.getElementById('supervisor-data').textContent = 'Failed to load supervisor data.';
811
  }
812
  } catch (error) {
813
- showToast('error', 'Error fetching supervisor data: ' + error.message);
814
- document.getElementById('supervisor-data').textContent = 'Failed to load supervisor data.';
815
  }
816
  }
817
 
818
- async function generateCoaching() {
819
- if (!supervisorData) {
820
- showToast('error', 'Supervisor data not loaded. Please refresh the page.');
821
- return;
822
- }
823
 
 
 
824
  try {
825
- const response = await fetch('/generate', {
826
  method: 'POST',
827
- headers: { 'Content-Type': 'application/json' },
828
- body: JSON.stringify(supervisorData)
829
  });
830
  const result = await response.json();
831
-
832
  if (result.status === 'success') {
833
- coachingOutput = result.output;
834
- showToast('success', 'Coaching output generated successfully!');
835
-
836
- // Populate Daily Checklist
837
- const checklistDiv = document.getElementById('checklist-items');
838
- checklistDiv.innerHTML = '';
839
- if (coachingOutput.checklist && coachingOutput.checklist.length > 0) {
840
- totalChecklistItems = coachingOutput.checklist.length;
841
- coachingOutput.checklist.forEach((item, index) => {
842
- const itemDiv = document.createElement('div');
843
- itemDiv.className = 'checklist-item';
844
- itemDiv.innerHTML = `
845
- <input type="checkbox" id="checklist-${index}" onchange="markComplete(${index}, this)">
846
- <label for="checklist-${index}">${item}</label>
847
- `;
848
- checklistDiv.appendChild(itemDiv);
849
- });
850
- updateChecklistProgress();
851
- } else {
852
- checklistDiv.innerHTML = '<p>No checklist items available.</p>';
853
- }
854
-
855
- // Populate Focus Tips
856
- const tipsDiv = document.getElementById('focus-tips');
857
- tipsDiv.innerHTML = '';
858
- if (coachingOutput.tips && coachingOutput.tips.length > 0) {
859
- const tipCard = document.createElement('div');
860
- tipCard.className = 'tip-card';
861
- tipCard.innerHTML = `
862
- <h4>Today's Top 3 Focus Areas</h4>
863
- <ul>
864
- ${coachingOutput.tips.map(tip => `<li>${tip}</li>`).join('')}
865
- </ul>
866
- `;
867
- tipsDiv.appendChild(tipCard);
868
- } else {
869
- tipsDiv.innerHTML = '<p>No focus tips available.</p>';
870
- }
871
-
872
- updateKPIDashboard();
873
  } else {
874
  showToast('error', result.message);
875
- document.getElementById('checklist-items').innerHTML = '<p>Failed to generate checklist.</p>';
876
- document.getElementById('focus-tips').innerHTML = '<p>Failed to generate focus tips.</p>';
877
  }
878
  } catch (error) {
879
- showToast('error', 'Error generating coaching output: ' + error.message);
880
- document.getElementById('checklist-items').innerHTML = '<p>Failed to generate checklist.</p>';
881
- document.getElementById('focus-tips').innerHTML = '<p>Failed to generate focus tips.</p>';
882
  }
883
  }
884
 
885
- function markComplete(index, checkbox) {
886
- const itemDiv = checkbox.parentElement;
887
- if (checkbox.checked) {
888
- itemDiv.classList.add('completed');
 
 
 
 
 
 
 
 
889
  } else {
890
- itemDiv.classList.remove('completed');
891
  }
892
- updateChecklistProgress();
893
- showToast('success', `Checklist item ${index + 1} marked as ${checkbox.checked ? 'complete' : 'incomplete'} (simulated).`);
894
  }
895
 
896
- function updateReflectionHistory() {
897
- const historyDiv = document.getElementById('reflection-history');
898
- historyDiv.innerHTML = '';
899
- if (reflectionHistory.length > 0) {
900
- reflectionHistory.forEach(ref => {
901
- const entryDiv = document.createElement('div');
902
- entryDiv.className = 'reflection-entry';
903
- entryDiv.innerHTML = `<span>${ref.date}:</span> ${ref.text}`;
904
- historyDiv.appendChild(entryDiv);
 
 
 
 
 
 
 
 
 
 
905
  });
906
  } else {
907
- historyDiv.innerHTML = '<p>No reflections yet. Start logging your thoughts!</p>';
908
  }
909
  }
910
 
911
- async function submitReflection() {
912
- const reflectionInput = document.getElementById('reflection-input').value.trim();
913
-
914
- if (!reflectionInput) {
915
- showToast('error', 'Please enter a reflection before submitting.');
916
- return;
917
- }
918
-
919
- if (!supervisorData) {
920
- showToast('error', 'Supervisor data not loaded. Please refresh the page.');
921
- return;
922
- }
923
 
924
  try {
925
- const response = await fetch('/submit_reflection', {
926
  method: 'POST',
927
  headers: { 'Content-Type': 'application/json' },
928
- body: JSON.stringify({ reflection: reflectionInput })
929
  });
930
  const result = await response.json();
931
-
932
  if (result.status === 'success') {
933
- supervisorData.reflection_log = reflectionInput;
934
- document.getElementById('supervisor-data').textContent = JSON.stringify(supervisorData, null, 2);
935
- reflectionHistory.push({
936
- date: new Date().toLocaleString(),
937
- text: reflectionInput
938
- });
939
- updateReflectionHistory();
940
- document.getElementById('reflection-input').value = '';
941
- showToast('success', result.message);
942
- generateCoaching();
943
  } else {
944
  showToast('error', result.message);
945
  }
946
  } catch (error) {
947
- showToast('error', 'Error submitting reflection: ' + error.message);
948
- }
949
- }
950
-
951
- function updateKPIDashboard() {
952
- const kpiDashboard = document.getElementById('kpi-dashboard');
953
- kpiDashboard.innerHTML = '';
954
-
955
- // KPI 1: Engagement Score
956
- const engagementScore = supervisorData && supervisorData.engagement_score ? supervisorData.engagement_score : 85;
957
- const engagementCard = document.createElement('div');
958
- engagementCard.className = 'kpi-card';
959
- engagementCard.innerHTML = `
960
- <h4>Engagement Score</h4>
961
- <div class="kpi-value">${engagementScore}%</div>
962
- <div class="progress-bar">
963
- <div class="progress-fill" style="width: ${engagementScore}%"></div>
964
- </div>
965
- <p class="kpi-trend">Target: 90%</p>
966
- `;
967
- kpiDashboard.appendChild(engagementCard);
968
-
969
- // KPI 2: Task Completion Rate
970
- const taskCompletionRate = checklistProgress;
971
- const taskCard = document.createElement('div');
972
- taskCard.className = 'kpi-card';
973
- taskCard.innerHTML = `
974
- <h4>Task Completion Rate</h4>
975
- <div class="kpi-value">${Math.round(taskCompletionRate)}%</div>
976
- <div class="progress-bar">
977
- <div class="progress-fill" style="width: ${taskCompletionRate}%"></div>
978
- </div>
979
- <p class="kpi-trend">Based on Daily Checklist</p>
980
- `;
981
- kpiDashboard.appendChild(taskCard);
982
-
983
- // KPI 3: Reflection Frequency
984
- const reflectionFrequency = reflectionHistory.length;
985
- const reflectionCard = document.createElement('div');
986
- reflectionCard.className = 'kpi-card';
987
- reflectionCard.innerHTML = `
988
- <h4>Reflection Frequency</h4>
989
- <div class="kpi-value">${reflectionFrequency}</div>
990
- <div class="progress-bar">
991
- <div class="progress-fill" style="width: ${(reflectionFrequency / 5) * 100}%"></div>
992
- </div>
993
- <p class="kpi-trend">Goal: 5 per week</p>
994
- `;
995
- kpiDashboard.appendChild(reflectionCard);
996
-
997
- // KPI 4: KPI Flag
998
- const kpiFlag = supervisorData && supervisorData.kpi_flag !== undefined ? supervisorData.kpi_flag : false;
999
- const flagCard = document.createElement('div');
1000
- flagCard.className = 'kpi-card';
1001
- flagCard.innerHTML = `
1002
- <h4>KPI Flag Status</h4>
1003
- <div class="kpi-value">
1004
- <span class="kpi-flag ${kpiFlag ? 'active' : 'inactive'}">${kpiFlag ? 'Active' : 'Inactive'}</span>
1005
- </div>
1006
- <p class="kpi-trend">Performance Indicator</p>
1007
- `;
1008
- kpiDashboard.appendChild(flagCard);
1009
- }
1010
-
1011
- function downloadPDF() {
1012
- if (!supervisorData || !supervisorData.download_link) {
1013
- showToast('error', 'No download link available.');
1014
- return;
1015
  }
1016
- window.open(supervisorData.download_link, '_blank');
1017
  }
1018
 
1019
- // Event Listeners
1020
- document.getElementById('search-bar').addEventListener('input', searchData);
1021
  window.onload = () => {
1022
- fetchSupervisorData();
1023
- setAvatar();
 
1024
  };
1025
  </script>
1026
  </body>
 
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>
 
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) {
 
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>