Update templates/index.html
Browse files- templates/index.html +197 -279
templates/index.html
CHANGED
@@ -196,7 +196,6 @@
|
|
196 |
font-size: 20px;
|
197 |
color: #ed8936;
|
198 |
}
|
199 |
-
/* Daily Checklist Section */
|
200 |
.checklist-header {
|
201 |
display: flex;
|
202 |
justify-content: space-between;
|
@@ -256,7 +255,6 @@
|
|
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;
|
@@ -284,7 +282,6 @@
|
|
284 |
font-size: 15px;
|
285 |
color: #4a5568;
|
286 |
}
|
287 |
-
/* Supervisor Data Section */
|
288 |
pre {
|
289 |
background-color: #f7fafc;
|
290 |
padding: 15px;
|
@@ -296,7 +293,6 @@
|
|
296 |
overflow-y: auto;
|
297 |
color: #4a5568;
|
298 |
}
|
299 |
-
/* Reflection Journal Section */
|
300 |
.reflection-journal {
|
301 |
display: flex;
|
302 |
flex-direction: column;
|
@@ -347,7 +343,6 @@
|
|
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));
|
@@ -413,7 +408,6 @@
|
|
413 |
background-color: #f56565;
|
414 |
color: #fff;
|
415 |
}
|
416 |
-
/* Buttons */
|
417 |
button {
|
418 |
padding: 12px 25px;
|
419 |
background: linear-gradient(to right, #f6ad55, #ed8936);
|
@@ -435,7 +429,6 @@
|
|
435 |
.download-btn:hover {
|
436 |
background: linear-gradient(to right, #2f855a, #38a169);
|
437 |
}
|
438 |
-
/* Toast Notifications */
|
439 |
.toast {
|
440 |
position: fixed;
|
441 |
top: 20px;
|
@@ -459,7 +452,6 @@
|
|
459 |
.toast.visible {
|
460 |
display: block;
|
461 |
}
|
462 |
-
/* Responsive Design */
|
463 |
@media (max-width: 900px) {
|
464 |
.content-grid {
|
465 |
grid-template-columns: 1fr;
|
@@ -572,7 +564,6 @@
|
|
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>
|
@@ -581,19 +572,16 @@
|
|
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">
|
@@ -605,17 +593,13 @@
|
|
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 |
|
@@ -626,7 +610,6 @@
|
|
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;
|
@@ -636,15 +619,13 @@
|
|
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.
|
646 |
-
|
647 |
-
avatar.textContent = username.charAt(0).toUpperCase();
|
648 |
} else {
|
649 |
avatar.textContent = 'G';
|
650 |
}
|
@@ -653,7 +634,6 @@
|
|
653 |
}
|
654 |
}
|
655 |
|
656 |
-
// Dropdown Toggle
|
657 |
function toggleDropdown() {
|
658 |
const dropdown = document.getElementById('dropdown');
|
659 |
dropdown.classList.toggle('active');
|
@@ -670,7 +650,6 @@
|
|
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 {
|
@@ -681,7 +660,6 @@
|
|
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');
|
@@ -729,7 +707,6 @@
|
|
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;
|
@@ -738,6 +715,16 @@
|
|
738 |
progressCircle.querySelector('span').textContent = `${Math.round(checklistProgress)}%`;
|
739 |
}
|
740 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
741 |
async function fetchSupervisorData() {
|
742 |
try {
|
743 |
const response = await fetch('/get_supervisor_data');
|
@@ -747,7 +734,6 @@
|
|
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());
|
@@ -761,267 +747,199 @@
|
|
761 |
<label for="checklist-${index}">${item}</label>
|
762 |
`;
|
763 |
checklistDiv.appendChild(itemDiv);
|
764 |
-
|
765 |
-
|
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 |
-
|
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 |
-
|
891 |
-
}
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
} else {
|
907 |
-
|
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 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
body: JSON.stringify({ reflection: reflectionInput })
|
929 |
});
|
930 |
-
|
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 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1007 |
`;
|
1008 |
-
kpiDashboard.appendChild(
|
1009 |
-
}
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1025 |
</script>
|
1026 |
</body>
|
1027 |
</html>
|
|
|
196 |
font-size: 20px;
|
197 |
color: #ed8936;
|
198 |
}
|
|
|
199 |
.checklist-header {
|
200 |
display: flex;
|
201 |
justify-content: space-between;
|
|
|
255 |
text-decoration: line-through;
|
256 |
color: #a0aec0;
|
257 |
}
|
|
|
258 |
.tip-card {
|
259 |
background: linear-gradient(145deg, #e6f0fa, #d1e3ff);
|
260 |
padding: 20px;
|
|
|
282 |
font-size: 15px;
|
283 |
color: #4a5568;
|
284 |
}
|
|
|
285 |
pre {
|
286 |
background-color: #f7fafc;
|
287 |
padding: 15px;
|
|
|
293 |
overflow-y: auto;
|
294 |
color: #4a5568;
|
295 |
}
|
|
|
296 |
.reflection-journal {
|
297 |
display: flex;
|
298 |
flex-direction: column;
|
|
|
343 |
font-weight: 600;
|
344 |
color: #2d3748;
|
345 |
}
|
|
|
346 |
.kpi-dashboard {
|
347 |
display: grid;
|
348 |
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
|
408 |
background-color: #f56565;
|
409 |
color: #fff;
|
410 |
}
|
|
|
411 |
button {
|
412 |
padding: 12px 25px;
|
413 |
background: linear-gradient(to right, #f6ad55, #ed8936);
|
|
|
429 |
.download-btn:hover {
|
430 |
background: linear-gradient(to right, #2f855a, #38a169);
|
431 |
}
|
|
|
432 |
.toast {
|
433 |
position: fixed;
|
434 |
top: 20px;
|
|
|
452 |
.toast.visible {
|
453 |
display: block;
|
454 |
}
|
|
|
455 |
@media (max-width: 900px) {
|
456 |
.content-grid {
|
457 |
grid-template-columns: 1fr;
|
|
|
564 |
|
565 |
<div class="container">
|
566 |
<div class="content-grid">
|
|
|
567 |
<div class="section checklist-section">
|
568 |
<div class="checklist-header">
|
569 |
<h3><i>📋</i> Daily Checklist</h3>
|
|
|
572 |
<div id="checklist-items"></div>
|
573 |
</div>
|
574 |
|
|
|
575 |
<div class="section tips-section">
|
576 |
<h3><i>💡</i> Today's Top 3 Focus Areas</h3>
|
577 |
<div id="focus-tips"></div>
|
578 |
</div>
|
579 |
|
|
|
580 |
<div class="section full-width">
|
581 |
<h3><i>📊</i> Supervisor Data</h3>
|
582 |
<pre id="supervisor-data">Loading supervisor data...</pre>
|
583 |
</div>
|
584 |
|
|
|
585 |
<div class="section full-width reflection-journal">
|
586 |
<h3><i>📝</i> Reflection Journal</h3>
|
587 |
<div class="reflection-input-area">
|
|
|
593 |
</div>
|
594 |
</div>
|
595 |
|
|
|
596 |
<div class="section full-width kpi-section">
|
597 |
<h3><i>📈</i> KPI Summary Dashboard</h3>
|
598 |
+
<div class="kpi-dashboard" id="kpi-dashboard"></div>
|
|
|
|
|
599 |
</div>
|
600 |
</div>
|
601 |
</div>
|
602 |
|
|
|
603 |
<div id="error" class="toast error"></div>
|
604 |
<div id="success" class="toast success"></div>
|
605 |
|
|
|
610 |
let checklistProgress = 0;
|
611 |
let totalChecklistItems = 0;
|
612 |
|
|
|
613 |
function showToast(id, message) {
|
614 |
const toast = document.getElementById(id);
|
615 |
toast.textContent = message;
|
|
|
619 |
}, 3000);
|
620 |
}
|
621 |
|
|
|
622 |
async function setAvatar() {
|
623 |
const avatar = document.getElementById('avatar');
|
624 |
try {
|
625 |
const response = await fetch('/get_supervisor_data');
|
626 |
const result = await response.json();
|
627 |
+
if (result.status === 'success' && result.data.supervisor_name !== 'GUEST') {
|
628 |
+
avatar.textContent = result.data.supervisor_name.charAt(0).toUpperCase();
|
|
|
629 |
} else {
|
630 |
avatar.textContent = 'G';
|
631 |
}
|
|
|
634 |
}
|
635 |
}
|
636 |
|
|
|
637 |
function toggleDropdown() {
|
638 |
const dropdown = document.getElementById('dropdown');
|
639 |
dropdown.classList.toggle('active');
|
|
|
650 |
headers: { 'Content-Type': 'application/json' }
|
651 |
});
|
652 |
const result = await response.json();
|
|
|
653 |
if (result.status === 'success') {
|
654 |
window.location.href = '/login';
|
655 |
} else {
|
|
|
660 |
}
|
661 |
}
|
662 |
|
|
|
663 |
function searchData() {
|
664 |
const query = document.getElementById('search-bar').value.toLowerCase().trim();
|
665 |
const resultsDiv = document.getElementById('search-results');
|
|
|
707 |
showToast('error', 'Voice search not implemented yet.');
|
708 |
}
|
709 |
|
|
|
710 |
function updateChecklistProgress() {
|
711 |
const completedItems = document.querySelectorAll('.checklist-item.completed').length;
|
712 |
checklistProgress = totalChecklistItems > 0 ? (completedItems / totalChecklistItems) * 100 : 0;
|
|
|
715 |
progressCircle.querySelector('span').textContent = `${Math.round(checklistProgress)}%`;
|
716 |
}
|
717 |
|
718 |
+
function markComplete(index, checkbox) {
|
719 |
+
const itemDiv = checkbox.parentElement;
|
720 |
+
if (checkbox.checked) {
|
721 |
+
itemDiv.classList.add('completed');
|
722 |
+
} else {
|
723 |
+
itemDiv.classList.remove('completed');
|
724 |
+
}
|
725 |
+
updateChecklistProgress();
|
726 |
+
}
|
727 |
+
|
728 |
async function fetchSupervisorData() {
|
729 |
try {
|
730 |
const response = await fetch('/get_supervisor_data');
|
|
|
734 |
supervisorData = result.data;
|
735 |
document.getElementById('supervisor-data').textContent = JSON.stringify(supervisorData, null, 2);
|
736 |
|
|
|
737 |
const checklistDiv = document.getElementById('checklist-items');
|
738 |
if (supervisorData.daily_checklist) {
|
739 |
const checklistItems = supervisorData.daily_checklist.split('\n').filter(item => item.trim());
|
|
|
747 |
<label for="checklist-${index}">${item}</label>
|
748 |
`;
|
749 |
checklistDiv.appendChild(itemDiv);
|
750 |
+
actic: read
|
751 |
+
checklistDiv.appendChild(itemDiv);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
752 |
});
|
753 |
+
updateChecklistProgress();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
754 |
} else {
|
755 |
+
checklistDiv.innerHTML = '<p>No checklist items available.</p>';
|
756 |
+
}
|
757 |
+
|
758 |
+
const tipsDiv = document.getElementById('focus-tips');
|
759 |
+
if (supervisorData.suggested_tips) {
|
760 |
+
const tips = supervisorData.suggested_tips.split('\n').filter(tip => tip.trim());
|
761 |
+
tipsDiv.innerHTML = '';
|
762 |
+
const tipCard = document.createElement('div');
|
763 |
+
tipCard.className = 'tip-card';
|
764 |
+
tipCard.innerHTML = `
|
765 |
+
<h4>Today's Top 3 Focus Areas</h4>
|
766 |
+
<ul>
|
767 |
+
${tips.map(tip => `<li>${tip}</li>`).join('')}
|
768 |
+
</ul>
|
769 |
+
`;
|
770 |
+
tipsDiv.appendChild(tipCard);
|
771 |
} else {
|
772 |
+
tipsDiv.innerHTML = '<p>No focus tips available.</p>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
773 |
}
|
774 |
|
775 |
+
if (supervisorData.reflection_log) {
|
776 |
+
reflectionHistory.push({
|
777 |
+
date: new Date().toLocaleString(),
|
778 |
+
text: supervisorData.reflection_log
|
|
|
779 |
});
|
780 |
+
updateReflectionHistory();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
781 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
782 |
|
783 |
+
const downloadBtn = document.getElementById('download-btn');
|
784 |
+
if (supervisorData.download_link) {
|
785 |
+
downloadBtn.onclick = () => window.open(supervisorData.download_link, '_blank');
|
786 |
+
downloadBtn.textContent = 'Download Report';
|
787 |
+
} else {
|
788 |
+
downloadBtn.onclick = downloadPDF;
|
789 |
+
downloadBtn.textContent = 'Download PDF Summary';
|
790 |
+
}
|
791 |
+
|
792 |
+
updateKPIDashboard();
|
793 |
+
} else {
|
794 |
+
showToast('error', result.message);
|
795 |
+
document.getElementById('supervisor-data').textContent = 'Failed to load supervisor data.';
|
796 |
+
}
|
797 |
+
} catch (error) {
|
798 |
+
showToast('error', 'Error fetching supervisor data: ' + error.message);
|
799 |
+
document.getElementById('supervisor-data').textContent = 'Failed to load supervisor data.';
|
800 |
+
}
|
801 |
+
}
|
802 |
+
|
803 |
+
async function generateCoaching() {
|
804 |
+
if (!supervisorData) {
|
805 |
+
showToast('error', 'Supervisor data not loaded. Please refresh the page.');
|
806 |
+
return;
|
807 |
+
}
|
808 |
+
|
809 |
+
try {
|
810 |
+
const response = await fetch('/generate', {
|
811 |
+
method: 'POST',
|
812 |
+
headers: { 'Content-Type': 'application/json' },
|
813 |
+
body: JSON.stringify(supervisorData)
|
814 |
+
});
|
815 |
+
const result = await response.json();
|
816 |
+
|
817 |
+
if (result.status === 'success') {
|
818 |
+
coachingOutput = result.output;
|
819 |
+
showToast('success', 'Coaching output generated successfully!');
|
820 |
+
await fetchSupervisorData();
|
821 |
+
} else {
|
822 |
+
showToast('error', result.message);
|
823 |
+
}
|
824 |
+
} catch (error) {
|
825 |
+
showToast('error', 'Error generating coaching output: ' + error.message);
|
826 |
+
}
|
827 |
+
}
|
828 |
+
|
829 |
+
async function submitReflection() {
|
830 |
+
const reflectionInput = document.getElementById('reflection-input');
|
831 |
+
const reflection = reflectionInput.value.trim();
|
832 |
+
|
833 |
+
if (!reflection) {
|
834 |
+
showToast('error', 'Reflection cannot be empty.');
|
835 |
+
return;
|
836 |
+
}
|
837 |
+
|
838 |
+
try {
|
839 |
+
const response = await fetch('/submit_reflection', {
|
840 |
+
method: 'POST',
|
841 |
+
headers: { 'Content-Type': 'application/json' },
|
842 |
+
body: JSON.stringify({ reflection })
|
843 |
+
});
|
844 |
+
const result = await response.json();
|
845 |
+
|
846 |
+
if (result.status === 'success') {
|
847 |
+
showToast('success', result.message);
|
848 |
+
reflectionHistory.push({
|
849 |
+
date: new Date().toLocaleString(),
|
850 |
+
text: reflection
|
851 |
+
});
|
852 |
+
reflectionInput.value = '';
|
853 |
+
updateReflectionHistory();
|
854 |
+
await fetchSupervisorData();
|
855 |
+
} else {
|
856 |
+
showToast('error', result.message);
|
857 |
+
}
|
858 |
+
} catch (error) {
|
859 |
+
showToast('error', 'Error submitting reflection: ' + error.message);
|
860 |
+
}
|
861 |
+
}
|
862 |
+
|
863 |
+
function updateReflectionHistory() {
|
864 |
+
const historyDiv = document.getElementById('reflection-history');
|
865 |
+
if (reflectionHistory.length > 0) {
|
866 |
+
historyDiv.innerHTML = reflectionHistory.map(ref => `
|
867 |
+
<div class="reflection-entry">
|
868 |
+
<span>${ref.date}</span>: ${ref.text}
|
869 |
+
</div>
|
870 |
+
`).join('');
|
871 |
+
} else {
|
872 |
+
historyDiv.innerHTML = '<p>No reflections yet. Start logging your thoughts!</p>';
|
873 |
+
}
|
874 |
+
}
|
875 |
+
|
876 |
+
function updateKPIDashboard() {
|
877 |
+
const kpiDashboard = document.getElementById('kpi-dashboard');
|
878 |
+
kpiDashboard.innerHTML = '';
|
879 |
+
|
880 |
+
if (supervisorData) {
|
881 |
+
const kpiData = [
|
882 |
+
{
|
883 |
+
title: 'Engagement Score',
|
884 |
+
value: `${supervisorData.engagement_score}%`,
|
885 |
+
progress: supervisorData.engagement_score,
|
886 |
+
trend: supervisorData.engagement_score > 80 ? 'Upward' : 'Stable'
|
887 |
+
},
|
888 |
+
{
|
889 |
+
title: 'KPI Flag',
|
890 |
+
value: supervisorData.kpi_flag ? 'Active' : 'Inactive',
|
891 |
+
class: supervisorData.kpi_flag ? 'active' : 'inactive'
|
892 |
+
}
|
893 |
+
];
|
894 |
+
|
895 |
+
kpiData.forEach(kpi => {
|
896 |
+
const kpiCard = document.createElement('div');
|
897 |
+
kpiCard.className = 'kpi-card';
|
898 |
+
kpiCard.innerHTML = `
|
899 |
+
<h4>${kpi.title}</h4>
|
900 |
+
<div class="kpi-value ${kpi.class || ''}">${kpi.value}</div>
|
901 |
+
${kpi.progress !== undefined ? `
|
902 |
+
<div class="progress-bar">
|
903 |
+
<div class="progress-fill" style="width: ${kpi.progress}%"></div>
|
904 |
+
</div>
|
905 |
+
<div class="kpi-trend">Trend: ${kpi.trend}</div>
|
906 |
+
` : ''}
|
907 |
`;
|
908 |
+
kpiDashboard.appendChild(kpiCard);
|
909 |
+
});
|
910 |
+
} else {
|
911 |
+
kpiDashboard.innerHTML = '<p>No KPI data available.</p>';
|
912 |
+
}
|
913 |
+
}
|
914 |
+
|
915 |
+
async function downloadPDF() {
|
916 |
+
try {
|
917 |
+
const response = await fetch('/download_pdf');
|
918 |
+
if (response.ok && response.headers.get('content-type').includes('application/pdf')) {
|
919 |
+
const blob = await response.blob();
|
920 |
+
const url = window.URL.createObjectURL(blob);
|
921 |
+
const a = document.createElement('a');
|
922 |
+
a.href = url;
|
923 |
+
a.download = `supervisor_report_${supervisorData?.supervisor_name || 'report'}.pdf`;
|
924 |
+
document.body.appendChild(a);
|
925 |
+
a.click();
|
926 |
+
document.body.removeChild(a);
|
927 |
+
window.URL.revokeObjectURL(url);
|
928 |
+
showToast('success', 'PDF downloaded successfully!');
|
929 |
+
} else {
|
930 |
+
const result = await response.json();
|
931 |
+
showToast('error', result.message);
|
932 |
+
}
|
933 |
+
} catch (error) {
|
934 |
+
showToast('error', 'Error downloading PDF: ' + error.message);
|
935 |
+
}
|
936 |
+
}
|
937 |
+
|
938 |
+
document.getElementById('search-bar').addEventListener('input', searchData);
|
939 |
+
document.addEventListener('DOMContentLoaded', () => {
|
940 |
+
setAvatar();
|
941 |
+
fetchSupervisorData();
|
942 |
+
});
|
943 |
</script>
|
944 |
</body>
|
945 |
</html>
|