geethareddy's picture
Update templates/index.html
6f978da verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Construction Supervisor AI Coach</title>
<style>
:root {
--primary-blue: #2563EB;
--secondary-orange: #F97316;
--accent-yellow: #FBBF24;
--success-green: #48BB78;
--error-red: #F56565;
--warning-yellow: #ECC94B;
--background-light: #F7FAFC;
--card-bg: #FFFFFF;
--text-dark: #1A202C;
--text-muted: #718096;
}
body {
font-family: 'Roboto', Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #F5F7FA;
color: var(--text-dark);
line-height: 1.6;
display: flex;
}
/* Sidebar */
.sidebar {
width: 200px;
background-color: var(--card-bg);
height: 100vh;
position: fixed;
top: 0;
left: 0;
padding: 20px;
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
gap: 10px;
}
.sidebar h1 {
font-size: 18px;
color: var(--primary-blue);
margin: 0 0 20px 0;
}
.sidebar a {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 15px;
color: var(--text-muted);
text-decoration: none;
border-radius: 5px;
transition: background 0.3s ease;
}
.sidebar a.active {
background-color: #E6F0FA;
color: var(--primary-blue);
}
.sidebar a:hover {
background-color: #E6F0FA;
}
.sidebar img {
width: 20px;
height: 20px;
}
/* Main Content */
.main-content {
margin-left: 200px;
padding: 20px;
flex: 1;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
background-color: var(--card-bg);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.header .user-info {
display: flex;
align-items: center;
gap: 10px;
}
.header .user-info img {
width: 20px;
height: 20px;
}
.header .user-info span {
font-size: 14px;
color: var(--text-muted);
}
.header .user-info .avatar {
width: 30px;
height: 30px;
background-color: var(--primary-blue);
color: #FFFFFF;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
/* Sections */
.section {
background-color: var(--card-bg);
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
}
.section h2 {
font-size: 24px;
color: var(--text-dark);
margin: 0 0 10px 0;
}
.section p {
font-size: 14px;
color: var(--text-muted);
margin: 0 0 20px 0;
}
/* Dashboard Section */
.dashboard-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.checklist-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 0;
font-size: 14px;
}
.checklist-item input {
accent-color: var(--primary-blue);
}
.checklist-item label {
flex: 1;
color: var(--text-dark);
}
.checklist-item label.category-safety {
color: var(--error-red);
}
.checklist-item label.category-materials {
color: var(--primary-blue);
}
.checklist-item label.category-inspection {
color: var(--warning-yellow);
}
.project-progress {
display: flex;
flex-direction: column;
gap: 10px;
}
.project-progress .progress-bar {
width: 100%;
height: 10px;
background-color: #E2E8F0;
border-radius: 5px;
overflow: hidden;
}
.project-progress .progress-fill {
height: 100%;
background-color: var(--primary-blue);
transition: width 0.5s ease;
}
.metrics-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.metric-card {
text-align: center;
padding: 10px;
border-radius: 5px;
background-color: #F9FAFB;
}
.metric-card h4 {
font-size: 14px;
color: var(--text-muted);
margin: 0 0 5px 0;
}
.metric-card .value {
font-size: 24px;
font-weight: 700;
color: var(--primary-blue);
}
.metric-card .trend {
font-size: 12px;
color: var(--error-red);
}
.tips-card {
padding: 15px;
border-radius: 5px;
margin-bottom: 10px;
font-size: 14px;
}
.tips-card.warning {
background-color: #FEF3C7;
color: var(--warning-yellow);
}
.tips-card.info {
background-color: #EBF5FF;
color: var(--primary-blue);
}
.tips-card.medium {
background-color: #F3F4F6;
color: var(--text-muted);
}
/* Reflections Section */
.mood-buttons {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
.mood-buttons button {
padding: 8px 15px;
border: 1px solid #E2E8F0;
border-radius: 5px;
background-color: var(--card-bg);
color: var(--text-muted);
cursor: pointer;
transition: background 0.3s ease;
}
.mood-buttons button.active {
background-color: var(--primary-blue);
color: #FFFFFF;
border-color: var(--primary-blue);
}
.reflection-input textarea {
width: 100%;
height: 100px;
padding: 10px;
border: 1px solid #E2E8F0;
border-radius: 5px;
resize: none;
font-size: 14px;
margin-bottom: 10px;
}
.reflection-history .entry {
padding: 10px 0;
border-bottom: 1px solid #E2E8F0;
font-size: 14px;
}
.reflection-history .entry:last-child {
border-bottom: none;
}
.reflection-history .entry .date {
font-weight: 600;
color: var(--text-dark);
}
.reflection-history .entry .mood {
padding: 2px 8px;
border-radius: 5px;
font-size: 12px;
margin-left: 10px;
}
.reflection-history .entry .mood.concerned {
background-color: #FEF3C7;
color: var(--warning-yellow);
}
.reflection-history .entry .mood.satisfied {
background-color: #D1FAE5;
color: var(--success-green);
}
.reflection-history .entry .mood.neutral {
background-color: #F3F4F6;
color: var(--text-muted);
}
/* Reports Section */
.report-form {
display: flex;
flex-direction: column;
gap: 15px;
}
.report-form input,
.report-form select {
padding: 10px;
border: 1px solid #E2E8F0;
border-radius: 5px;
font-size: 14px;
}
.report-form .date-range {
display: flex;
gap: 10px;
}
.report-list .report-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid #E2E8F0;
font-size: 14px;
}
.report-list .report-item:last-child {
border-bottom: none;
}
.report-list .report-item .status {
padding: 2px 8px;
border-radius: 5px;
font-size: 12px;
background-color: #D1FAE5;
color: var(--success-green);
}
/* Milestones Section */
.milestones-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.milestone-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
border-radius: 5px;
margin-bottom: 10px;
font-size: 14px;
}
.milestone-item.completed {
background-color: #D1FAE5;
}
.milestone-item.in-progress {
background-color: #EBF5FF;
}
.milestone-item.not-started {
background-color: #F3F4F6;
}
.milestone-item .progress-bar {
width: 100%;
height: 5px;
background-color: #E2E8F0;
border-radius: 5px;
overflow: hidden;
margin-top: 5px;
}
.milestone-item .progress-fill {
height: 100%;
background-color: var(--primary-blue);
transition: width 0.5s ease;
}
.milestone-item .status {
padding: 2px 8px;
border-radius: 5px;
font-size: 12px;
}
.milestone-item .status.completed {
background-color: var(--success-green);
color: #FFFFFF;
}
.milestone-item .status.in-progress {
background-color: var(--primary-blue);
color: #FFFFFF;
}
.milestone-item .status.not-started {
background-color: var(--text-muted);
color: #FFFFFF;
}
/* Profile Section */
.profile-grid {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 20px;
align-items: center;
margin-bottom: 20px;
}
.profile-grid .avatar {
width: 80px;
height: 80px;
background-color: var(--primary-blue);
color: #FFFFFF;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
}
.profile-details p {
margin: 5px 0;
font-size: 14px;
}
.preferences-form {
display: flex;
flex-direction: column;
gap: 15px;
}
.preferences-form .toggle {
display: flex;
align-items: center;
gap: 10px;
}
.preferences-form .toggle input {
width: 40px;
height: 20px;
appearance: none;
background-color: #E2E8F0;
border-radius: 20px;
position: relative;
cursor: pointer;
outline: none;
}
.preferences-form .toggle input:checked {
background-color: var(--primary-blue);
}
.preferences-form .toggle input::before {
content: '';
width: 16px;
height: 16px;
background-color: #FFFFFF;
border-radius: 50%;
position: absolute;
top: 2px;
left: 2px;
transition: transform 0.3s ease;
}
.preferences-form .toggle input:checked::before {
transform: translateX(20px);
}
.preferences-form select {
padding: 10px;
border: 1px solid #E2E8F0;
border-radius: 5px;
font-size: 14px;
}
/* Buttons */
button {
padding: 10px 20px;
background-color: var(--primary-blue);
color: #FFFFFF;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
transition: background 0.3s ease;
}
button:hover {
background-color: #1E4DB7;
}
button.secondary {
background-color: #E2E8F0;
color: var(--text-dark);
}
button.secondary:hover {
background-color: #D1D5DB;
}
/* Toast Notifications */
.toast {
position: fixed;
top: 20px;
right: 20px;
padding: 10px 20px;
border-radius: 5px;
z-index: 1000;
display: none;
font-size: 14px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.toast.error {
background-color: var(--error-red);
color: #FFFFFF;
}
.toast.success {
background-color: var(--success-green);
color: #FFFFFF;
}
.toast.visible {
display: block;
}
/* Responsive Design */
@media (max-width: 768px) {
.sidebar {
width: 60px;
padding: 10px;
}
.sidebar h1 {
font-size: 14px;
}
.sidebar a {
padding: 5px;
justify-content: center;
}
.sidebar a span {
display: none;
}
.main-content {
margin-left: 60px;
padding: 10px;
}
.dashboard-grid {
grid-template-columns: 1fr;
}
.metrics-grid {
grid-template-columns: 1fr;
}
.profile-grid {
grid-template-columns: 1fr;
text-align: center;
}
.profile-grid .avatar {
margin: 0 auto;
}
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
</head>
<body>
<!-- Sidebar -->
<div class="sidebar">
<h1>STPL Coach</h1>
<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>
<a href="#reflections" onclick="showSection('reflections')"><img src="https://img.icons8.com/ios-filled/50/book.png" alt="Reflections"> <span>Reflections</span></a>
<a href="#reports" onclick="showSection('reports')"><img src="https://img.icons8.com/ios-filled/50/report-card.png" alt="Reports"> <span>Reports</span></a>
<a href="#milestones" onclick="showSection('milestones')"><img src="https://img.icons8.com/ios-filled/50/milestone.png" alt="Milestones"> <span>Milestones</span></a>
<a href="#profile" onclick="showSection('profile')"><img src="https://img.icons8.com/ios-filled/50/user.png" alt="Profile"> <span>Profile</span></a>
</div>
<!-- Main Content -->
<div class="main-content">
<div class="header">
<div></div>
<div class="user-info">
<img src="https://img.icons8.com/ios-filled/50/bell.png" alt="Notifications">
<span>Senior Construction Supervisor</span>
<div class="avatar">A</div>
</div>
</div>
<!-- Dashboard Section -->
<div class="section dashboard-section" id="dashboard-section">
<h2>Good morning, Alex</h2>
<p>Here's your checklist summary for today</p>
<div class="dashboard-grid">
<div>
<h3>Today's Checklist</h3>
<p>1 of 5 complete</p>
<div id="checklist-items">
<div class="checklist-item">
<input type="checkbox" id="checklist-0" onchange="markComplete(0, this)">
<label for="checklist-0" class="category-safety">Review safety equipment status for concrete pouring team</label>
</div>
<div class="checklist-item">
<input type="checkbox" id="checklist-1" onchange="markComplete(1, this)">
<label for="checklist-1" class="category-materials">Verify delivery of steel reinforcement for floor 3</label>
</div>
<div class="checklist-item">
<input type="checkbox" id="checklist-2" onchange="markComplete(2, this)">
<label for="checklist-2">Coordinate with electrical contractor on conduit installation</label>
</div>
<div class="checklist-item">
<input type="checkbox" id="checklist-3" onchange="markComplete(3, this)">
<label for="checklist-3" class="category-inspection">Inspect temporary weather protection measures</label>
</div>
<div class="checklist-item">
<input type="checkbox" id="checklist-4" onchange="markComplete(4, this)">
<label for="checklist-4">Update project timeline based on foundation completion</label>
</div>
</div>
<h3>Today's Coaching Tips</h3>
<div class="tips-card warning">
<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.
</div>
<div class="tips-card info">
<strong>Team Motivation:</strong> The concrete team has been exceeding expectations. Consider acknowledging their performance in the next team meeting to boost morale.
</div>
<div class="tips-card medium">
<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.
</div>
</div>
<div>
<h3>Project Progress</h3>
<div class="project-progress">
<p>Riverfront Commercial Complex<br>Aug 15, 2023 - Feb 28, 2025</p>
<p><strong>Overall Progress:</strong> 35%</p>
<div class="progress-bar">
<div class="progress-fill" style="width: 35%"></div>
</div>
<p><strong>Current Milestone:</strong> Structural Steel Erection (65% Complete)<br>Due: Dec 15, 2023</p>
</div>
<h3>Performance Metrics</h3>
<div class="metrics-grid">
<div class="metric-card">
<h4>Engagement</h4>
<div class="value">87%</div>
<p class="trend">Weekly Engagement Trend: High</p>
</div>
<div class="metric-card">
<h4>Completion</h4>
<div class="value">92%</div>
</div>
<div class="metric-card">
<h4>Stress</h4>
<div class="value">7 days</div>
</div>
</div>
<p>2 KPI Flags</p>
</div>
</div>
</div>
<!-- Reflections Section -->
<div class="section reflections-section" id="reflections-section" style="display: none;">
<h2>Reflection Journal</h2>
<p>Record daily reflections and insights to improve your leadership</p>
<h3>Add Daily Reflection</h3>
<div class="reflection-input">
<p>How are you feeling today?</p>
<div class="mood-buttons">
<button onclick="selectMood('Satisfied')">Satisfied</button>
<button onclick="selectMood('Motivated')">Motivated</button>
<button onclick="selectMood('Neutral')">Neutral</button>
<button onclick="selectMood('Concerned')">Concerned</button>
<button onclick="selectMood('Frustrated')">Frustrated</button>
</div>
<textarea id="reflection-input" placeholder="Share your thoughts on today’s progress, challenges, or learnings..."></textarea>
<button class="secondary" onclick="submitReflection()">Submit Reflection</button>
</div>
<h3>Reflection History</h3>
<div class="reflection-history" id="reflection-history">
<div class="entry">
<span class="date">Nov 15, 2023</span><span class="mood concerned">Concerned</span>
<p>Faced challenges with the concrete supplier today. Need to improve communication channels and possibly consider backup suppliers for critical phases.</p>
<p><strong>Learned:</strong> Always have contingency plans for key materials.</p>
</div>
<div class="entry">
<span class="date">Nov 14, 2023</span><span class="mood satisfied">Satisfied</span>
<p>Team excelled during the steel installation. The morning huddle approach is working well, setting daily priorities.</p>
<p><strong>Learned:</strong> Regular brief check-ins improve team alignment.</p>
</div>
<div class="entry">
<span class="date">Nov 13, 2023</span><span class="mood neutral">Neutral</span>
<p>Safety inspection identified several minor issues that were quickly addressed. Need to remind the team about proper ladder protocols.</p>
<p><strong>Learned:</strong> Regular safety reminders are necessary even for experienced workers.</p>
</div>
</div>
</div>
<!-- Reports Section -->
<div class="section reports-section" id="reports-section" style="display: none;">
<h2>Reports & Analytics</h2>
<p>Generate and download reports for your performance and project status</p>
<h3>Generate New Report</h3>
<div class="report-form">
<input type="text" placeholder="Enter report title" id="report-title">
<select id="report-type">
<option value="Weekly Summary">Weekly Summary</option>
<option value="Monthly Review">Monthly Review</option>
</select>
<div class="date-range">
<input type="date" id="start-date" value="2025-04-30">
<input type="date" id="end-date" value="2025-05-07">
</div>
<div>
<input type="checkbox" id="include-metrics" checked>
<label for="include-metrics">Performance metrics & KPIs</label>
</div>
<div>
<input type="checkbox" id="include-reflections" checked>
<label for="include-reflections">Daily reflections & learnings</label>
</div>
<button class="secondary" onclick="generateReport()">Generate Report</button>
</div>
<h3>Your Reports</h3>
<div class="report-list" id="report-list">
<div class="report-item">
<div>
<p>Weekly Performance Summary</p>
<p>Nov 12, 2023 • Weekly Summary</p>
<p>Completion: 92% • Milestones: 2 • Improvements: 3</p>
</div>
<div>
<span class="status">Generated</span>
<button onclick="downloadReport('weekly')">Download</button>
</div>
</div>
<div class="report-item">
<div>
<p>October Monthly Review</p>
<p>Nov 1, 2023 • Monthly Performance</p>
<p>Completion: 88% • Milestones: 4 • Improvements: 5</p>
</div>
<div>
<span class="status">Generated</span>
<button onclick="downloadReport('monthly')">Download</button>
</div>
</div>
</div>
</div>
<!-- Milestones Section -->
<div class="section milestones-section" id="milestones-section" style="display: none;">
<div class="milestones-header">
<div>
<h2>Project Milestones</h2>
<p>Track and update project milestones for Riverfront Commercial Complex</p>
</div>
<div>
<button class="secondary" onclick="syncSalesforce()">Sync with Salesforce</button>
<button onclick="addMilestone()">Add Milestone</button>
</div>
</div>
<div id="milestones-list">
<div class="milestone-item completed">
<div>
<p><strong>Foundation Completion</strong></p>
<p>Due: Oct 30, 2023</p>
<p>Complete site foundation work including footings, piers, and foundation walls</p>
<div class="progress-bar">
<div class="progress-fill" style="width: 100%"></div>
</div>
</div>
<span class="status completed">Completed</span>
</div>
<div class="milestone-item in-progress">
<div>
<p><strong>Structural Steel Erection</strong></p>
<p>Due: Dec 15, 2023</p>
<p>Erect the structural steel components for the main building frame</p>
<div class="progress-bar">
<div class="progress-fill" style="width: 65%"></div>
</div>
</div>
<span class="status in-progress">In Progress</span>
</div>
<div class="milestone-item not-started">
<div>
<p><strong>Building Envelope</strong></p>
<p>Due: Mar 1, 2024</p>
<p>Complete exterior walls, roofing, and weatherproofing</p>
<div class="progress-bar">
<div class="progress-fill" style="width: 0%"></div>
</div>
</div>
<span class="status not-started">Not Started</span>
</div>
<div class="milestone-item not-started">
<div>
<p><strong>MEP Rough-in</strong></p>
<p>Due: May 15, 2024</p>
<p>Complete mechanical, electrical, and plumbing rough-in work</p>
<div class="progress-bar">
<div class="progress-fill" style="width: 0%"></div>
</div>
</div>
<span class="status not-started">Not Started</span>
</div>
<div class="milestone-item not-started">
<div>
<p><strong>Interior Finishing</strong></p>
<p>Due: Oct 30, 2024</p>
<p>Complete all interior finishes including drywall, flooring, and fixtures</p>
<div class="progress-bar">
<div class="progress-fill" style="width: 0%"></div>
</div>
</div>
<span class="status not-started">Not Started</span>
</div>
</div>
</div>
<!-- Profile Section -->
<div class="section profile-section" id="profile-section" style="display: none;">
<h2>Profile & Settings</h2>
<p>Manage your profile and AI coaching preferences</p>
<h3>Supervisor Profile</h3>
<div class="profile-grid">
<div class="avatar">A</div>
<div class="profile-details">
<p><strong>Name:</strong> Alex Rivera</p>
<p><strong>Email:</strong> [email protected]</p>
<p><strong>Phone:</strong> (555) 123-4567</p>
<p><strong>Role:</strong> Senior Construction Supervisor</p>
<p><strong>Company:</strong> STPL Construction</p>
<p><strong>Experience:</strong> 12 years</p>
</div>
</div>
<h3>Coaching Preferences</h3>
<div class="preferences-form">
<div class="toggle">
<label>AI Coaching Notifications</label>
<input type="checkbox" id="notifications-toggle" checked>
</div>
<p>Receive push notifications for new coaching tips and checklist reminders</p>
<div>
<label>Coaching Frequency</label>
<select id="coaching-frequency">
<option value="Daily">Daily</option>
<option value="Weekly">Weekly</option>
</select>
</div>
<div>
<label>Preferred Time</label>
<select id="preferred-time">
<option value="Morning 6:00 AM">Morning 6:00 AM</option>
<option value="Evening 6:00 PM">Evening 6:00 PM</option>
</select>
</div>
<button onclick="savePreferences()">Save Preferences</button>
</div>
</div>
</div>
<!-- Toast Notifications -->
<div id="error" class="toast error"></div>
<div id="success" class="toast success"></div>
<script>
let supervisorData = {
supervisor_id: 'SUP_001',
role: 'Senior Construction Supervisor',
project_id: 'Riverfront_001',
milestones: [
{ name: 'Foundation Completion', status: 'Completed', progress: 100, due: '2023-10-30' },
{ name: 'Structural Steel Erection', status: 'In Progress', progress: 65, due: '2023-12-15' },
{ name: 'Building Envelope', status: 'Not Started', progress: 0, due: '2024-03-01' },
{ name: 'MEP Rough-in', status: 'Not Started', progress: 0, due: '2024-05-15' },
{ name: 'Interior Finishing', status: 'Not Started', progress: 0, due: '2024-10-30' }
],
reflection_log: '',
engagement_score: 87,
completion_rate: 92,
stress_days: 7
};
let coachingOutput = {
checklist: [
'Review safety equipment status for concrete pouring team',
'Verify delivery of steel reinforcement for floor 3',
'Coordinate with electrical contractor on conduit installation',
'Inspect temporary weather protection measures',
'Update project timeline based on foundation completion'
],
tips: [
'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.',
'Team Motivation: The concrete team has been exceeding expectations. Consider acknowledging their performance in the next team meeting to boost morale.',
'Schedule Optimization: Based on current pace, electrical work can begin 2 days earlier than planned. Consider adjusting the schedule to improve overall timeline.'
],
quote: 'Success is the sum of small efforts, repeated day in and day out.'
};
let reflectionHistory = [
{ 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.' },
{ 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.' },
{ 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.' }
];
let checklistProgress = 0;
let totalChecklistItems = coachingOutput.checklist.length;
let selectedMood = '';
// Toast Notification Function
function showToast(id, message) {
const toast = document.getElementById(id);
toast.textContent = message;
toast.classList.add('visible');
setTimeout(() => {
toast.classList.remove('visible');
}, 3000);
}
// Navigation
function showSection(section) {
document.querySelectorAll('.section').forEach(s => s.style.display = 'none');
document.getElementById(`${section}-section`).style.display = 'block';
document.querySelectorAll('.sidebar a').forEach(a => a.classList.remove('active'));
document.querySelector(`.sidebar a[href="#${section}"]`).classList.add('active');
}
// Checklist
function markComplete(index, checkbox) {
const itemDiv = checkbox.parentElement;
if (checkbox.checked) {
itemDiv.classList.add('completed');
} else {
itemDiv.classList.remove('completed');
}
updateChecklistProgress();
showToast('success', `Checklist item ${index + 1} marked as ${checkbox.checked ? 'complete' : 'incomplete'}.`);
}
function updateChecklistProgress() {
const completedItems = document.querySelectorAll('#checklist-items input:checked').length;
checklistProgress = totalChecklistItems > 0 ? (completedItems / totalChecklistItems) * 100 : 0;
}
// Reflections
function selectMood(mood) {
selectedMood = mood;
document.querySelectorAll('.mood-buttons button').forEach(btn => btn.classList.remove('active'));
document.querySelector(`.mood-buttons button[onclick="selectMood('${mood}')"]`).classList.add('active');
}
async function submitReflection() {
const reflectionInput = document.getElementById('reflection-input').value.trim();
if (!reflectionInput) {
showToast('error', 'Please enter a reflection before submitting.');
return;
}
if (!selectedMood) {
showToast('error', 'Please select a mood before submitting.');
return;
}
try {
const response = await fetch('/submit_reflection', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ reflection: reflectionInput, mood: selectedMood })
});
const result = await response.json();
if (result.status === 'success') {
supervisorData.reflection_log = reflectionInput;
reflectionHistory.unshift({
date: new Date().toLocaleString(),
mood: selectedMood,
text: reflectionInput,
learned: 'To be analyzed by AI...'
});
updateReflectionHistory();
document.getElementById('reflection-input').value = '';
selectedMood = '';
document.querySelectorAll('.mood-buttons button').forEach(btn => btn.classList.remove('active'));
showToast('success', 'Reflection submitted successfully.');
} else {
showToast('error', result.message);
}
} catch (error) {
showToast('error', 'Error submitting reflection: ' + error.message);
}
}
function updateReflectionHistory() {
const historyDiv = document.getElementById('reflection-history');
historyDiv.innerHTML = '';
if (reflectionHistory.length > 0) {
reflectionHistory.forEach(ref => {
const entryDiv = document.createElement('div');
entryDiv.className = 'entry';
entryDiv.innerHTML = `
<span class="date">${ref.date}</span><span class="mood ${ref.mood.toLowerCase()}">${ref.mood}</span>
<p>${ref.text}</p>
<p><strong>Learned:</strong> ${ref.learned}</p>
`;
historyDiv.appendChild(entryDiv);
});
} else {
historyDiv.innerHTML = '<p>No reflections yet. Start logging your thoughts!</p>';
}
}
// Reports
async function generateReport() {
const title = document.getElementById('report-title').value.trim();
const type = document.getElementById('report-type').value;
const startDate = document.getElementById('start-date').value;
const endDate = document.getElementById('end-date').value;
const includeMetrics = document.getElementById('include-metrics').checked;
const includeReflections = document.getElementById('include-reflections').checked;
if (!title) {
showToast('error', 'Please enter a report title.');
return;
}
try {
const response = await fetch('/generate_pdf', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title,
type,
startDate,
endDate,
includeMetrics,
includeReflections,
checklist: coachingOutput?.checklist || [],
tips: coachingOutput?.tips || [],
milestones: supervisorData?.milestones || [],
reflections: reflectionHistory
})
});
const result = await response.json();
if (result.status === 'success') {
const reportList = document.getElementById('report-list');
const reportItem = document.createElement('div');
reportItem.className = 'report-item';
reportItem.innerHTML = `
<div>
<p>${title}</p>
<p>${new Date().toLocaleDateString()}${type}</p>
<p>Completion: ${supervisorData.completion_rate}% • Milestones: ${supervisorData.milestones.length} • Improvements: ${reflectionHistory.length}</p>
</div>
<div>
<span class="status">Generated</span>
<button onclick="downloadReport('${title}')">Download</button>
</div>
`;
reportList.prepend(reportItem);
showToast('success', 'Report generated successfully.');
} else {
showToast('error', result.message || 'Failed to generate report.');
}
} catch (error) {
showToast('error', 'Error generating report: ' + error.message);
}
}
async function downloadReport(title) {
showToast('success', `Downloading report: ${title}`);
}
// Milestones
async function syncSalesforce() {
try {
const response = await fetch('/sync_salesforce', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (result.status === 'success') {
supervisorData.milestones = result.data.milestones;
updateMilestones();
showToast('success', 'Milestones synced with Salesforce.');
} else {
showToast('error', result.message);
}
} catch (error) {
showToast('error', 'Error syncing with Salesforce: ' + error.message);
}
}
async function addMilestone() {
const name = prompt('Enter milestone name:');
const due = prompt('Enter due date (YYYY-MM-DD):');
if (name && due) {
supervisorData.milestones.push({
name,
status: 'Not Started',
progress: 0,
due
});
updateMilestones();
showToast('success', 'Milestone added successfully.');
} else {
showToast('error', 'Please provide both name and due date.');
}
}
function updateMilestones() {
const milestonesDiv = document.getElementById('milestones-list');
milestonesDiv.innerHTML = '';
if (supervisorData.milestones?.length > 0) {
supervisorData.milestones.forEach(milestone => {
const milestoneDiv = document.createElement('div');
milestoneDiv.className = `milestone-item ${milestone.status.toLowerCase().replace(' ', '-')}`;
milestoneDiv.innerHTML = `
<div>
<p><strong>${milestone.name}</strong></p>
<p>Due: ${milestone.due}</p>
<p>${milestone.description || ''}</p>
<div class="progress-bar">
<div class="progress-fill" style="width: ${milestone.progress}%"></div>
</div>
</div>
<span class="status ${milestone.status.toLowerCase().replace(' ', '-')}">${milestone.status}</span>
`;
milestonesDiv.appendChild(milestoneDiv);
});
} else {
milestonesDiv.innerHTML = '<p>No milestones available.</p>';
}
}
// Profile
async function savePreferences() {
const notifications = document.getElementById('notifications-toggle').checked;
const frequency = document.getElementById('coaching-frequency').value;
const time = document.getElementById('preferred-time').value;
try {
const response = await fetch('/save_preferences', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ notifications, frequency, time })
});
const result = await response.json();
if (result.status === 'success') {
showToast('success', 'Preferences saved successfully.');
} else {
showToast('error', result.message);
}
} catch (error) {
showToast('error', 'Error saving preferences: ' + error.message);
}
}
// Initialize
window.onload = () => {
updateChecklistProgress();
updateReflectionHistory();
updateMilestones();
};
</script>
</body>
</html>