geethareddy commited on
Commit
8a37466
·
verified ·
1 Parent(s): e1551f7

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +971 -224
templates/index.html CHANGED
@@ -3,204 +3,824 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>AI Coach for Site Supervisors</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <link href="https://cdnjs.cloudflare.com/ajax/libs/heroicons/2.1.1/outline/index.min.css" rel="stylesheet">
9
  <style>
10
  body {
11
- font-family: 'Inter', sans-serif;
 
 
 
 
 
12
  }
13
- .checklist-item {
14
- transition: background-color 0.3s ease, transform 0.2s ease;
 
 
 
 
 
15
  }
16
- .checklist-item.completed {
17
- background-color: #ecfdf5;
18
- transform: scale(1.02);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
  .checklist-item:hover {
21
- transform: scale(1.02);
22
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  .tip-card {
24
- transition: transform 0.3s ease, box-shadow 0.3s ease;
 
 
 
 
 
25
  }
26
  .tip-card:hover {
27
- transform: translateY(-5px);
28
- box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
29
  }
30
- .fade-in {
31
- animation: fadeIn 0.5s ease-in-out;
 
 
 
32
  }
33
- @keyframes fadeIn {
34
- from { opacity: 0; transform: translateY(10px); }
35
- to { opacity: 1; transform: translateY(0); }
 
36
  }
37
- .gradient-header {
38
- background: linear-gradient(135deg, #3b82f6, #1d4ed8);
 
 
39
  }
40
- .spinner {
41
- border: 4px solid #f3f3f3;
42
- border-top: 4px solid #3b82f6;
43
- border-radius: 50%;
44
- width: 24px;
45
- height: 24px;
46
- animation: spin 1s linear infinite;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  display: none;
 
 
 
 
 
 
 
48
  }
49
- @keyframes spin {
50
- 0% { transform: rotate(0deg); }
51
- 100% { transform: rotate(360deg); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
  </style>
 
54
  </head>
55
- <body class="bg-gray-50 min-h-screen flex flex-col">
56
- <!-- Header -->
57
- <header class="gradient-header text-white p-6 shadow-lg">
58
- <h1 class="text-3xl font-bold tracking-tight flex items-center">
59
- <svg class="w-8 h-8 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
60
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
61
- </svg>
62
- AI Coach for Supervisors
63
- </h1>
64
- <p class="mt-1 text-sm opacity-80">Your daily guide to success</p>
65
- </header>
66
-
67
- <!-- Main Content -->
68
- <main class="flex-1 p-6 space-y-8 max-w-3xl mx-auto">
69
- <!-- Supervisor Input Form -->
70
- <section class="bg-white rounded-xl shadow-md p-6 fade-in">
71
- <h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
72
- <svg class="w-6 h-6 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
73
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
74
- </svg>
75
- Supervisor Details
76
- </h2>
77
- <div class="space-y-4">
78
- <div>
79
- <label class="block text-gray-700 font-medium mb-1">Role</label>
80
- <input id="role" type="text" value="Site Supervisor" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-400 focus:border-transparent" placeholder="e.g., Site Supervisor">
 
 
 
81
  </div>
82
- <div>
83
- <label class="block text-gray-700 font-medium mb-1">Location</label>
84
- <input id="location" type="text" value="Construction Site A" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-400 focus:border-transparent" placeholder="e.g., Construction Site A">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  </div>
86
- <div>
87
- <label class="block text-gray-700 font-medium mb-1">Project Schedule (JSON)</label>
88
- <textarea id="schedule" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-400 focus:border-transparent" rows="3" placeholder='e.g., [{"task": "Foundation Inspection", "due_date": "2025-05-07", "status": "Pending"}]'>[{"task": "Foundation Inspection", "due_date": "2025-05-07", "status": "Pending"}, {"task": "Material Delivery", "due_date": "2025-05-06", "status": "Delayed"}]</textarea>
89
  </div>
90
- <button id="loadData" class="w-full bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors duration-200 flex items-center justify-center">
91
- <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
92
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9H20m-7 7v5h-.582m-7.356-2A8.001 8.001 0 0119.418 15H4"></path>
93
- </svg>
94
- Load Coaching Data
95
- <div id="spinner" class="spinner ml-2"></div>
96
- </button>
97
  </div>
98
- </section>
99
-
100
- <!-- Alerts (Placeholder) -->
101
- <section id="alerts" class="bg-red-50 rounded-xl shadow-md p-6 fade-in hidden">
102
- <h2 class="text-2xl font-semibold text-red-800 mb-4 flex items-center">
103
- <svg class="w-6 h-6 mr-2 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
104
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
105
- </svg>
106
- Alerts
107
- </h2>
108
- <p class="text-red-700">No alerts at this time. (Placeholder for missed milestones or unsafe patterns)</p>
109
- </section>
110
-
111
- <!-- Checklist -->
112
- <section id="checklistSection" class="bg-white rounded-xl shadow-md p-6 fade-in hidden">
113
- <h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
114
- <svg class="w-6 h-6 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
115
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
116
- </svg>
117
- Daily Checklist
118
- </h2>
119
- <ul id="checklist" class="space-y-3"></ul>
120
- </section>
121
-
122
- <!-- Tips -->
123
- <section id="tipsSection" class="bg-white rounded-xl shadow-md p-6 fade-in hidden">
124
- <h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
125
- <svg class="w-6 h-6 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
126
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
127
- </svg>
128
- Today's Top 3 Focus Areas
129
- </h2>
130
- <ul id="tips" class="space-y-3"></ul>
131
- </section>
132
-
133
- <!-- Quote -->
134
- <section id="quoteSection" class="bg-white rounded-xl shadow-md p-6 fade-in hidden">
135
- <h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
136
- <svg class="w-6 h-6 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
137
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"></path>
138
- </svg>
139
- Motivational Quote
140
- </h2>
141
- <p id="quote" class="italic text-gray-600 text-lg"></p>
142
- </section>
143
-
144
- <!-- Reflection Journal -->
145
- <section class="bg-white rounded-xl shadow-md p-6 fade-in">
146
- <h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
147
- <svg class="w-6 h-6 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
148
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
149
- </svg>
150
- Reflection Journal
151
- </h2>
152
- <textarea id="reflection" class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-400 focus:border-transparent" rows="4" placeholder="Log your thoughts or observations..."></textarea>
153
- <button id="saveReflection" class="mt-3 w-full bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors duration-200">Save Reflection</button>
154
- </section>
155
-
156
- <!-- Engagement Score -->
157
- <section class="bg-white rounded-xl shadow-md p-6 fade-in">
158
- <h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
159
- <svg class="w-6 h-6 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
160
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 012-2h2a2 2 0 012 2v12a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
161
- </svg>
162
- Engagement Score
163
- </h2>
164
- <p class="text-gray-600 mb-3">Weekly trend (Placeholder)</p>
165
- <div class="h-40 bg-gray-100 rounded-lg flex items-center justify-center">
166
- <svg width="100%" height="100" class="max-w-full">
167
- <polyline points="10,90 30,70 50,80 70,50 90,60 110,40 130,60" fill="none" stroke="#3b82f6" stroke-width="2"/>
168
- <text x="10" y="20" fill="#4b5563" font-size="12">Engagement: 85%</text>
169
- <line x1="10" y1="90" x2="130" y2="90" stroke="#d1d5db" stroke-width="1"/>
170
- <line x1="10" y1="90" x2="10" y2="30" stroke="#d1d5db" stroke-width="1"/>
171
- </svg>
172
  </div>
173
- </section>
174
-
175
- <!-- PDF Download -->
176
- <section class="bg-white rounded-xl shadow-md p-6 fade-in">
177
- <h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
178
- <svg class="w-6 h-6 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
179
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
180
- </svg>
181
- Summary Report
182
- </h2>
183
- <button id="downloadPdf" class="w-full bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors duration-200">Download PDF Summary</button>
184
- </section>
185
- </main>
186
 
187
  <script>
188
- // Default supervisor data
189
- let supervisorData = {
190
- supervisor_id: "SUP123",
191
- role: "Site Supervisor",
192
- project_id: "PRJ456",
193
- milestones: [
194
- { task: "Foundation Inspection", due_date: "2025-05-07", status: "Pending" },
195
- { task: "Material Delivery", due_date: "2025-05-06", status: "Delayed" }
196
- ],
197
- reflection_log: "Noticed delays due to rain; team morale is low.",
198
- weather: "Rainy, 20°C"
199
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
- async function fetchCoachingOutput() {
202
- const spinner = document.getElementById('spinner');
203
- spinner.style.display = 'block';
204
  try {
205
  const response = await fetch('/generate', {
206
  method: 'POST',
@@ -208,73 +828,200 @@
208
  body: JSON.stringify(supervisorData)
209
  });
210
  const result = await response.json();
 
211
  if (result.status === 'success') {
212
- updateUI(result.output);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  } else {
214
- alert('Error: ' + result.message);
 
 
215
  }
216
  } catch (error) {
217
- alert('Failed to fetch coaching output: ' + error.message);
218
- } finally {
219
- spinner.style.display = 'none';
220
  }
221
  }
222
 
223
- function updateUI(output) {
224
- // Show sections
225
- document.getElementById('checklistSection').classList.remove('hidden');
226
- document.getElementById('tipsSection').classList.remove('hidden');
227
- document.getElementById('quoteSection').classList.remove('hidden');
 
 
 
 
 
228
 
229
- // Checklist
230
- const checklist = document.getElementById('checklist');
231
- checklist.innerHTML = output.checklist.map(item => `
232
- <li class="checklist-item flex items-center p-3 bg-gray-50 rounded-lg">
233
- <input type="checkbox" class="w-5 h-5 text-green-500 rounded focus:ring-green-400 mr-3" onchange="toggleCompletion(this)">
234
- <span class="text-gray-700">${item}</span>
235
- </li>
236
- `).join('');
 
 
 
 
 
 
 
 
 
237
 
238
- // Tips
239
- const tips = document.getElementById('tips');
240
- tips.innerHTML = output.tips.map(tip => `
241
- <li class="tip-card p-4 bg-blue-50 rounded-lg text-gray-700">${tip}</li>
242
- `).join('');
243
 
244
- // Quote
245
- document.getElementById('quote').textContent = output.quote;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
 
248
- function toggleCompletion(checkbox) {
249
- const li = checkbox.parentElement;
250
- li.classList.toggle('completed', checkbox.checked);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  }
252
 
253
- document.getElementById('saveReflection').addEventListener('click', () => {
254
- const reflection = document.getElementById('reflection').value;
255
- if (reflection) {
256
- alert('Reflection saved: ' + reflection);
257
- } else {
258
- alert('Please enter a reflection');
259
- }
260
- });
261
-
262
- document.getElementById('downloadPdf').addEventListener('click', () => {
263
- alert('PDF download feature coming soon...');
264
- });
265
-
266
- document.getElementById('loadData').addEventListener('click', () => {
267
- const role = document.getElementById('role').value;
268
- const location = document.getElementById('location').value;
269
- const schedule = JSON.parse(document.getElementById('schedule').value || '[]');
270
- supervisorData.role = role;
271
- supervisorData.location = location;
272
- supervisorData.milestones = schedule;
273
- fetchCoachingOutput();
274
- });
275
-
276
- // Initial load (optional, can be triggered by button only)
277
- fetchCoachingOutput();
278
  </script>
279
  </body>
280
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Coach Dashboard</title>
 
 
7
  <style>
8
  body {
9
+ font-family: 'Roboto', Arial, sans-serif;
10
+ margin: 0;
11
+ padding: 0;
12
+ background: linear-gradient(135deg, #f0f2f5 0%, #e9ecef 100%);
13
+ color: #2d3748;
14
+ line-height: 1.6;
15
  }
16
+ .header {
17
+ background: linear-gradient(to right, #1a3c7a, #2957a4);
18
+ padding: 15px 25px;
19
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
20
+ position: sticky;
21
+ top: 0;
22
+ z-index: 100;
23
  }
24
+ .header-title {
25
+ color: #fff;
26
+ margin: 0;
27
+ font-size: 26px;
28
+ font-weight: 700;
29
+ text-align: center;
30
+ padding-bottom: 10px;
31
+ }
32
+ .header-actions {
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: space-between;
36
+ gap: 20px;
37
+ }
38
+ .avatar {
39
+ width: 42px;
40
+ height: 42px;
41
+ background: linear-gradient(to right, #f6ad55, #ed8936);
42
+ color: #fff;
43
+ border-radius: 50%;
44
+ display: flex;
45
+ align-items: center;
46
+ justify-content: center;
47
+ font-size: 20px;
48
+ font-weight: 600;
49
+ cursor: pointer;
50
+ position: relative;
51
+ transition: transform 0.2s ease;
52
+ }
53
+ .avatar:hover {
54
+ transform: scale(1.05);
55
+ background: linear-gradient(to right, #ed8936, #dd6b20);
56
+ }
57
+ .dropdown {
58
+ display: none;
59
+ position: absolute;
60
+ top: 50px;
61
+ right: 0;
62
+ background-color: #fff;
63
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
64
+ border-radius: 10px;
65
+ min-width: 160px;
66
+ z-index: 101;
67
+ overflow: hidden;
68
+ }
69
+ .dropdown.active {
70
+ display: block;
71
+ }
72
+ .dropdown a {
73
+ display: block;
74
+ padding: 12px 20px;
75
+ color: #2d3748;
76
+ text-decoration: none;
77
+ font-size: 15px;
78
+ transition: background 0.3s ease;
79
+ }
80
+ .dropdown a:hover {
81
+ background-color: #f7fafc;
82
+ }
83
+ .search-container {
84
+ position: relative;
85
+ flex: 1;
86
+ max-width: 500px;
87
+ }
88
+ .search-bar {
89
+ width: 100%;
90
+ padding: 12px 45px 12px 20px;
91
+ border: 2px solid #e2e8f0;
92
+ border-radius: 25px;
93
+ font-size: 15px;
94
+ box-sizing: border-box;
95
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
96
+ background-color: #fff;
97
+ }
98
+ .search-bar:focus {
99
+ border-color: #ed8936;
100
+ outline: none;
101
+ box-shadow: 0 0 8px rgba(237, 137, 54, 0.3);
102
+ }
103
+ .mic-icon {
104
+ position: absolute;
105
+ right: 15px;
106
+ top: 50%;
107
+ transform: translateY(-50%);
108
+ width: 22px;
109
+ height: 22px;
110
+ background: url('https://img.icons8.com/ios-filled/50/000000/microphone.png') no-repeat center;
111
+ background-size: contain;
112
+ cursor: pointer;
113
+ opacity: 0.6;
114
+ transition: opacity 0.3s ease;
115
+ }
116
+ .mic-icon:hover {
117
+ opacity: 1;
118
+ }
119
+ .search-results {
120
+ position: absolute;
121
+ top: 50px;
122
+ left: 0;
123
+ right: 0;
124
+ background-color: #fff;
125
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
126
+ border-radius: 10px;
127
+ max-height: 220px;
128
+ overflow-y: auto;
129
+ z-index: 100;
130
+ display: none;
131
+ }
132
+ .search-results.active {
133
+ display: block;
134
+ }
135
+ .search-results p {
136
+ padding: 10px 15px;
137
+ margin: 0;
138
+ font-size: 14px;
139
+ color: #4a5568;
140
+ border-bottom: 1px solid #edf2f7;
141
+ transition: background 0.2s ease;
142
+ }
143
+ .search-results p:hover {
144
+ background-color: #f7fafc;
145
+ }
146
+ .search-results p:last-child {
147
+ border-bottom: none;
148
+ }
149
+ .action-bar {
150
+ background-color: #fff;
151
+ padding: 15px 25px;
152
+ display: flex;
153
+ justify-content: center;
154
+ gap: 20px;
155
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
156
+ position: sticky;
157
+ top: 90px;
158
+ z-index: 99;
159
+ }
160
+ .container {
161
+ max-width: 1200px;
162
+ margin: 40px auto;
163
+ padding: 0 25px;
164
+ }
165
+ .content-grid {
166
+ display: grid;
167
+ grid-template-columns: 1fr 1fr;
168
+ gap: 30px;
169
+ margin-bottom: 40px;
170
+ }
171
+ .section {
172
+ padding: 25px;
173
+ background-color: #fff;
174
+ border-radius: 12px;
175
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
176
+ border-left: 5px solid #ed8936;
177
+ transition: transform 0.2s ease, box-shadow 0.3s ease;
178
+ }
179
+ .section:hover {
180
+ transform: translateY(-5px);
181
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
182
+ }
183
+ .section.full-width {
184
+ grid-column: span 2;
185
+ }
186
+ h3 {
187
+ margin: 0 0 20px 0;
188
+ color: #1a3c7a;
189
+ font-size: 22px;
190
+ font-weight: 600;
191
+ display: flex;
192
+ align-items: center;
193
+ gap: 10px;
194
+ }
195
+ h3 i {
196
+ font-size: 20px;
197
+ color: #ed8936;
198
+ }
199
+ /* 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
+
629
+ // Toast Notification Function
630
+ function showToast(id, message) {
631
+ const toast = document.getElementById(id);
632
+ toast.textContent = message;
633
+ toast.classList.add('visible');
634
+ setTimeout(() => {
635
+ toast.classList.remove('visible');
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',
 
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>
1027
  </html>